• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

位图转换为单色

用户头像
it1352
帮助15

问题说明

我正在尝试将图像保存为单色(黑白,1 位深度),但我不知道该怎么做.

I am trying to save an image as monochrome (black&white, 1 bit-depth) but I'm coming up lost how to do it.

我从 png 开始并转换为位图进行打印(它是热敏打印机,无论如何只支持黑色 - 如果我尝试将它们作为彩色/灰度发送,它对于大图像的速度会很慢).

I am starting with a png and converting to a bitmap for printing (it's a thermal printer and only supports black anyway - plus its slow as hell for large images if I try to send them as color/grayscale).

到目前为止,我的代码将其转换为位图非常简单,但它保留了原始颜色深度.

My code so far is dead simple to convert it to a bitmap, but it is retaining the original colour depth.

Image image = Image.FromFile("C:\test.png");

byte[] bitmapFileData = null;
int bitsPerPixel = 1;
int bitmapDataLength;

using (MemoryStream str = new MemoryStream())
{
    image.Save(str, ImageFormat.Bmp);
    bitmapFileData = str.ToArray();
}

正确答案

#1

这是我放在一起的一些代码,它采用全彩色(24 位/像素)图像,并将其转换为 1 位/像素输出位图,应用标准 RGB 到灰度转换,然后使用 Floyd-Steinberg 将灰度转换为 1 位/像素输出.

Here's some code I put together that takes a full colour (24 bits/pixel) image, and converts it to a 1 bit/pixel output bitmap, applying a standard RGB to greyscale conversion, and then using Floyd-Steinberg to convert greyscale to the 1 bit/pixel output.

请注意,这绝不应该被视为理想"的实现,但它确实有效.如果您愿意,可以应用许多改进.例如,它将整个输入图像复制到 data 数组中,而我们实际上只需要在内存中保留两行(当前"和下一个"行)来累积错误数据.尽管如此,性能似乎还可以接受.

Note that this should by no means be considered an "ideal" implementation, but it does work. There are a number of improvements that could be applied if you wanted. For example, it copies the entire input image into the data array, whereas we really only need to keep two lines in memory (the "current" and "next" lines) for accumulating the error data. Despite this, performance seems acceptable.

public static Bitmap ConvertTo1Bit(Bitmap input)
{
    var masks = new byte[] { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
    var output = new Bitmap(input.Width, input.Height, PixelFormat.Format1bppIndexed);
    var data = new sbyte[input.Width, input.Height];
    var inputData = input.LockBits(new Rectangle(0, 0, input.Width, input.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
    try
    {
        var scanLine = inputData.Scan0;
        var line = new byte[inputData.Stride];
        for (var y = 0; y < inputData.Height; y  , scanLine  = inputData.Stride)
        {
            Marshal.Copy(scanLine, line, 0, line.Length);
            for (var x = 0; x < input.Width; x  )
            {
                data[x, y] = (sbyte)(64 * (GetGreyLevel(line[x * 3   2], line[x * 3   1], line[x * 3   0]) - 0.5));
            }
        }
    }
    finally
    {
        input.UnlockBits(inputData);
    }
    var outputData = output.LockBits(new Rectangle(0, 0, output.Width, output.Height), ImageLockMode.WriteOnly, PixelFormat.Format1bppIndexed);
    try
    {
        var scanLine = outputData.Scan0;
        for (var y = 0; y < outputData.Height; y  , scanLine  = outputData.Stride)
        {
            var line = new byte[outputData.Stride];
            for (var x = 0; x < input.Width; x  )
            {
                var j = data[x, y] > 0;
                if (j) line[x / 8] |= masks[x % 8];
                var error = (sbyte)(data[x, y] - (j ? 32 : -32));
                if (x < input.Width - 1) data[x   1, y]  = (sbyte)(7 * error / 16);
                if (y < input.Height - 1)
                {
                    if (x > 0) data[x - 1, y   1]  = (sbyte)(3 * error / 16);
                    data[x, y   1]  = (sbyte)(5 * error / 16);
                    if (x < input.Width - 1) data[x   1, y   1]  = (sbyte)(1 * error / 16);
                }
            }
            Marshal.Copy(line, 0, scanLine, outputData.Stride);
        }
    }
    finally
    {
        output.UnlockBits(outputData);
    }
    return output;
}

public static double GetGreyLevel(byte r, byte g, byte b)
{
    return (r * 0.299   g * 0.587   b * 0.114) / 255;
}

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /reply/detail/tangicbak
系列文章
更多 icon
同类精品
更多 icon
继续加载