Let's say I have an image composed of black and white RGB pixels, with varying levels of transparency. I then want to use GDI+ to maintain the transparency levels of all pixels and transform just the black pixels to red, leaving the white ones unaffected.
I think the colormap would look something like:
|0 0 0 0 0|
|0 0 0 0 0|
|0 0 0 0 0|
|0 0 0 1 0|
|1 0 0 0 1|
but how, short of looping over each pixel in turn and testing its colour, can I apply that map just to the black pixels?
To answer you main question: there is no way to use matrices to replace a specific color, because matrices are merely transformations without conditions.
To solve your problem: because of the combination you are using (Black and White), matrices can be used! See detailed answer below...
A very good reference: Color Transformations and the Color Matrix.
You are very close in your matrix guess, however, you weren't keeping all of the RGBA values intact. Take a look here:
R G B A W
___________________
| 1 | 0 | 0 | 0 | 0 |
| 0 | 1 | 0 | 0 | 0 |
| 0 | 0 | 1 | 0 | 0 |
| 0 | 0 | 0 | 1 | 0 |
| 1 | 0 | 0 | 0 | 1 |
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
Through the diagonal 1
's, you are maintaining the current RGBA values. By specifying a 1
on [4][0]
, you are also saying that you want that value at its maximum!
In your specific case of using Black and White, replacing only the Black color will work, because White has its RGB values already at maximum (255, 255, 255).
Hence, through the above matrix you are basically saying: keep all RGB at their current values, but I also want Red to always be 255!
Detailed example using sequence (R, G, B, A), and applying the above rules: Red at maximum = 255, everything else the same.
As you can see, the Red component is always set to its maximum, and the rest is maintained.
Sample picture:
The left side contains original colors with an alpha value specified, while the right contains the same image with the above transformation applied. The circles on the left side are organized in the following manner:
R G B A | R G B A
______________________|_______________________
circle[0,0] = | (255, 0, 0, 0) | (255, 0, 0, 64) | = circle[0,1]
[1,0] = | ( 0, 0, 0, 0) | ( 0, 0, 0, 64) | = [1,1]
[2,0] = | (255, 255, 255, 0) | (255, 255, 255, 64) | = [2,1]
[3,0] = | (255, 0, 0, 128) | (255, 0, 0, 255) | = [3,1]
[4,0] = | ( 0, 0, 0, 128) | ( 0, 0, 0, 255) | = [4,1]
[5,0] = | (255, 255, 255, 128) | (255, 255, 255, 255) | = [5,1]
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
C# code to generate the sample image:
using (Bitmap myBitmap = new Bitmap(102, 302))
{
Graphics g = Graphics.FromImage(myBitmap);
g.Clear(Color.Transparent);
g.FillEllipse(new SolidBrush(Color.FromArgb(0, Color.Red)), new Rectangle(1, 1, 50, 50));
g.FillEllipse(new SolidBrush(Color.FromArgb(0, Color.Black)), new Rectangle(1, 51, 50, 50));
g.FillEllipse(new SolidBrush(Color.FromArgb(0, Color.White)), new Rectangle(1, 101, 50, 50));
g.FillEllipse(new SolidBrush(Color.FromArgb(64, Color.Red)), new Rectangle(51, 1, 50, 50));
g.FillEllipse(new SolidBrush(Color.FromArgb(64, Color.Black)), new Rectangle(51, 51, 50, 50));
g.FillEllipse(new SolidBrush(Color.FromArgb(64, Color.White)), new Rectangle(51, 101, 50, 50));
g.FillEllipse(new SolidBrush(Color.FromArgb(128, Color.Red)), new Rectangle(1, 151, 50, 50));
g.FillEllipse(new SolidBrush(Color.FromArgb(128, Color.Black)), new Rectangle(1, 201, 50, 50));
g.FillEllipse(new SolidBrush(Color.FromArgb(128, Color.White)), new Rectangle(1, 251, 50, 50));
g.FillEllipse(new SolidBrush(Color.FromArgb(255, Color.Red)), new Rectangle(51, 151, 50, 50));
g.FillEllipse(new SolidBrush(Color.FromArgb(255, Color.Black)), new Rectangle(51, 201, 50, 50));
g.FillEllipse(new SolidBrush(Color.FromArgb(255, Color.White)), new Rectangle(51, 251, 50, 50));
g.DrawRectangle(Pens.Black, 0, 0, myBitmap.Width - 1, myBitmap.Height - 1);
e.Graphics.DrawImage(myBitmap, 0, 0);
ColorMatrix colorMatrix = new ColorMatrix(
new Single[][]
{
new [] { 1f, 0, 0, 0, 0 },
new [] { 0f, 1, 0, 0, 0 },
new [] { 0f, 0, 1, 0, 0 },
new [] { 0f, 0, 0, 1, 0 },
new [] { 1f, 0, 0, 0, 1 }
});
using (ImageAttributes imageAttr = new ImageAttributes())
{
imageAttr.SetColorMatrix(colorMatrix);
Rectangle rect = new Rectangle(150, 0, myBitmap.Width, myBitmap.Height);
e.Graphics.DrawImage(myBitmap, rect, 0, 0, myBitmap.Width, myBitmap.Height, GraphicsUnit.Pixel, imageAttr);
}
}
The black color is represented by 0, The white color is represented by 1
To get your mathematics work with the black pixels only you should the following:
your colormap in step 2 will look like:
|0 0 0 0 0|
|0 1 0 0 0|
|0 0 1 0 0|
|0 0 0 1 0|
|0 0 0 0 1|
The result now should be as the following:
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