C#在另一个位图的alpha通道中复制位图的像素

我有两个位图,一个包含“普通”图像,另一个包含灰度图像。

我的目标只是将灰度图像放在第一个位图的alpha通道中,以便像面具一样使用灰度图像。

我已经看到了一些使用SetPixel来做到这一点的解决方案,但它很慢并且由于内存分配错误而在最终图像上创建了一些奇怪的工件。

因此,可能通过浏览原始位图中的所有像素并从Alpha通道中的灰度位图分配相应像素来实现此目的。 也许使用LockBits像素arrays?

所以我的问题是如何做到这一点? 我特别难以找到如何在alpha通道中分配像素以及如何在灰度位图中获取相应的像素。

这还没有使用LockBits,但它足够好看看它是否会让你想要你想要的:

public Bitmap getGrayOverlay(Bitmap bmpColor, Bitmap bmpGray) { Size s1 = bmpColor.Size; Size s2 = bmpGray.Size; if (s1 != s2) return null; Bitmap bmpResult= new Bitmap(s1.Width, s1.Height); for (int y = 0; y < s1.Height; y++) for (int x = 0; x < s1.Width; x++) { Color c1 = bmpColor.GetPixel(x, y); Color c2 = bmpGray.GetPixel(x, y); bmpResult.SetPixel(x, y, Color.FromArgb((int)(255 * c2.GetBrightness()), c1 ) ); } return bmpResult; } 

当你完成它们时,处理所有三个位图!

这是LockBit版本,稍长一点,但基本相同。 大约快10倍..我假设输入文件是24bppRGB或32bppARGB,否则它们返回null ..:

 public Bitmap getGrayOverlayLBA(Bitmap bmp1, Bitmap bmp2) { Size s1 = bmp1.Size; Size s2 = bmp2.Size; if (s1 != s2) return null; PixelFormat fmt1 = bmp1.PixelFormat; PixelFormat fmt2 = bmp2.PixelFormat; PixelFormat fmt = new PixelFormat(); fmt = PixelFormat.Format32bppArgb; Bitmap bmp3 = new Bitmap(s1.Width, s1.Height, fmt); Rectangle rect = new Rectangle(0, 0, s1.Width, s1.Height); BitmapData bmp1Data = bmp1.LockBits(rect, ImageLockMode.ReadOnly, fmt1); BitmapData bmp2Data = bmp2.LockBits(rect, ImageLockMode.ReadOnly, fmt2); BitmapData bmp3Data = bmp3.LockBits(rect, ImageLockMode.ReadWrite, fmt); byte bpp1 = 4; byte bpp2 = 4; byte bpp3 = 4; if (fmt1 == PixelFormat.Format24bppRgb) bpp1 = 3; else if (fmt1 == PixelFormat.Format32bppArgb) bpp1 = 4; else return null; if (fmt2 == PixelFormat.Format24bppRgb) bpp2 = 3; else if (fmt2 == PixelFormat.Format32bppArgb) bpp2 = 4; else return null; int size1 = bmp1Data.Stride * bmp1Data.Height; int size2 = bmp2Data.Stride * bmp2Data.Height; int size3 = bmp3Data.Stride * bmp3Data.Height; byte[] data1 = new byte[size1]; byte[] data2 = new byte[size2]; byte[] data3 = new byte[size3]; System.Runtime.InteropServices.Marshal.Copy(bmp1Data.Scan0, data1, 0, size1); System.Runtime.InteropServices.Marshal.Copy(bmp2Data.Scan0, data2, 0, size2); System.Runtime.InteropServices.Marshal.Copy(bmp3Data.Scan0, data3, 0, size3); for (int y = 0; y < s1.Height; y++) { for (int x = 0; x < s1.Width; x++) { int index1 = y * bmp1Data.Stride + x * bpp1; int index2 = y * bmp2Data.Stride + x * bpp2; int index3 = y * bmp3Data.Stride + x * bpp3; Color c1, c2; if (bpp1 == 4) c1 = Color.FromArgb(data1[index1 + 3], data1[index1 + 2], data1[index1 + 1], data1[index1 + 0]); else c1 = Color.FromArgb(255, data1[index1 + 2], data1[index1 + 1], data1[index1 + 0]); if (bpp2 == 4) c2 = Color.FromArgb(data2[index2 + 3], data2[index2 + 2], data2[index2 + 1], data2[index2 + 0]); else c2 = Color.FromArgb(255, data2[index2 + 2], data2[index2 + 1], data2[index2 + 0]); byte A = (byte)(255 * c2.GetBrightness()); data3[index3 + 0] = c1.B; data3[index3 + 1] = c1.G; data3[index3 + 2] = c1.R; data3[index3 + 3] = A; } } System.Runtime.InteropServices.Marshal.Copy(data3, 0, bmp3Data.Scan0, data3.Length); bmp1.UnlockBits(bmp1Data); bmp2.UnlockBits(bmp2Data); bmp3.UnlockBits(bmp3Data); return bmp3; } 

编辑:我修改了代码以允许24bpp图像作为源。