CS 302, Program 4

Program 4, Fall 2014: ImageMaker

  P4 TEAMS DUE before 4:00 PM on Friday, December 5th
  P4 CODE DUE before 4:00 PM on Friday, December 12th

[ P4 Announcements | Overview | Program | Components | Classes | GettingStarted | Sample Files | Shape String Format | Specifications | Milestones | Testing | Submission | Testing Server ]

[+] P4 Announcements

Tip: Don't save a copy of this write-up, you'll miss updates.

Corrections, clarifications, and other announcements regarding this programming assignment will be found in this section:

[+] Overview

Assignment Goals


For this assignment, you will create a program called ImageMaker that will read input files and generate new image files. To do this, your program will first read a background image file into a BufferedImage instance.  It will then provide options to the user including reading and parsing (intepret) an input file that contains a list of shapes.

The shape input files specify shapes to be added to the image using Shape Format lines. Your program must interpret the shape information and "draw" the filled shapes on to the background image internally.  The user won't see results until the save (write) the image to a file and view it with a program that can view jpg files.

The ImageMaker menu allows user to choose to output (write) the final result as jpg file.  The jpg file can then be opened by any program that can read jpg files. The user interface for this assignment includes command line arguments and a short user menu.  See Sample Files: misc-src, provided-src, and sample-runs.

Java has several classes that will help you read and write image files.  This write-up and the DemoBufferedImage.java program will get you started. 


[+] The Program

1. At the Start

At the start, display the welcome message "Welcome to ImageMaker" and then display the background image menu: 

1.a Start of program if there ARE NO command-line args:

Welcome to ImageMaker
Choose background image file:
1. red.jpg
2. green.jpg
3. blue.jpg
4. black.jpg
5. white.jpg
6. Load new image file

1.b Start of program if there ARE two command-line args.

If the command-line arguments are:  ocean_background.jpg jungle_background.jpg

Welcome to ImageMaker
Choose background image file:
1. ocean_background.jpg
2. jungle_background.jpg
3. Load new image file

To set command-line arguments for your program:

  1. Select Run -> Run Configurations from the menu.
  2. Select the Arguments tab.
  3. Enter the names of the background image files you wish to be available to the user at startup. See Configure_Run Configurations diagram.

The dimensions of the background image are the dimensions of the result image.  The background also represents the initial state of the image that will be made.  After a valid background image has been selected, display a message with the following format: 

 Background Image: white.jpg (576x384)

where the message displays the correct filename and the image dimensions (width x height) for the background image chosen. Such a message must be displayed when the background image is set at start and when it is changed via the menu. 

If the background file is already in the list of background images, do not add it to the list and display the message "filename.jpg is already in list"  and reprompt the user for a different file.

If the file chosen doesn't exist or otherwise can't be read into a BufferedImage object in your program, display the message "File not found" and re-prompt the user for a filename.


2. At the Main Menu

After a background file has been loaded, present the following menu which repeats until the user chooses Quit.

Main Menu
1. Change background image
2. Add shapes to shape list
3. Draw and fill shapes onto current background
4. Write current image to a file
5. Quit

[+] Components of the Program

1. Change background image

Displays a menu of background options to the user and lets them reset the internal (BufferedImage) to the background image that was selected. This option does not draw the shape list to the Graphics component of a BufferedImage (that only happens when user selects option 3). Also, do not clear the list of shapes.  See sample_run_01 for correct prompts and responses.

2. Add shapes to shape list

Displays a sub-menu that allows the user to select if they want to add shapes manually through the program's menu prompts, or read many shape descriptions from a file.  See sample_run_02_rect, sample_run_02_arc, sample_run_02_poly for correct prompts and responses.

3. Draw and fill shapes onto current background

Draw any shapes that are in the current list of shapes on to the internal buffered image.  See DemoBufferedImage.java file for example code that does this and modify it to work with the data structures you have used in your program.   See samples runs sample_run_02_rect and sample_run_02_arc for correct prompts and responses.

4. Write current image to a file

Prompts the user for a filename and then writes the current state of the internal buffered image to a file.  It does not draw the shape list to the Graphics component of a BufferedImage (that only happens when user selects option 3).  See DemoBufferedImage.java file for example code that does this and modify it to work with the data structures you have used in your program.   See sample_run_04 for correct prompts and responses.

5. Quit

