static Bitmap convert(Bitmap Src) { if (Src.PixelFormat != PixelFormat.Format8bppIndexed) { throw (new Exception()); } ColorPalette palette = Src.Palette; Bitmap Dst = new Bitmap(Src.Width, Src.Height, PixelFormat.Format32bppArgb); BitmapData SrcData = Src.LockBits(new Rectangle(0, 0, Src.Width, Src.Height), ImageLockMode.ReadOnly, Src.PixelFormat); BitmapData DstData = Dst.LockBits(new Rectangle(0, 0, Dst.Width, Dst.Height), ImageLockMode.WriteOnly, Dst.PixelFormat); IntPtr SrcAdr = SrcData.Scan0; IntPtr DstAdr = DstData.Scan0; for(int y = 0; y < Src.Height; y++) { for(int x = 0; x < Src.Width; x++) { Color color; { int pos = x + SrcData.Stride * y; byte index = Marshal.ReadByte(SrcAdr, pos); color = palette.Entries[index]; } { int pos = x * 4 + DstData.Stride * y; Marshal.WriteByte(DstAdr, pos + 0, color.B); Marshal.WriteByte(DstAdr, pos + 1, color.G); Marshal.WriteByte(DstAdr, pos + 2, color.R); Marshal.WriteByte(DstAdr, pos + 3, color.A); } } } Src.UnlockBits(SrcData); Dst.UnlockBits(DstData); return (Dst); }
コードを読めばわかると思うが、入力はFormat8bppIndexedのみで、出力はFormat32bppArgbとなる。違うフォーマットに対応するには2段forをそれぞれに作る必要があり、FormatNNに対応するだけでも少なくとも196種類の分岐が必要となる。さすがに使う用もないのに実装するのも面倒なので今回は8bppIndexedから32bppArgbのみの実装とした。
ピクセルフォーマットの変換って地味に重要なのでC#に付属してても良さそうな気がするんだけど。特に8bppは今でも使われる部分はあるだろうし、Grapicsに使うには8bppは不可だし。
Bitmap.Clone でフォーマットを指定すると、32bppArgbに変換できますよ!
返信削除https://docs.microsoft.com/ja-jp/dotnet/api/system.drawing.bitmap.clone?view=dotnet-plat-ext-3.1