CS 215 ­ Fundamentals of Programming II Fall 2013 ­ Programming Project 4 Problem Statement 30 points

advertisement
CS 215 ­ Fundamentals of Programming II
Fall 2013 ­ Programming Project 4
30 points
Out: October 18, 2013
Due: October 28, 2013 (Monday)
Problem Statement
Images may be thought of as objects that can be manipulated. For example, we may want to rotate or flip an image. Or we may want to do some processing on the image like inverting the image. Images are described by giving their geometry (width and height) and a grid of pixel values.
Most image formats are binary formats that arrange the pixel components in various ways, usually to compress the data. However, there is a family of ASCII formats that we can read and write using regular C++ language file scanning and printing routines called the Portable Any Map (or PNM) formats. For this project we will use the plain Portable Grayscale Map (or PGM) format that can be used to represent grayscale images like the following (reduced to fit in this document).
In the "plain" PGM format, the above image is represented as follows:
P2
466 540
255
0
0
0
0
...
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
The first three lines are a "header" describing the characteristics of the image. The "P2" is a "magic" string that must be the first line of the file and tells programs this is a plain PGM file. The second line is the width (number of columns) and height (number of rows), respectively, of the image in pixels. The third line is the maximum 10/18/2013
Page 1 of 8
D. Hwang
possible pixel value in the file, usually and at most 255, but not always. The lines after this are the values for each pixel in the image starting with the upper left corner going left to right and top to bottom. The values range from 0 for black to the maximum pixel value for white. (The first pixels of the image above are all black.) Note that while this format is easy for humans to read, it is inefficient in space. This image is around 700 kilobytes in the PGM format, while the equivalent PNG format file is only about 53.6 kilobytes.
PGM files can be viewed using various image viewers. On Linux, emacs will display PGM files when loaded. To toggle between the visual image and the underlying text file, type Ctrl-c Ctrl-c. The program eog also can display PGM files (and most other image formats). Several PGM files will be made available in directory /home/hwang/cs215/project4 on csserver.
Specification for Image Class Data Attributes For this project, an Image is modeled using a dynamically­allocated two­dimensional array of integers, as demonstrated in lecture, to allow images of differing sizes to be created. Thus the data attributes include at least those shown below. You may add additional appropriate attributes.
Objects
Type
Name
width of image (number of columns)
int
width
height of image (number of rows)
int
height
maximum pixel value
int
max_value
pointer to (height x width) grid of pixel values
int**
grid
Operations ●
Explicit­value constructor ­ receives the width and the height of an image, and a maximum pixel value. Default values are given below. If initial_width or initial_height is 0, then the grid pointer should be initialized to the null pointer. This is state will be called an empty image.
Otherwise the constructor should dynamically allocate a two­dimensional grid of integers in the specified size as demonstrated in lecture, and initialize all elements to 0. Note: this will create a solid black image.
Analysis 10/18/2013
Objects
Default
Type
Movement
Name
initial width of image
0
int
received
initial_width
initial height of image
0
int
received
initial_height
maximum pixel value
255
int
received
initial_max
Page 2 of 8
D. Hwang
●
Copy constructor ­ creates a new Image that is identical to an existing one. Analysis Objects
Type
Movement
Name
source image object
Image
received
original
●
Destructor ­ deallocates the grid if the image is not empty
Analysis ­ no objects ●
swap – utility member function that swaps the contents of the received image with this image for use with operator=
Analysis
●
Objects
Type
Movement
Name
image object to swap with
Image
received & passed back
other
operator= ­ overloaded assignment operator member function. Makes an existing Image object identical to the source Image object. It is recommended that the technique given in the textbook and covered in lecture be used to implement this function.
Analysis ●
Objects
Type
Movement
Name
source Image object
Image
received
original
empty – returns true if there is no image currently loaded in this object (i.e., grid is the null pointer).
Analysis ●
Objects
Type
Movement
Name
result
bool
returned
­­­­­
get_width ­ returns the width of the image
Analysis 10/18/2013
Objects
Type
Movement
Name
width of image
int
returned
width
Page 3 of 8
D. Hwang
●
get_height ­ returns the height of the image
Analysis
●
Objects
Type
Movement
Name
height of image
int
returned
get_height
get_max_value ­ returns the maximum pixel value of the image
Analysis ●
Objects
Type
Movement
Name
maximum pixel value
int
returned
max_value
rotate_left ­ returns a new image that is this image rotated to the left 90 degrees.
Analysis ●
Objects
Type
Movement
Name
rotated image
Image
returned
new_image
flip_horizontal ­ returns a new image that is this image flipped about the horizontal axis
Analysis ●
Objects
Type
Movement
Name
horizontally flipped image
Image
returned
new_image
flip_vertical ­ returns a new image that is this image flipped about the vertical axis
Analysis ●
Objects
Type
Movement
Name
vertically flipped image
Image
returned
new_image
invert – returns a new image that is this image inverted
Analysis Objects
Type
Movement
Name
inverted image
Image
returned
new_image
The inverted value of a pixel value is simply the pixel value subtracted from the maximum pixel value.
10/18/2013
Page 4 of 8
D. Hwang
●
load – load an image from an input file stream attached to a PGM file. Assumes the file has been opened, and the input stream is at the beginning of the file and it is in a valid state. If the file does not contain a PGM image (i.e., the magic string is not "P2") it should throws a runtime_error exception (see notes below) without changing this image. Otherwise, this function should read the data from the file and store it in this image object. Note that the existing image is not likely to be the same size as the image in the file. A swapping technique similar to that recommended for operator= could be used here to make sure there are no memory leaks.
Analysis ●
Objects
Type
Movement
Name
input file stream
ifstream
received & passed back
in_file
write – writes this image to an output file stream. Assumes the file has been opened, and the output stream is in a valid state and nothing has been written to it. If the image is empty, it should not write anything. (I.e., do not write an image header).
Analysis Objects
Type
Movement
Name
output file stream
ofstream
received & passed back
out_file
The format of the output file is as shown above. The header information is written into the output file first. The magic string (P2) goes on a line by itself. The width and the height go on the second line with exactly one space in between. The maximum pixel value goes on the third line by itself. The pixel values are written in field widths of 4 with exactly 15 values on a line, except perhaps the last line. The last line of pixel values must end with an newline (but not two newlines).
Assignment (20 points) Write the implementation of the Image class specified above. The Image class definition must be put in header file image.h with suitable compilation guards. The implementations of the Image member functions must be put in source file image.cpp. The Image class must be implemented using a dynamically­allocated two­dimensional array as discussed in lecture. Projects that do not use a dynamically­allocated two­dimensional array will be returned for resubmission with late penalty. The member function names and the order of the parameters must be as specified above. Your code will be linked with a grading driver program that expects this. Note that all of the functions must be correct to receive full credit whether or not the main program uses them.
(10 points) Write a main program in file image_manipulator.cpp that is menu­driven and interactive. The program will have the concept of a current image and a new image that are both empty initially. Users use the following command set to load an image, create a new image that is a manipulation of the current image, and write the new image to a file. Commands may be entered in upper or lower case. An example run is shown below. Note that this program may or may not make use of all of the Image class operations.
10/18/2013
Page 5 of 8
D. Hwang
Command
Description
L
Load current image from file. Must handle any generated runtime_error exceptions by printing the error message contained in the thrown exception.
A
Create new image rotated 90 degrees left
B
Create new image flipped along horizontal axis
C
Create new image flipped along vertical axis
D
Create new image that is inverted
W
Write new image to file
Q
Quit the program
Unsuccessfully file opens should cause an error message to be printed and the command to be ignored.
You must submit a makefile named Makefile that creates an executable named image_manipulator for your project. It should conform to the examples as demonstrated in class. REMINDER: Your project must compile for it to be graded. Submissions that do not compile will be returned for resubmission and assessed a late penalty. Submissions that do not substantially work also will be returned for resubmission and assessed a late penalty.
Follow the guidelines in the C++ Programming Style Guideline handout. As stated in the syllabus, part of the grade on a programming project depends on how well you adhere to the guidelines. The grader will look at your code listing and grade it according to the guidelines. What to submit Electronically submit a tarfile containing files Makefile, image.h, image.cpp, and image_manipulator.cpp as explained in the handout Submission Instructions for CS 215. Do not submit object or executable files. The submission system will compile and test the Image class implementation against an autotest driver program. It will compile the project main program and check that an executable named image_manipulator is created, but will not run it The submission system will accept submissions no earlier than the evening of Monday, October 21.
Notes about using the runtime_error exception
Exception handling in C++ was covered in lecture on Monday, September 23, and is in Section 2.2 of the textbook. Here is a recap.
Standard exception classes, including runtime_error, are defined in the <stdexcept> library. These classes have an explicit­value constructor that has one received parameter that is a message string. This parameter generally is used to store an error message. There is one member function, what(), that returns the message string.
An exception is thrown when an error has occurred, such as trying to access a data structure with invalid indexes, by constructing an exception object and using the throw operator. Throwing an exception causes the function to terminate. For example, in the Image load function, the code to prevent trying to load data from a file that is not a plain PGM file might be:
10/18/2013
Page 6 of 8
D. Hwang
if (magic_string != "P2")
// construct and throw an exception object, terminates the function
throw runtime_error ("File is not a PGM image file.");
// everything is good, perform the load
In the main program, exceptions are caught and handled using a try-catch construct. The function call that may throw an exception is placed inside the try block, while the exception object is listed like a parameter in the catch block header. The handler code for the exception is placed in the catch block. For example, to catch an runtime_error exception thrown by the load function, the code might be:
try
{
cout << "Enter an input file name: ";
cin >> infile_name;
in.open(infile_name.c_str());
// code to check open succeed omitted
current_image.load(in);
} // end try
catch (const runtime_error & re) // the thrown exception object
{
// print out its message
cout << re.what() << " Try again!" << endl;
} // end catch
Sample run user@csserver:~$ ls
image_manipulator moon.pgm
user@csserver:~$ ./image_manipulator
Choose
L A B C D W Q -
from the following commands:
Load current image from file
Create new image rotated 90 degrees left
Create new image flipped along horizontal axis
Create new image flipped along vertical axis
Create new inverted image
Write new image to file
Quit the program
Enter your command: l
Enter name of image file to load into current image: moon.pgm
8< snip – menu list omitted in the rest of the sample run >8
Enter your command: a
Creating rotated image
Enter your command: w
Enter name of file to write new image: moon-rotated.pgm
10/18/2013
Page 7 of 8
D. Hwang
Enter your command: d
Creating inverted image
Enter your command: w
Enter name of file to write new image: moon-inverted.pgm
Enter your command: q
Bye!!
user@csserver:~$ ls
image_manipulator moon.pgm
user@csserver:~$
10/18/2013
moon-inverted.pgm
Page 8 of 8
moon-rotated.pgm
D. Hwang
Download