In this assignment we will be exploring file input and image processing. In the process, we will also gain experience using exceptions and assertions. The project is to be worked on in pairs with the first part being due on July 21 ar 9:00pm and the second part being due on July 28 at 9:00pm.
Part 1: Input/Output
In this part we will develop the infrastructure to read in images from files. There are two types of files we will be dealing with: black and white images, and color (RGB) images. But before we get to all that, a note on images. . .
Digital Images
Digital images are represented in a computer as a grid of intensity values. Each grid element, indexed by row and column number, is known as a pixel, short for picture element. For a black and white image, each pixel contains one value representing how bright that pixel should be (for our purposes, all intensity values will be represented as values from 0 to 255). A value of 255 is totally white.
For color images, each pixel stores three values, one for each primary color of light, red, green, and blue. Because of the way our eyes work, combining these colors in different amounts creates the illusion of millions of different colors spanning the entire spectrum!
One more thing: i mentioned before that pixels are reffered to by their row and column (r,c). This is true but you should know that the pixel at row 0, column 0 (0,0) is at the upper left corner of the image while the pixel at (height-1, width-1) is at the lower right.
File Formats
We will be manipulating files using two formats: PGM and PPM. PGM (Portable Grey Map) is a format for storing grayscale images and PPM (Portable Pixel Map) is used to store color images.
The file format for PGM images is very simple. The element of the
file is the string P2
. The next elements are the number
of columns followed by the number of rows followed by the number of
levels. (The number of levels is the number of divisions between full
black and full white.) When I say "element" I mean a string of
alphanumeric characters separated by whitespace. After the number of
levels, the intensity for each pixel is given. Additionally, any line
that begins with '#' is a comment. For example:
P2 # i made this image by hand 10 10 255 0 0 0 0 0 0 0 0 0 0 0 255 0 0 255 0 255 255 255 0 0 255 0 0 255 0 0 255 0 0 0 255 0 0 255 0 0 255 0 0 0 255 255 255 255 0 0 255 0 0 0 255 0 0 255 0 0 255 0 0 0 255 0 0 255 0 0 255 0 0 0 255 0 0 255 0 0 255 0 0 0 255 0 0 255 0 255 255 255 0 0 0 0 0 0 0 0 0 0 0
The PPM format is very similar. Instead of P6
there is
P3
and instead of single values for each pixel, there are
three values in a row, one for red, one for green, and one for blue.
For example:
P3 10 10 255 0 255 255 0 255 255 0 255 255 0 255 255 0 255 255 0 255 255 0 255 255 0 255 255 0 255 255 0 255 255 0 255 255 255 255 0 0 255 255 0 255 255 255 255 0 0 255 255 255 0 255 255 0 255 255 0 255 0 255 255 0 255 255 255 255 0 0 255 255 0 255 255 255 255 0 0 255 255 0 255 255 255 0 255 0 255 255 0 255 255 0 255 255 255 255 0 0 255 255 0 255 255 255 255 0 0 255 255 0 255 255 255 0 255 0 255 255 0 255 255 0 255 255 255 255 0 255 255 0 255 255 0 255 255 0 0 255 255 0 255 255 255 0 255 0 255 255 0 255 255 0 255 255 255 255 0 0 255 255 0 255 255 255 255 0 0 255 255 0 255 255 255 0 255 0 255 255 0 255 255 0 255 255 255 255 0 0 255 255 0 255 255 255 255 0 0 255 255 0 255 255 255 0 255 0 255 255 0 255 255 0 255 255 255 255 0 0 255 255 0 255 255 255 255 0 0 255 255 0 255 255 255 0 255 0 255 255 0 255 255 0 255 255 255 255 0 0 255 255 0 255 255 255 255 0 0 255 255 255 0 255 255 0 255 255 0 255 0 255 255 0 255 255 0 255 255 0 255 255 0 255 255 0 255 255 0 255 255 0 255 255 0 255 255 0 255 255 0 255 255
(Try copying and pasting the above text into a text editor and saving
the file with a .pgm
or .ppm
extension...you
should have a viewable image!
Your Task
Create classes called PPMImage and PGMImage in the
imageprocessing
package. These class should implement an
interface Image or extend an abstract class Image. Whether you use
inheritance or interfaces is up to you, but be sure you are able to
justify your choice. The image class/interface should define the
methods:
int getWidth()
which returns the image's widthint getHeight()
which returns the image's heightint[] getPixel(int r, int c)
which returns the pixel data at the given row and column.void setPixel(int r, int c, int[] pixel)
which sets the pixel data at the given row and column.String toString()
returns a string representation of the image that can be copy and pasted into a text editor to be saved as a ppm/pgm (this means the string must conform to the file format standards as listed above!).
int[] getPixel(int r, int
c)
that returns the values at the specified row and column. If
the image is a color image (a ppm) the colors should be in RGB order
with the R at index 0. You should define methods the two classes have
in common in the interface or abstract class, Image.
Create a file called ImageReader which takes a single String
representing the file name of the image to be read. An appropriate
response is required at this point if the file is invalid. When the
method Image produceImage()
is called, the image is
loaded from the file and returned. The image should not be loaded
until the produceImage method is called. Again something reasonable
(having to do with exceptions!) should be done in the case of
something going wrong (such as getPixelValues being called before the
image has been produced...).
Note that ImageReader should be able to read both PPM images and PGM images.
Create a class called ImageWriter whose constructor takes an Image and a file name and writes the image to the file.
In all cases, if your program can fail, it should fail gracefully! Use exceptions and assertions wherever appropriate!
Create a class called TimesTwo whose constructor takes only an Image
and and has a method Image produceImage()
that returns an
image identical to the image input into the constructor but twice the
size. That is, it scales the image by 2x.
A class for viewing your loaded images is provided along with some sample images. The class ImageViewer is a member of the imageprocessing package. Its constructor takes an Image and pops up a window with the image on the screen. Additionally you can use a number of programs freely available online to produce you own images; I recomend IrfanView.
Turn in (by 7/21 at 9:00pm):
- Image.java
- PPMImage.java
- PGMImage.java
- ImageReader.java
- ImageWriter.java
- Two (2) screenshots: one of an unscaled picture being viewed with the provided viewer class, and one of a scaled using TimesTwo being viewed with the provided viewer class.
- 1 image you created by hand.
- A thorough 1 page technical detailing the design decisions made in you project and other details of you implementation.
Part 2: . . .
A big surprise!