Assignment 6 (5B): See The Magic Due July  28 at 9:00pm and

In this assignment we continue to explore image processing.  Unless otherwise noted, everything that said about the first part of the assignment applies to this part, too.

All files   Back to Part I

Part 2: An Image Viewer and Transformer -- Turn in files here.

In Part One you read data from an input stream and saved it within IImage objects.  You used an external program, such as IrFanView, to render the file as an image on the screen.  Now that you know something about graphics and drawing in Java, you can create your own viewer.

When you wrote the produceTimesTwo method, you were producing one image from another.  Such an operation can be called a "filter".   Filters can be imagined to transform images for a wide variety of artistic and practical reasons.

The application you build in Part Two will have a window showing some buttons and two panels where images can be displayed.  The buttons cause file operations or image filters to take place.   Two required operations are "Load File" and "Save File" (your code from the IImageProcessor is called for this.)  Other buttons invoke filters.  A filter takes the image from the left-hand panel, transforms it, and displays the output image in the right-hand panel.  Don't panic about the buttons or about event handlers!  All that code is supplied.  Your focus is on displaying and filtering images.

Your Task

Create a Java application with a graphical interface, which can view and filter images.  A framework for the application is provided by the classes listed below.  Aside from understanding how it fits together, your main job will be implementing ImagePanel and the IImageFilter classes.

ImageFrame.java (supplied, but you can modify): a frame with image panels and a row of buttons.  You may modify this class to improve the appearance if you wish, but you should not make any substantive changes.
ImageButtonPanel.java (supplied, not modifiable): a panel holding buttons to activate the image operations.  This panel is displayed on the Image Frame.  When it is constructed, it will be given references to the objects (your classes) that actually perform the operations. 
ImagePanel.java (you create from scratch): This extension of AbstractImagePanel.java (supplied; the abstract class already extends JPanel) is capable of displaying an IImage object.  Much of your hard work in this project will be the writing and debugging of this class.  In addition to JPanel methods, ImagePanel has public methods getImage and setImage, specified by the abstract class.   The image, as displayed, should be a recognizable rendering of the original image, although the rendering doesn't have to be exactly what IrFanView would present.  The main idea is to draw small Shapes of appropriate size, position, and color to correspond to the pixels in the image being rendered.  (Don't overlook opportunities for creativity and experimentation here.  The shapes don't have to be rectangles or ovals...)  It is not necessary to strictly preserve the original size or aspect ratio (width/height) ratio, although a professional image viewer would have that capability.
Image Filters (you create; more about this below): An image filter satisfies the IImageFilter interface (supplied).  It takes an image and produces another image from it.  You should write a number of these filter classes and supply them to the ImageFrame (i.e., in ImageApplication when the frame is created).  They will then be available on the Image Frame as buttons.  Note: making the filters show up as buttons is automatic and won't take any changes by you to either the filter or the panel classes.
ImageApplication.java (you create or modify): A very small class, whose main method creates the ImageFrame. In doing so, it should supply all of the required and optional filters.  A sample of this class is supplied, which you will need to modify.
ImageProducerProcessor.java (you created):  If this class worked properly in the earlier part of the project, you should not need to modify it.  It is needed for loading and saving PGM and PPM files.
PGMImage, PPMImage (you created): If these worked properly in the earlier part of the project, you should not need to modify them.
JUnit test cases: no requirement this time.

Image Filters

Each image filter is a separate class, and must implement the IImageFilter interface.  The filter should take a valid image and produce a new valid image from it.   Read the comments in the code for more information.
"Doubler"
(required):  produces an image with pixels duplicated in both directions.  The produceTimesTwo code you wrote in ImageProducerProcessor should be usable, without modification, but you need to create an IImageFilter class to call that code.
"Copier" (required): produce an image that is identical to the original (but is not the same object).
"Lightener" (required): produce an image identical to the original except that the pixels are all slightly lighter in color.  If you applied this filter to its output repeatedly, the output would eventually be all white.
And in addition: Think up and implement at least 2 filters of your own.  Try to be imaginative.  Although there's no extra credit for insane creativity, we will somehow show off the filters so that people inside and outside the class can appreciate them.

Written reports

1. A written report along the usual lines, prepared by you and your partner together.
2. A diagram showing the relationships of all the classes used in the project (whether your own code, supplied code, libraries, etc.).  You may omit classes used by ImageButtonPanel from this analysis.  This will be a rather large diagram, so don't leave it to the last minute.  In fact, doing it before writing any code will help you to understand the project!
3. A confidential, printed report, one per person, which describes the extent and nature of your individual contributions to the project.

Getting Started

1. Think of a short nickname for your team.  This will be useful in naming your image filter classes so that names are unique.
2. Browse through all of the supplied code.
3. Consider doing the class diagram first (see "written reports" section).
4. As a warm-up, write a small application which paints an ellipse on a panel, right in the middle, and touching all four sides (or nearly).  Then make it so that if you resize the window, the ellipse is automatically redrawn properly (no, this doesn NOT require knowing anything about events!).  Then draw (four) equal-sized ellipses to fill the screen.  Figuring out how to position and scale shapes, as well as how to draw them, is an essential part of getting the ImagePanel to work, so this exercise is highly recommended.


Turn in (by 7/28 at 9:00pm, one per team):

Note on the supplied code:  All the code is new.  We sincerely hope there are no bugs that have to be fixed.  If there are they will be announced and new versions made available.  The ImageButtonPanel might be deliberately updated to improve its appearance or layout; this would be done in such a way that you could stay with the older version if you wished.