Reputation: 603
I have a dilemma. At the first glance my task is simple enough, but I definitely have some troubles with it. I have an image. Gray image. And I need to get colored image. Pictures show it best.
I know two ways to do this: 1) changing tint, 2) changing hue (rotating color matrix)
Tint changes common color and also black. So I believe that this way is not suitable in my case.
Hue changing requires base image to be already colored, but all images are grey (with gradient) initially. But it works fine as it needed.
So I am a little confused about the way of solving this task.
May be there are some other ways to do what I need to do?
I am greatly appreciate your help, guys! Thank you in advance!
↑This is a base image↑
↑Similar is needed to be achieved↑
↑Tinted image↑
Upvotes: 1
Views: 1839
Reputation: 603
I wrote these two methods that do the job. You can set any color you want your image to be blended with.
private void ApplyColor(Bitmap bm, Color userColor)
{
if (bm==null)
return;
// pixels loop
for (int i = 0; i < bm.Width; i++)
{
for (int j = 0; j < bm.Height; j++)
{
// get current pixel
Color curPix = bm.GetPixel(i, j);
Color curPixColor = Color.FromArgb(curPix.A, curPix.R, curPix.G, curPix.B);
// get result color by blending
Color resultColor = Blend(curPixColor, userColor, ColorMixFactor);
// set pixel color
bm.SetPixel(i, j, resultColor);
}
}
}
public static Color Blend(Color srcColor, Color dstColor, double amount)
{
// restrict black (dark) color from being affected by the blending
var br = srcColor.GetBrightness();
if (br < BrightnessToAvoid)
return srcColor;
// get all 4 color channels
var r = (byte) ((srcColor.R*amount) + dstColor.R*(1 - amount));
var g = (byte) ((srcColor.G*amount) + dstColor.G*(1 - amount));
var b = (byte) ((srcColor.B*amount) + dstColor.B*(1 - amount));
var a = srcColor.A;
// get blended color
return Color.FromArgb(a, r, g, b);
}
Upvotes: 0
Reputation: 910
I have written some code to pass the grayscale component as yellow color (shared between the R and G components) i have got close enough results, all you need to do is to play with the R and G components ratios to get the degree of the yellow color you need. also you need to search more on how to handle the shadow at the bottom of the object.
// Load image
Bitmap bm = new Bitmap("D:\\a.png");
for (int i = 0; i < bm.Width; i++)
{
for (int j = 0; j < bm.Height; j++)
{
// Handles transparent pixles
if (bm.GetPixel(i, j).R == 0 & bm.GetPixel(i, j).G == 0 & bm.GetPixel(i, j).B == 0 & bm.GetPixel(i, j).A == 0) bm.SetPixel(i, j, Color.Transparent);
// Passes the grey component of the grescale image to R and G compenents and changes pixle color
else bm.SetPixel(i, j, Color.FromArgb(bm.GetPixel(i, j).R, bm.GetPixel(i, j).R, 0));
}
}
// Save image
bm.Save("D:\\b.png");
Here is the result i got from the posted image
Upvotes: 1