In Photoshop you can select "Color" (the second from the bottom) to set the blending mode to the next lower layer:
If you have just a gradient on top of an image the result could look like this:
The description of the color blending mode I found somewhere is:
Color changes the hue and saturation of the lower layer to the hue and saturation of the upper layer but leaves luminosity alone.
My code so far is:
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);
}
}
But that is - of course - just painting over the lower image.
So the question is:
How can I draw an image on top of another image using the blending mode "color" as available in Photoshop?
EDIT:
To make it a bit more clear of what I want to achieve:
And if someone wants to use the images for testing:
Here is my solution. I've used Rich Newman's HSLColor class to convert between RGB and HSL values.
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
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With