久久久久久久av_日韩在线中文_看一级毛片视频_日本精品二区_成人深夜福利视频_武道仙尊动漫在线观看

將位圖轉(zhuǎn)換為單色

Converting a bitmap to monochrome(將位圖轉(zhuǎn)換為單色)
本文介紹了將位圖轉(zhuǎn)換為單色的處理方法,對大家解決問題具有一定的參考價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧!

問題描述

我正在嘗試將圖像保存為單色(黑白,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 開始并轉(zhuǎn)換為位圖進行打印(它是熱敏打印機,無論如何只支持黑色 - 如果我嘗試將它們作為彩色/灰度發(fā)送,它對于大圖像的速度會很慢).

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

到目前為止,我的代碼將其轉(zhuǎn)換為位圖非常簡單,但它保留了原始顏色深度.

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

推薦答案

這是我放在一起的一些代碼,它采用全彩色(24 位/像素)圖像,并將其轉(zhuǎn)換為 1 位/像素輸出位圖,應(yīng)用標(biāo)準(zhǔn) RGB 到灰度轉(zhuǎn)換,然后使用 Floyd-Steinberg 將灰度轉(zhuǎn)換為 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.

請注意,這絕不應(yīng)該被視為理想"的實現(xiàn),但它確實有效.如果您愿意,可以應(yīng)用許多改進.例如,它將整個輸入圖像復(fù)制到 data 數(shù)組中,而我們實際上只需要在內(nèi)存中保留兩行(當(dāng)前"和下一個"行)來累積錯誤數(shù)據(jù).盡管如此,性能似乎還可以接受.

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

這篇關(guān)于將位圖轉(zhuǎn)換為單色的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網(wǎng)!

【網(wǎng)站聲明】本站部分內(nèi)容來源于互聯(lián)網(wǎng),旨在幫助大家更快的解決問題,如果有圖片或者內(nèi)容侵犯了您的權(quán)益,請聯(lián)系我們刪除處理,感謝您的支持!

相關(guān)文檔推薦

Right-click on a Listbox in a Silverlight 4 app(右鍵單擊 Silverlight 4 應(yīng)用程序中的列表框)
WPF c# webbrowser scrolls over top menu(WPF c# webbrowser 在頂部菜單上滾動)
C# Console app - How do I make an interactive menu?(C# 控制臺應(yīng)用程序 - 如何制作交互式菜單?)
How to avoid duplicate form creation in .NET Windows Forms?(如何避免在 .NET Windows Forms 中創(chuàng)建重復(fù)的表單?)
UI Automation Control Desktop Application and Click on Menu Strip(UI自動化控制桌面應(yīng)用程序并單擊菜單條)
Removing thin border around the menuitems(刪除菜單項周圍的細邊框)
主站蜘蛛池模板: 欧美成人免费视频 | 538精品视频 | 福利网站在线观看 | 成人午夜又粗又硬又大 | 日韩天堂av | 91视频在线观看免费 | 日韩免费观看视频 | 欧美视频一区二区三区 | 国产黄色精品视频 | 久久久香蕉 | 日韩中文字幕一区二区三区 | avxxxxx| 精品国产一区二区在线观看 | 中国黄色1级片 | 国产精品国产精品国产专区不片 | 麻豆成人91精品二区三区 | 能看毛片的网站 | 日日夜夜精品视频免费 | 日韩在线视频一区二区三区 | 成人看片网站 | 国产超碰在线 | 亚洲免费精品 | 成人黄色在线观看 | 国产精品欧美在线 | 日韩黄色免费视频 | 一区二区美女 | av在线一区二区 | 亚洲黄色片 | 日韩免费一区二区 | 精品日韩一区二区三区 | 天天爽夜夜操 | 一区二区三区在线免费 | 免费成人毛片 | 黄色av免费在线观看 | 香蕉视频一区二区 | 国产乱码久久久久久 | 成人在线黄色 | 中文字幕2021 | 一级毛片大全 | 手机看片福利视频 | 国产一级片在线 |