如何将图像另存为位图图像文件?

时间:2018-10-23 07:28:12

标签: c# gdi+

我做了一个自动图像阈值处理功能,想将其保存为位图文件。

但是,当我使用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();

3 个答案:

答案 0 :(得分:2)

我认为OP引用的是此adobe link中的最后一种图像 位图仅仅是数据的容器,存储的数据格式由PixelFormat设置定义。可以看出,“ Adob​​e”位图模式是2色格式模式,对应于C#位图中的PixelFormat.Format1bppIndexed

您有一些用于Bitmap的构造函数,这些构造函数以PixelFormat作为参数。

1.

// Return table to the loaded data order
  table.order.neutral().draw();

2.

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);

您还在做其他事情吗?