Question

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↑ this is a base image

↑Similar is needed to be achieved↑ this is needed to be achieved

↑Tinted image↑ tinted image

Était-ce utile?

La solution 2

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);
    }

Autres conseils

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

enter image description here

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top