Saves the current buffered image to a file name saved.jpg and exits the program.  See Sample Files for correct prompts and responses.


[+] Classes

Class You Are Required to Implement

ImageMaker (the main class)

The ImageMaker class must have the following and use this to launch the program.

public static void main(String [] args) { ... }
The main method used to launch your application.

Your class ImageMaker may also be instantiable (but this is not required).

Classes we Recommend you Define


An instantiable class that knows which shape the instance is and the values of each of its dimensions.  It can even have method to "draw itself on a java.awt.Graphics instance".


A config class with default values and constants, maybe some helper methods for user input.  

Pre-defined Classes You Will Likely Want to Import and Use (you are not limited to these classes)

java.awt.Color; - used to setColor of a Graphics instance (before drawing on that instance)
java.awt.Graphics; - can get from a BufferedImage and use this to setColor(), and then fillRect(), fillArc(), fillPolygon()
java.awt.image.BufferedImage - can read into BufferedImage from a file and can save a BufferedImage to a file
java.io.File - abstract representation of a file (for reading or writing)
java.io.FileNotFoundException - thrown when a file does not exist
java.io.IOException - thrown when a file can not be read
java.util.ArrayList - can keep expandable lists of filenames, and shape information
java.util.Scanner - for console input from the keyboard and for reading shape information from a file


[+] Getting Started

There is a demo program, but there are no program source code files provided for this project. The program design is somewhat up to you and worth 6-10% (3-5pts of 50) of your final program grade. We do require that the main() method that starts your application be inside a file called ImageMaker.java. To get the full design points, you must also have at least one instantiable class.  We recommend a Shape class that can be used to store information about any desired shape to be added to an image.

Create a new Java Project and add a class named ImageMaker.java that has a main method. This is the class that will be run as a Java Application.

DemoBufferedImage (demo program)

Download and add demo_in.jpg file and the DemoBufferedImage.java program source to your project to see a demonstration of how the java.awt.image.BufferedImage class can be used to read and write jpg image files from within a Java program.

CAUTION: Background image files must be placed in the current working directory and any image files that are written will be written to the current working directory. The project folder is the current working directory, even if you place your *.java files in a src folder.

yellow background == DemoBufferedImage ==> yellow background with rect, arc, and poly

The DemoBufferedImage.java program:

  1. reads in the demo_in.jpg (shown above left) to a BufferedImage object
  2. creates a Graphics object (from the BufferedImage)
  3. draws (fills) new shapes to the Graphics object
  4. writes the image file to demo_out.jpg file. (shown above right)


[+] Sample Files

We do provide several sample files, including background images, sample shape data files, sample runs showing program prompts and responses, and even a DemoBufferedImage.java program that you can run to learn how to read and write jpg files from Java.  You can view the jpg images your program creates in any browser or image viewer application.

misc-src Directory (background images and sample shapes files)

provided-src Directory (DemoBuffedImage.java file)

sample-runs Directory (Sample runs showing correct prompts and responses while program is running- more to come)



[+] Shape Format (Shape String Line formats)

The program must be able to read a file that contains shape information.  The shapes and their abbreviations are:

The shapes that are read in are not drawn on the image immediately.  Rather they are saved (in manner of your choosing) and then drawn on the image when the user makes that selection. Caution: the shapes must be drawn in the order they are added to the shape list to acheive the correct result as some shapes will draw over the top of previously drawn shapes.  This will allow the same sequence of shapes to be saved and drawn on multiple background image files if the user desires.

All shape input files will have this exact format. 

  1. One Shape String Line per shape
  2. Each shape line is a shape abbreviation (rect, arc, or poly) followed by the correct number of integer values.
  3. There will be no empty lines in any valid shape file.

Shape String Line formats (with abbreviations for the actual int values)

rect r g b x y w h
arc r g b x y w h a z
poly r g b n x1 y1 x2 y2 ... xN yN

Each possible shape (rect, arc, and poly) has its own format for the integer values that describe that shape's dimensions. The integer values in the above formats were chosen to make it easy to draw the shape on a java.awt.Graphics object.  Here is the key to the above abbreviations.


A red filled rectange that is 100 pixels wide and 75 pixels tall and has it upper left corner 20 pixels from left edge and 50 pixels from top edge would be described as:   rect 255 0 0 20 50 100 75

