Introduction
In my current job, I was creating a control that manipulated the brightness and contrast of an image. I didn't want to call Graphics.DrawImage
more than once. The solution was to do a matrix multiply on the two matrices (brightness and contrast) before drawing the image. Just for fun, I included a picture of my daughter in the project...
The main part of the code I wanted to share was the matrices and the matrix multiplication.
private void NewMatrices()
{
bm = new float[5][];
cm = new float[5][];
for (int i = 0; i < 5; i++)
{
bm[i] = new float[5];
cm[i] = new float[5];
}
float brightness = 0.2f;
bm[0][0] = 1; bm[0][1] = 0; bm[0][2] = 0; bm[0][3] = 0; bm[0][4] = 0;
bm[1][0] = 0; bm[1][1] = 1; bm[1][2] = 0; bm[1][3] = 0; bm[1][4] = 0;
bm[2][0] = 0; bm[2][1] = 0; bm[2][2] = 1; bm[2][3] = 0; bm[2][4] = 0;
bm[3][0] = 0; bm[3][1] = 0; bm[3][2] = 0; bm[3][3] = 1; bm[3][4] = 0;
bm[4][0] = brightness; bm[4][1] = brightness;
bm[4][2] = brightness; bm[4][3] = 1; bm[4][4] = 1;
float contrast = 20f;
float T = 0.5f * (1f - contrast);
cm[0][0] = contrast; cm[0][1] = 0; cm[0][2] = 0; cm[0][3] = 0; cm[0][4] = 0;
cm[1][0] = 0; cm[1][1] = contrast; cm[1][2] = 0; cm[1][3] = 0; cm[1][4] = 0;
cm[2][0] = 0; cm[2][1] = 0; cm[2][2] = contrast; cm[2][3] = 0; cm[2][4] = 0;
cm[3][0] = 0; cm[3][1] = 0; cm[3][2] = 0; cm[3][3] = 1; cm[3][4] = 0;
cm[4][0] = T; cm[4][1] = T; cm[4][2] = T; cm[4][3] = 1; cm[4][4] = 1;
}
private float[][] Multiply(float[][] f1, float[][] f2)
{
float[][] X = new float[5][];
for (int d = 0; d < 5; d++)
X[d] = new float[5];
int size = 5;
float[] column = new float[5];
for (int j = 0; j < 5; j++)
{
for (int k = 0; k < 5; k++)
{
column[k] = f1[k][j];
}
for (int i = 0; i < 5; i++)
{
float[] row = f2[i];
float s = 0;
for (int k = 0; k < size; k++)
{
s += row[k] * column[k];
}
X[i][j] = s;
}
}
return X;
}
Another interesting part of the code is the DrawImage
function. It takes in a matrix (i.e., float[][]
) and draws an image with that matrix.
private void DrawImage(float[][] Matrix)
{
ColorMatrix m = new ColorMatrix(Matrix);
ImageAttributes ia = new ImageAttributes();
ia.SetColorMatrix(m);
Rectangle rMy = new Rectangle(0,0,i.Width, i.Height);
Bitmap bm = new Bitmap(i.Width, i.Height);
Graphics g = Graphics.FromImage((Image)bm);
g.Clear(Color.Black);
g.DrawImage(i, rMy, 0, 0, i.Width, i.Height,
GraphicsUnit.Pixel, ia);
pictureBox1.Image = (Image)bm;
}
So now, we can call DrawImage
with one of our matrices we created above, or use Multiply
to combine them.
DrawImage(cm);
DrawImage(bm);
DrawImage(Multiply(cm,bm);