PixelFormatにFormat8bppIndexedというフォーマットがありました。8bppですので8bitのグレースケールを扱うフォーマットだと思われますので試してみたいと思います。
元画像(カラー)
ソースコード
namespace RGBtoGray;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
public partial class Form1 : Form
{
static Bitmap RGB2Gray(Bitmap color)
{
int width = color.Width;
int height = color.Height;
// Format8bppIndexed
var gray = new Bitmap(width, height, PixelFormat.Format8bppIndexed);
var rect = new Rectangle(0, 0, width, height);
var cData = color.LockBits(rect, ImageLockMode.ReadOnly, color.PixelFormat);
int channel = Bitmap.GetPixelFormatSize(color.PixelFormat) / 8;
var cStride = Math.Abs(cData.Stride);
byte[] cPixels = new byte[cStride * height];
Marshal.Copy(cData.Scan0, cPixels, 0, cPixels.Length);
var gData = gray.LockBits(rect, ImageLockMode.ReadWrite, gray.PixelFormat);
var gStride = Math.Abs(gData.Stride);
byte[] gPixels = new byte[gStride * height];
for (int y = 0; y<height; y++)
{
int ci = cStride * y;
int gi = gStride * y;
for (int x = 0; x < width; x++)
{
gPixels[gi + x] = cPixels[ci + x * channel];
}
}
Marshal.Copy(gPixels, 0, gData.Scan0, gPixels.Length);
color.UnlockBits(cData);
gray.UnlockBits(gData);
return gray;
}
public Form1()
{
InitializeComponent();
var src = new Bitmap(@"C:\Users\PC01114\Pictures\202211011619.PNG");
var dst = RGB2Gray(src);
var picbox = new PictureBox
{
Image = dst,
Dock = DockStyle.Fill,
};
Controls.Add(picbox);
}
}
結果
カラー画像の1チャンネル分から8bit画像を生成したのでグレースケールで表示されることを期待したのですが、色がついています。それもなかなかユニークな色使いです。
調べたところパレットを設定していないため、このような色になっているようです。
プログラムを修正してみます。
namespace RGBtoGray;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
public partial class Form1 : Form
{
static Bitmap RGB2Gray(Bitmap color)
{
int width = color.Width;
int height = color.Height;
// Format8bppIndexed
var gray = new Bitmap(width, height, PixelFormat.Format8bppIndexed);
var rect = new Rectangle(0, 0, width, height);
var cData = color.LockBits(rect, ImageLockMode.ReadOnly, color.PixelFormat);
int channel = Bitmap.GetPixelFormatSize(color.PixelFormat) / 8;
var cStride = Math.Abs(cData.Stride);
byte[] cPixels = new byte[cStride * height];
Marshal.Copy(cData.Scan0, cPixels, 0, cPixels.Length);
var gData = gray.LockBits(rect, ImageLockMode.ReadWrite, gray.PixelFormat);
var gStride = Math.Abs(gData.Stride);
byte[] gPixels = new byte[gStride * height];
for (int y = 0; y<height; y++)
{
int ci = cStride * y;
int gi = gStride * y;
for (int x = 0; x < width; x++)
{
gPixels[gi + x] = cPixels[ci + x * channel];
}
}
Marshal.Copy(gPixels, 0, gData.Scan0, gPixels.Length);
color.UnlockBits(cData);
gray.UnlockBits(gData);
// パレットの設定
var pallet = gray.Palette;
for(int i = 0; i < 255; i++)
{
pallet.Entries[i] = Color.FromArgb(i, i, i);
}
gray.Palette = pallet;
return gray;
}
public Form1()
{
InitializeComponent();
var src = new Bitmap(@"C:\Users\PC01114\Pictures\202211011619.PNG");
var dst = RGB2Gray(src);
dst.Save(@"c:\output.png", ImageFormat.Png);
var picbox = new PictureBox
{
Image = dst,
Dock = DockStyle.Fill,
};
Controls.Add(picbox);
}
}
結果
パレットを設定したところグレースケールになりました。ちなみに画像をファイルに保存しプロパティを見たところ8bitで保存されていました。
コメント