如何调用Windows自带的绘图软件将bmp图片转换为单色位图

问题描述 投票:0回答:1

如何调用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保存为单色位图?

c# windows visual-studio winforms paint
1个回答
0
投票

有很多方法可以进行颜色转换。如果您只需要处理特定的源和目标格式,并且可以处理不安全的代码,那么自己做并不难:

        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

© www.soinside.com 2019 - 2024. All rights reserved.