--- nono/lib/bitmap.cpp 2026/04/29 17:05:08 1.1.1.1 +++ nono/lib/bitmap.cpp 2026/04/29 17:05:12 1.1.1.2 @@ -113,9 +113,8 @@ BitmapI8::BitmapI8(int width_, int heigh // コンストラクタ BitmapI8::BitmapI8(const void *buf_, int width_, int height_) - : inherited(width_, height_, 8) { - buf = static_cast(const_cast(buf_)); + Create(buf_, width_, height_); } // デストラクタ @@ -133,6 +132,15 @@ BitmapI8::Create(int width_, int height_ buf = owned_buf.get(); } +// 元データを指定して作成 +void +BitmapI8::Create(const void *buf_, int width_, int height_) +{ + inherited::Create(width_, height_, 8); + + buf = static_cast(const_cast(buf_)); +} + // カラーコード cc で全体を塗りつぶす。 // 未使用ビットも変更される。 void @@ -220,6 +228,15 @@ BitmapRGB::DrawBitmap(int dx, int dy, co } } +// (dx, dy) にビットマップ src の全域を描画する。 +// 描画範囲をはみ出さないこと。 +void +BitmapRGB::DrawBitmap(int dx, int dy, const BitmapI8& src, const Color *palette) +{ + Rect sr(0, 0, src.GetWidth(), src.GetHeight()); + DrawBitmap(dx, dy, src, palette, sr); +} + // (dx, dy) にビットマップ src の範囲 sr を描画する。 // 描画範囲をはみ出さないこと。 void @@ -291,6 +308,74 @@ BitmapRGB::DrawScaleUp(int dx, int dy, i } } +// 分数で表現可能な拡大縮小描画。 +// dr にビットマップ src の (sxN / sxD, syN / syD) からを +// dst の 1 ピクセルに対して (sxS / sxD, syS / syD) ずつ動かした位置を +// 読み出し位置として描画する。 +// 描画範囲をはみ出さないこと。 +void +BitmapRGB::DrawScale(const Rect& dr, const BitmapI8& src, const Color *palette, + int sxN, int sxD, int sxS, int syN, int syD, int syS) +{ + assert(buf); + assert(sxD >= 1); + assert(syD >= 1); + assert(sxS != 0); + assert(syS != 0); + + int sxI = sxN / sxD; + int syI = syN / syD; + + sxN %= sxD; + syN %= syD; + + int sxI0 = sxI; + int sxN0 = sxN; + + int sx; + int sy = syI - 1; + + for (int y = 0; y < dr.h; y++) { + uint8 *d = GetPtr(dr.x, dr.y + y); + + if (sy != syI) { + sy = syI; + + sx = sxI0 - 1; + sxI = sxI0; + sxN = sxN0; + + uint8 cc = 0; + for (int x = 0; x < dr.w; x++) { + if (sx != sxI) { + sx = sxI; + const uint8 *s = src.GetPtr(sx, sy); + cc = *s; + } + const Color& c = palette[cc]; + *d++ = c.r; + *d++ = c.g; + *d++ = c.b; + + sxN += sxS; + if (sxN >= sxD) { + sxI += sxN / sxD; + sxN %= sxD; + } + } + } else { + // 前のラスタの中からコピーすればよい + memcpy(d, d - stride, dr.w * 3); + } + + syN += syS; + if (syN >= syD) { + syI += syN / syD; + syN %= syD; + } + } +} + // sr 範囲の色の平均を返す Color BitmapRGB::Mean(const RectD& sr) const