我做了一个自动图像阈值处理功能,想将其保存为位图文件。
但是,当我使用C# GDI+的Bitmap.Save
函数时,尽管我将ImageFormat设置为BMP,但它始终是RGB彩色图像文件,而不是位图图像文件。
我必须将其保存为打印机的位图图像文件,才能读取位图图像文件。
也许您会问我什么是位图图像文件。我不是图像处理专家,对此感到抱歉,很难解释清楚。但我可以举一个例子:在Photoshop中,有几种颜色模式,例如RGB模式/ CMYK模式/索引模式/灰度模式/位图模式,我想将图像保存为C#中的位图模式。
Adobe explain about the Bitmap mode in their website:
位图模式使用两个颜色值(黑色或白色)之一来表示图像中的像素。在位图模式下,图像的位深度为1,因此称为位图1位图像。
我用谷歌搜索,但对此一无所获。如何在C#中做到这一点?谢谢。
这是我的代码:
Thread T = new Thread(() => {
Bitmap processedBitmap = new Bitmap(@"G:\\0001.jpg");
BitmapData bitmapData = processedBitmap.LockBits(new Rectangle(0, 0, processedBitmap.Width, processedBitmap.Height), ImageLockMode.ReadWrite, processedBitmap.PixelFormat);
int bytesPerPixel = Bitmap.GetPixelFormatSize(processedBitmap.PixelFormat) / 8;
int byteCount = bitmapData.Stride * processedBitmap.Height;
byte[] pixels = new byte[byteCount];
IntPtr ptrFirstPixel = bitmapData.Scan0;
Marshal.Copy(ptrFirstPixel, pixels, 0, pixels.Length);
int heightInPixels = bitmapData.Height;
int widthInBytes = bitmapData.Width * bytesPerPixel;
for (int y = 0; y < heightInPixels; y++)
{
int currentLine = y * bitmapData.Stride;
for (int x = 0; x < widthInBytes; x = x + bytesPerPixel)
{
int oldBlue = pixels[currentLine + x];
int oldGreen = pixels[currentLine + x + 1];
int oldRed = pixels[currentLine + x + 2];
double averageColor = (oldBlue + oldGreen + oldRed) / 3;
int NewC;
if (averageColor > 200)
{
NewC = 255;
}
else
{
NewC = 0;
}
// calculate new pixel value
pixels[currentLine + x] = (byte)NewC;
pixels[currentLine + x + 1] = (byte)NewC;
pixels[currentLine + x + 2] = (byte)NewC;
}
}
// copy modified bytes back
Marshal.Copy(pixels, 0, ptrFirstPixel, pixels.Length);
processedBitmap.UnlockBits(bitmapData);
processedBitmap.Save("G:\\aaa.bmp", ImageFormat.Bmp);
MessageBox.Show("Sucess!");
});
T.Start();
答案 0 :(得分:2)
我认为OP引用的是此adobe link中的最后一种图像 位图仅仅是数据的容器,存储的数据格式由PixelFormat设置定义。可以看出,“ Adobe”位图模式是2色格式模式,对应于C#位图中的PixelFormat.Format1bppIndexed。
您有一些用于Bitmap的构造函数,这些构造函数以PixelFormat作为参数。
// Return table to the loaded data order
table.order.neutral().draw();
public Bitmap (int width, int height, System.Drawing.Imaging.PixelFormat format);
答案 1 :(得分:2)
使用源图像,您将获得24位图像。 进行颜色平均时,将使用以下代码写回图像缓冲区:
pixels[currentLine + x] = (byte)NewC;
pixels[currentLine + x + 1] = (byte)NewC;
pixels[currentLine + x + 2] = (byte)NewC;
您要重新写回24位。
因此,例如,如果您的RGB原始值为(202,203,249),则NewC将为218,然后将其阈值设置为255,因此您写回(255,255,255)仍然是RGB值,这仅用于白色。
然后使用
processedBitmap.Save("G:\\aaa.bmp", ImageFormat.Bmp);
ImageFormat类仅设置图像的类型,例如jpeg,png等。 正如您所发现的,您仍在输出24位图像。
因此,您想要将图像保存为每像素黑白图像纯1位。 为此,您需要指定要保存的图像的 PixelFormat ,特别是想要PixelFormat Format1bppIndexed。
如果您改为将代码的相关位更改为:
...
Marshal.Copy(pixels, 0, ptrFirstPixel, pixels.Length);
processedBitmap.UnlockBits(bitmapData);
Bitmap clone = processedBitmap.Clone(new Rectangle(0, 0, processedBitmap.Width, processedBitmap.Height), PixelFormat.Format1bppIndexed);
clone.Save("G:\\aaa.bmp", ImageFormat.Bmp);
MessageBox.Show("Success!");
现在您的输出克隆将是一个1bpp的图像。
但是,您可以进一步简化代码,因为此克隆功能实际上可以为您完成所有工作,并且可以将代码缩减为以下内容。
Bitmap processedBitmap = new Bitmap(@"G:\0001.jpg");
Bitmap clone = processedBitmap.Clone(new Rectangle(0, 0, processedBitmap.Width, processedBitmap.Height), PixelFormat.Format1bppIndexed);
clone.Save("G:\\aaa.bmp", ImageFormat.Bmp);
MessageBox.Show("Success!");
请注意,尽管输出略有不同。 这是输出的一些测试样本。
这是我的输入图片:
输出带有阈值代码的图像:
并仅使用克隆方法输出图像:
答案 2 :(得分:0)
要将BMP对象保存到文件中,您需要执行以下操作:
bmp.Save("c:\\Path\\To\\File\\image.bmp, ImageFormat.Bmp);
您还在做其他事情吗?