Reputation: 2050
I am trying to create a function that takes a gray scale image and a color and colors the gray scale image using that color shade but keeps the shading levels of the gray scale image. The function also should not color the transparent parts of the image. I have multiple layers (multiple png's) I will be combining later and only need to color certain layers. I have looked around and found similar things but not quite what I need. I know how to do it in HTML5 on front end for the user using Canvas but I need a way to achieve same thing on the backend using I am guessing either a manual method using unlocked bitmap memory calls or a ColorMatrix class. Can anyone help me, graphics aren't my strongest area but I am slowly learning. See the function below for what I need in C# that I did in javascript. Doing the hidden canvas stuff isn't as important because I am doing this server side for saving to PNG file...
function drawImage(imageObj, color) {
var hidden_canvas = document.createElement("canvas");
hidden_canvas.width = imageObj.width;
hidden_canvas.height = imageObj.height;
var hidden_context = hidden_canvas.getContext("2d");
// draw the image on the hidden canvas
hidden_context.drawImage(imageObj, 0, 0);
if (color !== undefined) {
var imageData = hidden_context.getImageData(0, 0, imageObj.width, imageObj.height);
var data = imageData.data;
for (var i = 0; i < data.length; i += 4) {
var brightness = 0.34 * data[i] + 0.5 * data[i + 1] + 0.16 * data[i + 2];
//red
data[i] = brightness + color.R;
//green
data[i + 1] = brightness + color.G;
//blue
data[i + 2] = brightness + color.B;
}
//overwrite original image
hidden_context.putImageData(imageData, 0, 0);
}
var canvas = document.getElementById('card');
var context = canvas.getContext('2d');
context.drawImage(hidden_canvas, 0, 0);
};
Upvotes: 0
Views: 945
Reputation: 54433
This should do the job:
public static Bitmap MakeChromaChange(Bitmap bmp0, Color tCol, float gamma)
{
Bitmap bmp1 = new Bitmap(bmp0.Width, bmp0.Height);
using (Graphics g = Graphics.FromImage(bmp1))
{
float f = (tCol.R + tCol.G + tCol.B) / 765f;
float tr = tCol.R / 255f - f;
float tg = tCol.G / 255f - f;
float tb = tCol.B / 255f - f;
ColorMatrix colorMatrix = new ColorMatrix(new float[][]
{ new float[] {1f + tr, 0, 0, 0, 0},
new float[] {0, 1f + tg, 0, 0, 0},
new float[] {0, 0, 1f + tb, 0, 0},
new float[] {0, 0, 0, 1, 0},
new float[] {0, 0, 0, 0, 1} });
ImageAttributes attributes = new ImageAttributes();
attributes.SetGamma(gamma);
attributes.SetColorMatrix(colorMatrix);
g.DrawImage(bmp0, new Rectangle(0, 0, bmp0.Width, bmp0.Height),
0, 0, bmp0.Width, bmp0.Height, GraphicsUnit.Pixel, attributes);
}
return bmp1;
}
Note that I kept a gamma parameter; if you don't need it keep the value at 1f
;
Here it is at work, adding first red then more red and some blue :
Transparent pixels are not affected.
For more on ColorMatrix
here is a really nice intro!
As a fun project I applied the known colors to a known face:
Upvotes: 1