would be drawn onto a Graphics instance with code like this:
color = new Color(255,0,0);
int x = 20, y = 50, w = 100, h = 75;

A 180 degree filled blue arc (part of oval) that is within a bounded rectangle that is 30 pixels wide and 60 pixels tall with the bounding rectangle's upper left corner 200 pixels from left edge and 150 pixels from top edge:
  arc 0 0 255 200 150 30 60 0 180

would be drawn onto a Graphics instance with code like this:
color = new Color(0,0,255);
int x = 200, y = 150, w = 30, h = 60, a = 0, z = 180;

A connected filled green polygon with the following five points, A(35,10), B(105,56), C(60,77), D(53,55), E(25,75) would be described as:
  poly 0 255 0 5 35 10 105 56 60 77 53 55 25 75  

would be drawn onto Graphics with code like this:
color = new Color(0,255,0);
int [] xcoords = {35, 105, 60, 53, 25};
int [] ycoords = {10,  56, 77, 55, 75};

Note: a filled polygon automatically connects the last point back to the first point. See Sample Files for more examples of shapes string lines.

[+] Program Specifications


  1. Your main class that launches your program must be named ImageMaker.
  2. Your program must get all user input (keyboard) from a single Scanner instance. 
  3. Your program must not crash.  See samples for the user input conditions you must handle.  In general if you need an int in a given range, repeat prompt until int in that range has been entered.  If a file is not found, reprompt for a new file name.  If a file can not be read, or is an invalid format, exit program with the can't handle that message.
  4. Your program must maintain a dynamic list (array or ArrayList) of available background image filenames to be displayed to user in menu option 1.
  5. Your program must allow the user to change the background image without losing the shape information that has been previously entered.  The existing shape information is not drawn on the new background until selected by user.
  6. Your program must allow the user to enter shape information using the prompts described in that option.
  7. Your program must be able to read shape information from a file using the format described. Bad file formats should fail gracefully.
  8. Your program must be able to "draw" each shape onto the current image so that when the current image is written to a file, the shapes will be visible.  See our sample runs and corresponding image results.
  9. Your program must maintain a list (array or ArrayList) of added shapes that can be drawn onto any background as selected by user..


  1. Your program may use command-line arguments as described.
  2. Your program may display a usage message if insufficient or incorrect command-line arguments are given.

    Usage messages are messages that are displayed to users when a program is launched incorrectly. The usage message tells the user how to correctly run the program and includes information about the required command line arguments. If the command-line arguments are not correct, your program must display the following usage information message and exit:

    java ImageMaker [bg1] [bg2] ... [bgN]
    [bg1] is the name of an image file [optional]
    [bg2] is the name of an image file [optional]
    [bg3] is the name of an image file [optional]
    java ImageMaker red.jpg green.jpg blue.jpg black.jpg white.jpg

When grading, we will be testing the displayed output to the user and viewing the resulting saved image files.

[+] Development Milestones

We suggest that you incrementally develop this program by following the milestones in the order listed below. This order will make it easy for you to check that each milestone is working properly before you move on to the next one. Don't move on to a new milestone until you can convince yourself that the current milestone is working correctly. The further along you get, the harder it will be to detect errors in code you developed early on.

Note. In order to get any milestone working, you may have to edit classes not mentioned in the milestone description.

Hint. In addition to getting specific functionality in your program.  Think about the design choices you are making, would a method help, or a new class?  Having all code in a single main method (program 1) will lose 5 points of design, but can otherwise get full credit.  Having all code in a single class, with no instances created will lose you 3 points of design, but can otherwise get full credit.  Having all code in one class, with many methods, and only one instance of your own class created will lose 2 points of design.  To get all 5 points of design, you must have an instantiable class that is used to create multiple instances that are stored and used by your program.  We suggest a Shape class for this requirement.

[+] Testing

You should test your program by running and testing individual methods frequently as you develop. For example, writing methods for each option and unit testing them separately will help ensure that they work together when needed in later parts of the program. You can edit the DemoBufferedImage.java class or create your own test class.

It is to your advantage to always have a compiling program so that you can run it and see what it does. If you follow the milestones outlined above, you should be able to verify whether you have completed each milestone by running your program and interacting with it.

[+] Submission

Before handing in your program, check that you've done the following:

Use the CS302 Forms Page to electronically submit and backup your work:

Submit these files: