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