在Windows窗体中保存带有alpha通道的单色位图会保存不同的(错误的)颜色

本文关键字:保存 错误 颜色 位图 窗体 alpha Windows 通道 单色 | 更新日期: 2023-09-27 18:18:03

在c#, .NET 2.0, Windows Forms, Visual Studio Express 2010中,我保存了一个相同颜色的图像:

  Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb);
  using (Graphics graphics = Graphics.FromImage(bitmap))
  {
      Brush brush = new SolidBrush(color);
      graphics.FillRectangle(brush, 0, 0, width, height);
      brush.Dispose();
  }
  bitmap.Save("test.png");
  bitmap.Save("test.bmp");

如果我使用,例如

Color [A=153, R=193, G=204, B=17] or #C1CC11

保存图像后,在外部查看器(如Paint)中打开它。. NET, IrfanView, XNView等。我被告知图像的颜色实际上是:

Color [A=153, R=193, G=203, B=16] or #C1CB10

所以它是相似的颜色,但不一样!

我尝试了PNG和BMP保存。

当涉及到透明度(alpha)时,.NET保存不同的颜色!当alpha值为255(无透明度)时,它保存当前颜色

在Windows窗体中保存带有alpha通道的单色位图会保存不同的(错误的)颜色

感谢Joe和Hans Passant的评论。

是的,正如Joe所说,问题就在这条线上:

graphics.FillRectangle(brush, 0, 0, width, height);

这里GDI+用相似的颜色修改颜色,但不是完全相同的颜色。

似乎解决方案是直接在像素中写入颜色值,使用位图。锁位和元帅。复制:

        Bitmap bitmap = new Bitmap(this.currentSampleWidth, this.currentSampleHeight, PixelFormat.Format32bppArgb);
        // Lock the bitmap's bits.  
        Rectangle rect = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
        BitmapData bmpData = bitmap.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, bitmap.PixelFormat);
        // Get the address of the first line.
        IntPtr ptr = bmpData.Scan0;
        // Declare an array to hold the bytes of the bitmap (32 bits per pixel)
        int pixelsCount = bitmap.Width * bitmap.Height;
        int[] argbValues = new int[pixelsCount];
        // Copy the RGB values into the array.
        System.Runtime.InteropServices.Marshal.Copy(ptr, argbValues, 0, pixelsCount);
        // Set the color value for each pixel.
        for (int counter = 0; counter < argbValues.Length; counter++)
            argbValues[counter] = color.ToArgb();
        // Copy the RGB values back to the bitmap
        System.Runtime.InteropServices.Marshal.Copy(argbValues, 0, ptr, pixelsCount);
        // Unlock the bits.
        bitmap.UnlockBits(bmpData);
        return bitmap;

只是想添加一点。根据我的经验,最后一个代码片段可能会抛出运行时错误。这是因为位图中的argb值数组是这样存储的:[a1, b1, g1, r1, a2, b2, g2, r2, a3,…]等等,其中a, r, g, b都是整数。您应该在图像上运行一些测试用例,以查看数组中a、r、g、b值的确切位置。位图不一定保证这种顺序性(是的,即使在。net中)。

稍微重写一下:

   byte[] rgbValues1 = new byte[4];
                            System.Drawing.Imaging.BitmapData bpData =
                            bm.LockBits(new Rectangle(0,0,bm.Width,bm.Height),System.Drawing.Imaging.ImageLockMode.ReadWrite,
                            bm.PixelFormat);
                        int thisPixel = ptStart.X * 4 + ptStart.Y * bpData.Stride;
                        IntPtr px = bpData.Scan0 + thisPixel;
                        System.Runtime.InteropServices.Marshal.Copy(px, rgbValues1, 0, rgbValues1.Length);

                        rgbValues1[0] = (byte)(255);//blue channel
                        rgbValues1[1] = (byte)(0);//green channel
                        rgbValues1[2] = (byte)(0);//red channel
                        rgbValues1[3] = (byte)(127)//should be alpha channel
                        System.Runtime.InteropServices.Marshal.Copy(rgbValues1, 0, px, 4);
                        bm.UnlockBits(bpData);
这将设置单个像素为蓝色,透明度为50%(或者它应该)…