如何调用Windows自带的绘图软件将bmp图片转换为单色位图
最近我在写一个标签设计软件,但是我生成的bmp文件永远无法使用标签打印机打印。这是我使用的代码:
private void button3_Click(object sender, EventArgs e)
{
Bitmap bmp = new Bitmap(panel1.Width, panel1.Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
panel1.DrawToBitmap(bmp, new Rectangle(0, 0, panel1.Width, panel1.Height));
//Bitmap bmpIndexed = new Bitmap(bmp.Width, bmp.Height, System.Drawing.Imaging.PixelFormat.Format1bppIndexed);
bmp.Save("led1.bmp", System.Drawing.Imaging.ImageFormat.Bmp);
bmp.Dispose();
//bmpIndexed.Dispose();
ResizeBmp("led1.bmp");
paint();
}
private void ResizeBmp(string path)
{
//Load images
Image originalImage = Image.FromFile(path);
// new size
int newWidth = 192;
int newHeight = 168;
//Create a new Bitmap object to store the resized image
Bitmap resizedImage = new Bitmap(newWidth, newHeight);
//Create a Graphics object for manipulating images
using (Graphics g = Graphics.FromImage(resizedImage))
{
//Set interpolation mode to preserve image quality
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
// Draw the resized image
g.DrawImage(originalImage, 0, 0, newWidth, newHeight);
}
//// Convert the resized image to black and white
//Bitmap monoImage = ConvertToMonochrome(resizedImage);
// Save the resized image to a file
ConvertTo1Bit(resizedImage).Save("led.bmp");
// Release resources
originalImage.Dispose();
resizedImage.Dispose();
//monoImage.Dispose();
//newbitmap.Dispose();
File.Delete("led1.bmp");
}
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;
}
是的,正如代码所示,这个标签设计软件只能打印单色bmp,所以我将bmp图像转换为单色bmp,但这仍然不起作用。
经过两天的不断尝试,我找到了问题所在。我用Windows自带的绘图软件,把bmp1放进去保存为单色位图,图片打印成功了。
所以我这里的重点是知道如何直接调用Windows自带的绘图软件,将bmp保存为单色位图?
有很多方法可以进行颜色转换。如果您只需要处理特定的源和目标格式,并且可以处理不安全的代码,那么自己做并不难:
public static unsafe Bitmap Bgr24ToGrayscale8(Bitmap bmp)
{
if (bmp.PixelFormat != PixelFormat.Format24bppRgb)
throw new InvalidOperationException("invalid pixelformat");
var bytesPerPixel = 3;
var sourceData = bmp.LockBits(
new Rectangle(0, 0, bmp.Width, bmp.Height),
ImageLockMode.ReadOnly,
bmp.PixelFormat);
var height = bmp.Height;
var width = bmp.Width;
var result = new Bitmap(bmp.Width, bmp.Height, PixelFormat.Format8bppIndexed);
var resultData = result.LockBits(
new Rectangle(0, 0, bmp.Width, bmp.Height),
ImageLockMode.ReadWrite,
result.PixelFormat);
try
{
var sourceStride = sourceData.Stride;
var targetStride = resultData.Stride;
var targetPtr = (byte*)resultData.Scan0;
var sourcePtr = (byte*)sourceData.Scan0;
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
// Do the actual conversion
var i = y * sourceStride + x * bytesPerPixel;
var value = (byte)(sourcePtr[i + 0] * 0.11f + sourcePtr[i + 1] * 0.59f + sourcePtr[i + 2] * 0.3f);
targetPtr[y * targetStride + x] = value;
}
}
}
finally
{
bmp.UnlockBits(sourceData);
result.UnlockBits(resultData);
}
return result;
}
虽然这看起来有很多代码,但其中大部分都是用于访问像素数据指针的样板。内部循环简单地获取每个颜色像素,计算等效的灰度值。这些常数旨在补偿眼睛对不同颜色的不同敏感度。
如果您需要更复杂的转换,您可能需要查看一些图像处理库,例如Magic.Net。