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

How can I save an image as Bitmap Image File?

我做了一个自动图像阈值功能,想把它保存为位图文件。

但是,当我使用C# GDI+Bitmap.Save功能时,虽然我将ImageFormat设置为BMP,但它始终是RGB彩色图像文件而不是位图图像文件。

我必须将它保存为位图图像文件,因为打印机只能读取位图图像文件。

也许你会问我位图图像文件是什么。我不是图像处理专家,很抱歉很难解释清楚。但是我可以举个例子:在Photoshop中,有几种颜色模式,比如RGB mode/CMYK mode/Index mode/Grayscale mode/Bitmap 模式,我想将图像保存为Bitmap C#中的模式。

这是 Adobe explain about the Bitmap mode in their website

Bitmap mode uses one of two color values (black or white) to represent the pixels in an image. Images in Bitmap mode are called bitmapped 1‑bit images because they have a bit depth of 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();

要将 BMP 对象保存到文件,您只需这样做:

bmp.Save("c:\Path\To\File\image.bmp, ImageFormat.Bmp);

你还有别的事吗?

我相信 OP 指的是此 adobe link 中的最后一种图像 位图只是数据的容器,您存储的数据格式由 PixelFormat 设置定义。可以看出"Adobe"Bitmap模式是2色格式模式,对应C#Bitmap中的PixelFormat.Format1bppIndexed

您有几个以 PixelFormat 作为参数的位图构造函数。

1.

public Bitmap (int width, int height, System.Drawing.Imaging.PixelFormat format);

2.

public Bitmap (int width, int height, int stride, System.Drawing.Imaging.PixelFormat format, IntPtr scan0);

您的源图像是 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 class 只是设置图像的类型,如 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:[=13=]01.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!");

请注意输出略有不同。 这是输出的一些测试样本。

这是我的输入图像:

使用阈值代码输出图像:

并且仅使用克隆方法输出图像: