使用混合模式颜色在另一个图像上绘制图像

在Photoshop中,您可以选择“颜色”(从底部开始的第二个)将混合模式设置为下一个较低层:

图层混合模式选择photoshop

如果图像顶部只有一个渐变,结果可能如下所示:

颜色混合示例

我在某处找到的颜色混合模式的描述是:

颜色将下层的色调和饱和度改变为上层的色调和饱和度,但仅留下亮度。

到目前为止我的代码是:

using(var g = Graphics.FromImage(canvas)) { // draw the lower image g.DrawImage(lowerImg, left, top); // creating a gradient and draw on top using (Brush brush = new LinearGradientBrush(new Rectangle(0, 0, canvasWidth, canvasHeight), Color.Violet, Color.Red, 20)) { g.FillRectangle(brush, 0, 0, canvasWidth, canvasHeight); } } 

但那是 – 当然 – 只是在较低的图像上绘画。

所以问题是:

如何使用Photoshop中提供的混合模式“颜色”在另一个图像上绘制图像?

编辑:

为了使我更清楚我想要实现的目标:

在此处输入图像描述

如果有人想使用图像进行测试:

在此处输入图像描述在此处输入图像描述

这是我的解决方案。 我使用了Rich Newman的HSLColor类来转换RGB和HSL值。

 using (Bitmap lower = new Bitmap("lower.png")) using (Bitmap upper = new Bitmap("upper.png")) using (Bitmap output = new Bitmap(lower.Width, lower.Height)) { int width = lower.Width; int height = lower.Height; var rect = new Rectangle(0, 0, width, height); BitmapData lowerData = lower.LockBits(rect, ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb); BitmapData upperData = upper.LockBits(rect, ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb); BitmapData outputData = output.LockBits(rect, ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb); unsafe { byte* lowerPointer = (byte*) lowerData.Scan0; byte* upperPointer = (byte*) upperData.Scan0; byte* outputPointer = (byte*) outputData.Scan0; for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { HSLColor lowerColor = new HSLColor(lowerPointer[2], lowerPointer[1], lowerPointer[0]); HSLColor upperColor = new HSLColor(upperPointer[2], upperPointer[1], upperPointer[0]); upperColor.Luminosity = lowerColor.Luminosity; Color outputColor = (Color) upperColor; outputPointer[0] = outputColor.B; outputPointer[1] = outputColor.G; outputPointer[2] = outputColor.R; // Moving the pointers by 3 bytes per pixel lowerPointer += 3; upperPointer += 3; outputPointer += 3; } // Moving the pointers to the next pixel row lowerPointer += lowerData.Stride - (width * 3); upperPointer += upperData.Stride - (width * 3); outputPointer += outputData.Stride - (width * 3); } } lower.UnlockBits(lowerData); upper.UnlockBits(upperData); output.UnlockBits(outputData); // Drawing the output image } 

您必须重新构建代码,以便在临时位图上绘制渐变,从临时位图和canvas中读取每个像素,并将组合像素写入canvas。 您应该能够找到RGB和HSL颜色之间的代码转换,一旦您可以这样做,将canvas中像素的色调和饱和度设置为临时位图中的值是微不足道的(尽管如果您想使用它会有点难度) alpha值)。

这是完整性的已接受答案的安全(和较慢)版本。

  using (var lower = new Bitmap(@"lower.png")) using (var upper = new Bitmap(@"upper.png")) using (var output = new Bitmap(lower.Width, lower.Height)) { var width = lower.Width; var height = lower.Height; for (var i = 0; i < height; i++) { for (var j = 0; j < width; j++) { var upperPixel = upper.GetPixel(j, i); var lowerPixel = lower.GetPixel(j, i); var lowerColor = new HSLColor(lowerPixel.R, lowerPixel.G, lowerPixel.B); var upperColor = new HSLColor(upperPixel.R, upperPixel.G, upperPixel.B) {Luminosity = lowerColor.Luminosity}; var outputColor = (Color)upperColor; output.SetPixel(j, i, outputColor); } } // Drawing the output image }