下面是一些代碼,我把它放在一起,需要全綵色(24位/像素)圖像,並將其轉換爲1位/像素輸出位圖,應用標準RGB灰度轉換,然後使用Floyd-Steinberg將灰度轉換爲1位/像素輸出。
請注意,這絕不應被視爲「理想」實現,但它確實有效。如果您願意,可以應用一些改進措施。例如,它將整個輸入圖像複製到data
數組中,而我們實際上只需要在內存中保留兩行(「當前」和「下一行」)來累積錯誤數據。儘管如此,表現似乎可以接受。
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;
}
http://stackoverflow.com/questions/4669317/how-to-convert-a-bitmap-image-to-black-and-white-in-c – Dmitriy 2012-07-13 14:36:00
的[轉換圖像黑色可能重複 - 白色或棕褐色在c#](http://stackoverflow.com/questions/4624998/convert-image-to-black-white-or-sepia-in-c-sharp) – ken2k 2012-07-13 14:37:28
其實,在我看來,這些問題是關於轉換爲灰度 - 而OP想要將其轉換爲1 BPP單色,其中涉及閾值/抖動。 – Ani 2012-07-13 14:40:27