Image Editing Tutorials: For C# and VB NET Students
You can manipulate each pixel of your image to get some really nice effects. We're going to add a colour filter to an image. We're going to take this image:
And turn it into this:
You can use any image for this, though. But if you want to use ours, right-click on the first London Bridge photo and save it to your own computer. Then load it into the PictureBox on your form.
The code for manipulating pixels is more difficult than for the rotating, flipping and cloning you did in previous lessons. We'll need to get a pixel's colour, create a new colour based on that pixel's colour, then set a new pixel colour.
Add a new button to your form. Double click the button to open up its code stub. Create a Bitmap from your PictureBox as before:
Bitmap bmp = new Bitmap(pictureBox1.Image);
Dim bmp As Bitmap = New Bitmap(PictureBox1.Image)
Now add these two variables to your code:
int x, y;
Dim x As Integer
Dim y As Integer
We need these because we're going to be using a double for loop, one inside the other. Add this double for loop to your code in C#:
for (x = 0; x < bmp.Width; x++)
for (y = 0; y < bmp.Height; y++)
And this one in VB:
For x = 0 To bmp.Width - 1
For y = 0 To bmp.Height - 1
The outer loop goes from 0 to the width of the Bitmap object called bmp. The inner loop goes from 0 to the height of the bmp object. Inside the inner loop, we'll get the x an y values. The first time round the outer loop the x variable will be 0. The inner loop is then executed in full, with the y variable being used. So you'd get these values the first time round:
If that's not too clear, take a look at this checker-board pattern:
This pattern is a square 16 pixels by 16. What our two loops do is to go from left to right, first of all. At the end of the line, we then drop down and go through the second row. All rows are then accessed from top to bottom.
Add this line to your inner for loop:
Color oldPixelColor = bmp.GetPixel(x, y);
Dim oldPixelColor As Color = bmp.GetPixel(x, y)
We're setting up a Color object here and calling it old_pixel_colour. After the equal sign we have this:
We're accessing the Bitmap object called bmp, which holds the image from the PictureBox. After a dot we have an inbuilt method called GetPixel. This gets the colour of a pixel. In between round brackets you type the coordinates of the pixel whose colour you want to grab. We have x, y inside the round brackets. The first time round our outer loop x will have a value of 0. The first time round our inner loop, y will also have a value of 0. So the first pixel we grab is at 0, 0 from our image, which would be the first white square top, left of our checkerboard image. The second time round the inner loop the x and y values will be 0 and 1, which would get us the first black square from the left on the top row of the checkerboard image.
The next line to add to your inner loop is this:
Color newPixelColor = Color.FromArgb(oldPixelColor.R, 0, 0);
Dim newPixelColor As Color = Color.FromArgb(oldPixelColor.R, 0, 0)
We're new setting up a new Color object and calling it newPixelColor. After an equal sign, we have this:
Color.FromArgb(oldPixelColor.R, 0, 0);
What we're doing here is creating a new colour based on the old one. To do that, we're using a method of the Color object called FromArgb. Ignore the A part for now (it stands for Alpha, and we'll get to it soon). The rgb part stands for Red, Green, Blue. This means the Red, Green, and Blue parts of a pixel. Our old pixel colour was white. This has a RGB of 255, 255, 255. A value of 255 means turn the colour full on. So the red part is turned full on, the green part is turned full on and the blue part is turned full on. This gives you a colour of white.
To turn the old white colour into red, we need to switch the red full on and the green and blue parts full off. This is done between the round brackets of FromArgb:
oldPixelColor.R, 0, 0
When you type a dot after the variable oldPixelColor you'll see the following list:
The B, G and R items allow you to get the Red, Blue and Green colour parts of a pixel. We're just getting the Red part. We're setting the Green and Blue parts to 0, meaning don't get these colours at all.
Remember, though, it's the just the Red part of the old colour. The old colour was white, which is RGB 255, 255, 255. We just want the first 255, the red part. We're setting the other 255's to 0.
Now that we have a new colour from the old one, we can set a pixel. Add this line to your inner loop (without the semicolon on the end for VB):
bmp.SetPixel(x, y, newPixelColor);
The SetPixel method sets a colour for a pixel. In between round brackets you first specify the location for your new pixel. Our location is held in the x and y variables, which will be 0, 0 the first time round both loops. After a comma, we type the new colour we want for the pixel in this position. So we've changed the pixel from white to red.
The second time round our inner for loop we get a black square. The colour black has a RGB value of 0, 0, 0. When we use FromArgb again we still get just the red part of those three numbers. The red part is 0. The new colour will, therefore, still be black.
When the loop is finished, the code above would turn a black and white checker-board pattern to this:
If we wanted the checker-board to go from white and black to yellow and black the FromArgb line would be this (again without the semicolon on the end for VB):
Color.FromArgb(oldPixelColor.R, oldPixelColor.G, 0);
This time, we're grabbing the Red and Green parts of the old colour. If the old colour is white (255, 255, 255) then the new RGB is 255, 255, 0. Turning red full on, green full on and blue off gives you yellow.
The final line to add is outside of the two loops:
pictureBox1.Image = bmp;
PictureBox1.Image = bmp
This sets the PictureBox image to the new version of the bmp image.
Here's what your code should look like in C#:
And here it is in Visual Basic:
Run your program and load an image into your PictureBox. Click your Filter button and it should turn red. As an exercise, amend your code so that the filter is blue instead of red.
Finally, a word about the A part of the FromArgb method.
The A stands for Alpha. An Alpha value is a measure of how transparent you want the colour of your pixels. A value of 0 means fully transparent, while of value of 255 means fully opaque. The default is 255. If you wanted to turn the opacity down a bit, you'd do it like this:
Color newPixelColor = Color.FromArgb(100, oldPixelColor.R, 0, 0);
Dim newPixelColor As Color = Color.FromArgb(100, oldPixelColor.R, 0, 0)
The Alpha value goes as the first argument to FromArgb. Here's our London Bridge image again. The one on the left has an Alpha value of 255. The image on the right has an Alpha value of 100 set for it:
In the next lesson, you'll learn how to invert the pixels in an image.