This lab we will be writing programs that manipulate images.
We will be using a format called PGM (.pgm), that is very
simple. It represents an image in a text file in which each
pixel is represented by a number from 0 and 255. 0 is black,
and 255 is white. The first line of the file is P2, the second
line is the width-space-height in pixels, the third is 255, and
from then on we get pixels values. So, for example,
here is the file
smallest.pgm:
:
P2
4 5
255
0 255 0 0
0 0 255 0
0 0 0 255
0 80 160 240
240 160 80 0 |
 |
Note: this image has
5 rows and 4 columns.
So we see that the
width is listed first,
and the height is
listed second!
|
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 (and youf VMs) 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
Finally, if you want to get the pixel dimensions of an image,
the
identify command will do it for you:
$ identify cat.jpg
cat.jpg JPEG 1024x768 1024x768+0+0 8-bit Grayscale Gray 256c 73.2KB 0.000u 0:00.000
... from which we see it is 1024x768.
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
(and you can test further with
ianfh.pgm and
cd.pgm).
Part 1: Posterize
Write a program
part1.cpp 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 program | cat.pgm | postercat.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.
Submit:
~/bin/submit-external -c=SI204 -p=lab09 part1.cpp
Important: I recommend you test your program
on smallest.pgm as shown below.
| smallest.pgm |
run program
| poster.pgm
|
~/$ cat smallest.pgm
P2
4 5
255
0 255 0 0
0 0 255 0
0 0 0 255
0 80 160 240
240 160 80 0 |
~/$ ./part1
filename: smallest.pgm
output filename: poster.pgm |
~/$ cat poster.pgm
P2
4 5
255
0 255 0 0
0 0 255 0
0 0 0 255
0 0 255 255
255 255 0 0 |
Part3: merging (you can try striping too)
Write a program
part3.cpp that reads in two files in .pgm format,
both of the same size,
and produces a new file of that size that merges the two files.
My rule for merging is that the value of pixel i,j in the merged file
is the average of the values of the first file's pixel i,j and
the second file's pixel i,j value (note: truncate any fractional
part, don't round!).
Here's an example:
| run of program | cat.pgm | dog.pgm | catdog.pgm |
~/$ ./part3
file 1: cat.pgm
file 2: dog.pgm
output filename: catdog.pgm |
 |
 |
 |
Submit:
~/bin/submit-external -c=SI204 -p=lab09 part1.cpp part2.cpp part3.cpp
Another intersting thing to try with two pictures of the same
size (not to turn in!) is to
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 number of vertical strips to use.
Here's an example:
| run of program | cat.pgm | dog.pgm | catdog.pgm |
~/$ ./part3b
file 1: cat.pgm
file 2: dog.pgm
Number of strips: 25
output filename: stripcatdog.pgm |
 |
 |
 |