3

I have a grayscale image that needs to be painted with values from a gradient of 5 colors. Light pixels should get a lighter color from the gradient, dark pixels should get a darker one.

If the gradient starts with yellow and ends with red, then white pixels would be yellow and black pixels red with everything in between along the gradient.

Can it be done with ColorMatrix?

Unihedron
  • 10,902
  • 13
  • 62
  • 72
Tom J
  • 33
  • 1
  • 4

3 Answers3

2

You mentioned "five colors" but also a gradient from red to yellow.

To illustrate the basic idea, we can generate a Color array from a byte array, where the byte array represents the 8-bit grayscale values of the original image.

  • grayscale value 0 (black) maps to red, which is Color.FromArgb(255,0,0)
  • grayscale value 255 (white) maps to yellow, which is Color.FromArgb(255,255,0)

To find the new gradient color (r,g,b) given the grayscale value (8-bit), do the following:

  1. Set the Red component to 255
  2. Set the Blue component to the original gray value (0 - 255)
  3. Set the Green component to 0

Sample code to convert from a byte array to Color array:

byte[] bytes = getImageBytes();
Color[] colors = new Color[bytes.Length];  

for(int i = 0; i < bytes.Length; i++)
{
    colors[i] = Color.FromArgb(255, bytes[i], 0);
}

To do this operation quickly, use "lock/unlock bits" code and manipulate the byte values directly.

http://msdn.microsoft.com/en-us/library/5ey6h79d.aspx

Rethunk
  • 3,976
  • 18
  • 32
2

What you want is in the simplest case a linear interpolation between 5 points in 3d. A direct color gradient between two colors {r1,g1,b1} and {r2,g2,b2} is, as you would walk onto the line in 3d which connects the points {r1,g1,b1} and {r2,g2,b2}. When your gray-values are in the interval [0,1], then you would want to have the color {r1,g1,b1} if you have a gray-level 0 and {r2,g2,b2} if you have a gray-level 1. The question is how to calculate the colors in between:

think of the simple school vector analysis. c1 is the point {r1,g1,b1}, c2 is {r2,g2,b2}. Start at c1 and go in direction of the vector c2-c1:

outColor = c1 + gray*(c2-c1)

or equivalently

outColor = (1-gray)c1 + grayc2

Remenber, gray must lie in the interval [0,1]. Otherwise you have to rescale it. This is simple linear interpolation between two points which can of course be extended for as many colors as you want.

For five colors the approach is basically the same. Here for 5 randomly chosen colors:

{{0.273372, 0.112407, 0.0415183}, 
 {0.79436,  0.696305, 0.167884}, 
 {0.235083, 0.999163, 0.848291}, 
 {0.295492, 0.780062, 0.246481}, 
 {0.584883, 0.460118, 0.940826}}

enter image description here

Two important things you have to know:

  1. If you want to have the color for a given gray-value, you first need to extract the two surrounding rgb-points. For instance if you want to have the color for gray=0.1 it would be the first and the second rgb-point.

  2. You have to rescale your gray-value according to the number of colors which you use in your gradient. Look at the image, with 5 colors, you have 4 different two point interpolation intervals. When you want to make the above mentioned color formula work, you have to rescale your gray-value for each color-interval to [0,1].

Remark: This is of course not the solution for the implementation in C#, but your question suggested, that creating a color-image of the same size was not your problem. Calculating the color-values for each gray-value is the key for your colorization.

halirutan
  • 4,281
  • 18
  • 44
0

You can simply iterate over all pixels of the grayscale image and take the Brightness and Alpha value of it (simplest by using LINQ). Then you take your desired color and use its Hue and Saturation and Brightness.

Now you create a new color by taking the Gray.Alpha, Color.Hue, Color.Saturation and a combination of Gray.Brightness and Color.Brightness and apply this color to the pixel in the grayscale image.

The first tricky parts is to create a color from Alpha, Hue, Saturation and Brigthness, but you can simply take this function ;-).

The last tricky part is to combine the Brightness of the gray and the color and is left as an exercise to the reader. ;-)

Community
  • 1
  • 1
Oliver
  • 43,366
  • 8
  • 94
  • 151