Lab 8: Image Manipulation


Black & White Cat - I created this image from cat.pgm by first running the blurring program (Part 5) and then running the posterization program (Part 1).

Project 1 had you read and write files of images. But you only did basic image manipulation that didn't require you to load the images into memory. This lab will instead ask you to load the entire picture into your program's memory, and perform more advanced manipulation. The project used the PPM format which had 3 values for 1 pixel (red/green/blue values). We will instead use the PGM format which has 1 value for 1 pixel. This means PGM are greyscale images without color. Each pixel is represented by a number from 0 and 255. 0 is black, and 255 is white.

So, for example:
P2
4 4
255
0   255 0   0
0   0   255 0
0   0   0   255
128 128 128 128   
<-- header
<-- size: 4 (width) x 4 (height)
<-- max value = 255 
So we will be reading, storing and writing files in these formats. I want you to use your own pictures for this stuff. Hopefully you already know how to download and save image files. What you need to know, however, is how to convert them to pgm files. Fortunately, the lab machines have a suite of tools called "Imagemagick" installed. One of these, convert, can do this conversion for you. Suppose foo.jpg is a file of yours (could be .png, .gif, whatever). To convert it to pgm do the following:
Whenever the output file in convert is a .pgm file, be sure to give the -compress none option! It's a good idea to check each .pgm file to make sure the format looks OK using the more command, like this:
more foo.pgm
convert -compress none foo.jpg fpp.pgm
You can convert back to .jpg with the following:
convert bar.pgm bar.jpg
You can also resize with Imagemagick. For example, to stretch/compress the an image tmp.jpg into a 300 wide by 500 pixel high image, I can do:
convert -resize 300x500! tmp.jpg tmpNEW.jpg
With these simple commands in hand, you should be able to prepare your own images for this lab. To view an image, use the eog program. For example:
eog foo.pgm &
I really prefer you find some images of your own. If you want, however, here are two for you to play with: dog.pgm / dog.jpg and cat.pgm / cat.jpg

Submission

Submit your code with the following:
~/bin/submit -c=SI204 -p=lab08 part1.cpp part2.cpp part3.cpp

There are no online test cases for this lab.

Part 1: Posterize

Write a program that reads in a file in .pgm format, and produces a "posterized" version of that file. Note: even though this particular part doesn't require it, I insist that you read the file completely and store it in a 2D array, and only then create the posterized version. Here's an example:
run of programcat.pgmpostercat.pgm
~/$ ./part1
filename: cat.pgm
output filename: postercat.pgm
The rule for posterization I used was this: if a pixel in the original has value > 128, in the new image that pixel has value 255. Otherwise, it has value 0.

Part 2: reflections

Write a program that reads in a file in .pgm format, and produces a version of that file that is the image with its reflection along the bottom of the original image. Here's an example:
run of programdog.pgmmirrordog.pgm
~/$ ./part2
filename: dog.pgm
output filename: mirrordog.pgm

Part 3: rotate

Write a program that reads in a file in .pgm format, and produces a version of that file with the image rotated 90 degrees counter-clockwise. Here's an example:
run of programcat.pgmrotatecat.pgm
~/$ ./part3 
filename: cat.pgm
output filename: rotatecat.pgm

Part 4: (optional) Going Further - striping

Write a program that reads in two files in .pgm format, both of the same size, and produces a new file of that size consisting of vertical strips alternatingly from one then the other of the input files. The user will input the numberof vertical strips to use. Here's an example:
run of programcat.pgmdog.pgmcatdog.pgm
~/$ ./part4
file 1: cat.pgm
file 2: dog.pgm
Number of strips: 25
output filename: stripcatdog.pgm

Part 5: (optional) Going Further - blur

Write a program that reads in a file in .pgm format, and produces a version of that image that's blurred. Here's an example:
run of programdog.pgmblurdog.pgm
~/$ ./part5
filename: cat.pgm
blur size: 100
output filename: blurdog.pgm
Note: blur size 100 with a
big file could take some time!
Here's how I did the blur, and I recommend you do it too. If K is the "blur size", pixel i,j in the output image is the average of the square of pixels centered at pixel i+K,j+K in the input image, with side-length 2*K + 1. To keep all the pixels in range, you'll see that the output image is smaller than the input image. C'est la vie.

Part 6: (optional) Still Going Further

From here, the sky's the limit. What do you want to do? You could draw pictures in pixels, fade to black as you move horizontally across an image, merge to images so that the top is image 1, the bottom is image 2, and the transition between is smooth. How about "masking", e.g. take one of the posterized images and a second image, and make it so that the second image only shows through where the posterized image is white. You could take an image and produce an ASCII art equivalent. You could do that thing where you create a big picture that's made up of little pictures.