Lab 6. Processing images

Lab 6. Processing images

Intro

In this lab, we are going to write programs that read a graphics file, performs some simple image processing, and output the result to a new file.

./prog < input_file > output_file

To load an image into our program, we will use an image format called PPM. To transform any normal image file like JPEG or PNG into PPM and back, we will use the utility convert, it’s installed on all computers in the Lab (it’s a standard Linux application).

This introduction first describes how an image can be represented in our program as a multidimensional array. Then it reviews the PPM graphics format.

Notice that the functions to read and write PPM files (through stdin and stdout) are provided to save your time, however they are very simple functions and you may implement them yourself.

RGB colors

All colors representable on the screen can be encoded with a triple of integers (Red, Green, Blue), such representation is called the RGB color model.

RGB color model

This model defines a color by giving the intensity level of red, green and blue light that mix together to create it on the display. With most of today’s displays, the intensity of each color can vary from 0 to 255, which gives 16,777,216 different colors.

The black color is represented by (0,0,0), white is (255,255,255). The primary colors, red, green, and blue are (255,0,0), (0,255,0), and (0,0,255), repectively.

If you are not familar with the RGB model, to get more examples, please see this demo of the RGB color scheme.

An image is an array

Any image is a rectangle of pixels of the dimension Width x Height. And since we represent the color of each pixel with three integers (R, G, B), we can use a 3D array of the dimension Width x Height x 3 to store the entire image:

int image [Width][Height][3];

Portable Pixmap Format (PPM format)

While there exist many great formats to compress graphics, such as PNG or JPEG, however, reading and writing such files is not a trivial task. We would like to load an image into our program, while avoiding such a complexity.

There exists a rather obscure graphics format called Portable Pixmap Format. It represents an image as a plain text file, in a super straight-forward way.

A good description of the Plain ASCII PPM format is given in the Wikipedia article, and a more formal description can be found here.

Consider an example:

PPM file scaled up

P3
# My PPM image file
4 5
255
 0   0   0      0   0   0      0   0   0     255  0  127
 0   0   0      0  255 127     0   0   0      0   0   0
 0   0   0      0   0   0      0  255 127     0   0   0
255  0  127     0   0   0      0   0   0      0   0   0
 0   0   0     127 127 127     0   0   0     127 127 127

The file starts with the line P3 informing us that the file format is Plain PPM. The comment line is skipped.

The following line 4 5 means that the image width = 4 and the image height = 5. Then, 255 tells us that the maximum color value is 255 (this is standard). The remaining numbers are the pixels of the image, 3 integers per pixel (the whitespace and the new-line symbols are disregarded).

Reading and writing PPM files

A simple program is avaialble here:

——> readwrite.cpp <——

This program reads an image file in the PPM format, and outputs a new image file, with the blue-component of the colors set to zero:

cat is yellow

Converting a normal image into PPM and back.

We are going to use the utility program convert to transform any normal graphics file into the PPM format. The program is available on all Linux Lab machines.

To convert a PNG or JPEG into PPM:

convert -compress none cat.jpg cat.ppm

To convert a PPM into PNG or JPEG:

convert dog.ppm dog.png

Also note that the image viewer application Eye of MATE (eom) can view PPM files directly, you can run it from the file manager or from the terminal:

eom cat.ppm

How to submit your code

Each program (the source code .cpp file) should be submitted through Blackboard (Course Materials > Lab).

You can submit all your programs at the end of the lab session in one submission. This way, we can hopefully avoid the situation when you are quickly writing your program, immediately uploading it to Blackboard, but then, say 10 minutes later, realizing that there is a bug in it.

Basically, submit when you are sure that it will be your final version.

Each program should start with a comment that contains your name and a short program description, for example:

/*
  Author: Your Name 
  Description: Lab 1. Task 1. Hello world
*/

You can submit incomplete programs, but their “incomplete” status must be clearly mentioned in the comment to the program. In this case, also briefly describe what is implemented, and what is not.

Assignments

Task 1. Using convert and simple image filtering.

Pick an image file from the Internet of the dimension not more than 250x250, and save it on disk.

Convert this image (assuming it’s called “image.png”) to the PPM format:

convert -compress none image.png image.ppm

Take the program readwrite.cpp, read its main function and make sure that you understand how it works. We essentially read the image into the array in, also updating width and height by reference. Then we run two nested loops, filling the output array out with the colors of the original image, with the only difference that the blue component for each pixel is set to zero (giving the output a yellow shade).

Compile the program as usual:

g++ -o readwrite readwrite.cpp

Run the program on your PPM image file:

./readwrite < image.ppm > out-task1.ppm

The command above redirects the contents of the file “image.ppm” into the Standard Input, and also it takes everything the program outputs and saves it into the file “out-task1.ppm” (it’s called Standard Output redirection).

Now, convert the PPM file into PNG format:

convert out-task1.ppm out-task1.png

When submitting your results to Blackboard, submit only the original file “image.png”, and the output you’ve got, “out-task1.png”. You don’t have to submit the source code.

Task 2. Cyan / Pink.

Now, let’s do some actual programming. Make a modification to the previous program.

It should make the left half of the image Cyan-shaded, and the right half Pink-shaded. Such an effect can be acheived if we:

For this task, as usual, submit the program. Optionally, you may submit your final image (in PNG format).

Task 3. Top-Right corner.

Modify the program in such a way that program that takes an image of size Width-by-Height, and outputs a new image of size (Width/2)-by-(Height/2) that contains exactly the Top-Right corner of the original image.

Notice that it’s important that both the width and the height of the output image must be twice as small. You may use the integer division there to determine the final width and height. So, for exmaple, if the input is an image of size 7-by-5, the output will be 3-by-2.

For this task, as usual, submit the program. Optionally, you may submit your final image (in PNG format).

Task 4. Scaling by the factor of two.

Modify the program to scale (resize) the input image size by the factor of 2.

We would like to scale the image with the simplest approach, in which each pixel of the original image becomes a square 2-by-2 of the same color. This method is called the nearest-neighbor interpolation.

(You may assume that the size of the input image is not more than 250-by-250).

For this task, as usual, submit the program. Optionally, you may submit your final image (in PNG format).

More advanced image processing

You may take a look at these two links: