CS111, Wellesley College, Fall 2007

Problem Set 9

Due on Tuesday, December 4 at the start of class

Reading

  • PicOps contract
  • Color contract
  • split method in String class
  • parseInt method in Integer class
  • BufferedReader contract
  • BufferedWriter contract
  • About this Problem Set

    The purpose of this problem set is to give you experience with arrays, I/O, and writing your own classes from scratch.

    All code for this assignment is available in the ps09_programs folder in the cs111d download directory on the cs server.

    How to turn in this Problem Set

    You are required to turn in both a hardcopy and a softcopy. For general guidelines on problem set submission, including how to submit a softcopy and how to check if you softcopy submission was successful, click here. Please make sure to keep a copy of your work, either on a zip disk, or in your private directory (or, to play it safe, both).

    Hardcopy Submission

    Your hardcopy packet should consist of:
    1. The cover page;
    2. Your modified Pic.java file.
    Staple these together, and submit them at the start of class on the due date.

    Softcopy Submission

    You should submit your final version of your ps09_programs folder. In particular, the Pic subfolder should contain your final version of Pic.java.

    Task 1: Image Manipulations

    Background

    As discussed in Lecture #20, images can be represented in a computer as a 2-dimensional (2D) array of pixels. Pixels can be encoded in different ways, e.g., as Colors or as integers. For instance, two images are shown below along with representations of the two images as 2D arrays of pixels (one 16x16 pixels and one 8x8 pixels), where each pixel is encoded as an integer (0 encodes the Color Black, -1 encodes the Color White, and -65536 encodes the Color Red).

    -100-1-100-1-1000000-1
    -100-1-100-1-1000000-1
    -100-1-100-1-1-1-100-1-1-1
    -100-1-100-1-1-1-100-1-1-1
    -100-1-100-1-1-1-100-1-1-1
    -100-1-100-1-1-1-100-1-1-1
    -100-1-100-1-1-1-100-1-1-1
    -1000000-1-1-1-100-1-1-1
    -1000000-1-1-1-100-1-1-1
    -100-1-100-1-1-1-100-1-1-1
    -100-1-100-1-1-1-100-1-1-1
    -100-1-100-1-1-1-100-1-1-1
    -100-1-100-1-1-1-100-1-1-1
    -100-1-100-1-1-1-100-1-1-1
    -100-1-100-1-1000000-1
    -100-1-100-1-1000000-1
      
    -65536-6553600-65536-6553600
    -65536-6553600-65536-6553600
    00-65536-6553600-65536-65536
    00-65536-6553600-65536-65536
    -65536-6553600-65536-6553600
    -65536-6553600-65536-6553600
    00-65536-6553600-65536-65536
    00-65536-6553600-65536-65536

    There are many different formats for storing images in files on a computer. Some popular formats include JPEG, GIF, PNG, and BMP. For this task, we will be storing images in text files, though you can easily convert back and forth between formats using operations found in the PicOps class below. The text files we will use contain 2D integer array representations of an image. The first line of the text file must contain two integers, separated by a single space " ", representing the height (i.e., number of rows of pixels) in the image and the width (i.e., number of columns of pixels) in the image, respectively. Following the first line, there are height further lines in the text file, each containing width integers separated by a single space, " ". Here are three examples of text files containing image representations: hi.txt, checkerBoard.txt, and MonaLisa.txt.

    In this problem, you will write code to read in a file containing a 2D array of integers representing the pixels of an image. You will then perform various manipulations of the image, such as mirroring the image, cropping the image, shrinking the image, and rotating the image. For example, the figures below represent an image as well as mirrored, cropped, shrunk, and rotated versions of the image.

    Original image Mirrored image Cropped image Shrunk image Rotated image

    Your Task

    One of the main aims of this problem is to give you practice writing a class from scratch. Your task is to create from scratch your own Pic class to represent an image and support various image manipulation operations. To do this, you will need to think carefully about appropriate declarations in the Pic class, such as instance variables, class variables, constructors, instance methods, and class methods. Your program will be evaluated, not only on the basis of correctness, but also on appropriateness of class declarations.

    At a minimum, your Pic class should have the following 1 constructor, 9 instance methods, and 3 class method.

    1. public Pic (String textFileName) throws IOException
      Constructor that initializes appropriate instance variables of a newly created Pic object. The constructor should read in an image from the text file specified by the String argument. The text file is assumed to contain a 2D integer array representation of an image. Since the constructor, or some helper method that it may invoke, reads in a file, the method may throw an IOException.
    2. public int getHeight ()
      Returns the height of this image, i.e., the number of rows of pixels in the image.
    3. Examples:
      getHeight() invoked on the HI image above returns 16.
      getHeight() invoked on the checkerBoard image above returns 8.
      getHeight() invoked on the MonaLisa image above returns 520.
      getHeight() invoked on the Mt_Baker image below returns 333.

    4. public int getWidth ()
      Returns the width of this image, i.e., the number of columns of pixles in the image.
    5. Examples:
      getWidth() invoked on the HI image above returns 16.
      getWidth() invoked on the checkerBoard image above returns 8.
      getWidth() invoked on the MonaLisa image above returns 334.
      getWidth() invoked on the Mt_Baker image below returns 500.

    6. public int getPixel (int row, int col)
      Returns an integer corresponding to the pixel in this image at the specified row and column. The first row of pixels in the image has index 0 and the first column of pixels in the image has index 0. Assumes the given row and column are within the bounds of the image, i.e., row is in the range [0, getHeight()-1] and col is in the range [0, getWidth()-1].

      Examples:
      getPixel(1, 4) invoked on the HI image above returns -1.
      getPixel(1, 4) invoked on the checkerBoard image above returns -65536.
      getPixel(1, 4) invoked on the MonaLisa image above returns -11248061.
      getPixel(1, 4) invoked on the Mt_Baker image below returns -9120807.

    7. public void setPixel (int row, int col, int value)
      Sets the pixel in this image at the specified row and column to the corresponding value specified by the integer argument value. The first row of pixels in the image has index 0 and the first column of pixels in the image has index 0. Assumes the given row and column are within the bounds of the image, i.e., row is in the range [0, getHeight()-1] and col is in the range [0, getWidth()-1].
    8. public int[][] getPixArray ()
      Returns a new 2D integer array corresponding to the pixels of this image. Modifications to the returned array should not affect this image.
    9. public void mirror ()
      Flips this image horizontally, i.e., around the vertical axis.
    10. Example:
      Mt_Baker mirror()

    11. public void crop (int row1, int col1, int row2, int col2)
      Crops this image to the specified rectangular region. The first two arguments correspond to the location (row and column) of the upper left corner of the rectangular region, and the last two arguments correspond to the location (row and column) of the lower right corner of the rectangular region. Assumes the given locations are valid, i.e., the specified rows and columns are within the bounds of the image, the first argument is less than the third argument, and the second argument is less than the fourth argument.
    12. Example:
      Mt_Baker crop(25, 150, 300, 350)

    13. public void shrink ()
      Shrinks this image in size by 1/4 by omitting every other row and every other column. If there is an odd number of rows or columns, then the final row or column is omitted, respectively.
    14. Example:
      Mt_Baker shrink()

    15. public void rotate90 ()
      Rotates this image 90 degrees clockwise.
    16. Example:
      Mt_Baker rotate90()

    17. public static int[][] readInTextFile (String textFileName) throws IOException
      Returns a new 2D integer array that corresponds to the image represented in the text file specified by the String argument. The text file is assumed to contain a 2D integer array representation of an image. Since the method reads in a file, it may throw an IOException.
    18. Notes:

    19. public static void outputTextFile (String textFileName, int[][] pix) throws IOException
      Outputs the given 2D integer array to a text file with the given name, so that the text file contains a 2D integer array representation of an image. Since the method outputs a file, it may throw an IOExceoption.
    20. Notes:

    21. public static void main (String[] args) throws IOException
      When your application is executed, e.g., by typing java Pic display MonaLisa.txt in the Interactions pane in Dr. Java, the main method will be invoked, and any command line arguments (i.e., display and MonaLisa.txt in the example above) will be referred to by the String array parameter args in the main method. The main method should process the command line arguments, referred to by args, and perform the appropriate image operations. The main method should process 13 different sets of command line arguments:
      1. If the first command line argument is display and the second is the name of a file containing an image representation, then the program should display the image in a new frame.
      2. If the first command line argument is toTextFile and the second is the name of an image file (e.g., JPEG, GIF, PNG, or BMP), then the program should output the image to a text file containing a 2D integer array representation of the image.
      3. If the first command line argument is textFileToJPEG and the second is the name of a text file containing an image representation, then the program should output the image to a JPEG file.
      4. If the first command line argument is getHeight and the second is the name of a text file containing an image representation, then the program should output the height (i.e., number of rows of pixels) of the image.
      5. If the first command line argument is getWidth and the second is the name of a text file containing an image representation, then the program should output the width (i.e., number of columns of pixels) of the image.
      6. If the first command line argument is getPixel, the second is a String representing an integer row, the third is a String representing an integer column, and the fourth is the name of a text file containing an image representation, then the program should output the integer value of the specified pixel in the image.
      7. If the first command line argument is setPixel, the second is a String representing an integer row, the third is a String representing an integer column, the fourth is a String representing an integer value of a pixel, and the fifth is the name of a text file containing an image representation, then the program should display an image in a new frame, where the displayed image corresponds to that in the text file, except that the value of the specified pixel in the image has been set to the specified value.
      8. If the first command line argument is getPixArray and the second is the name of a text file containing an image representation, then the program should create a new Pic object and display in a new frame the 2D integer array returned by invoking getPixelArray on the new Pic object.
      9. If the first command line argument is mirror, the second is the name of a text file containing an image representation, and the third is the name of a text file to which an image representation will be output, then the program should display a mirrored version of the image represented by the text file in the second command line argument and output the mirrored image to the text file named by the third command line argument.
      10. If the first command line argument is crop, the second is a String representing an integer row of the upper left corner of a rectangle, the third is a String representing an integer column of the upper left corner of a rectangle, the fourth is a String representing an integer row of the lower right corner of a rectangle, the fifth is a String representing an integer column of the lower right corner of a rectangle, the sixth is the name of a text file containing an image representation, and the seventh is the name of a text file to which an image representation will be output, then the program should display a cropped version of the image represented by the text file in the sixth command line argument and output the cropped image to the text file named by the seventh command line argument.
      11. If the first command line argument is shrink, the second is the name of a text file containing an image representation, and the third is the name of a text file to which an image representation will be output, then the program should display a shrunken version of the image represented by the text file in the second command line argument and output the shrunken image to the text file named by the third command line argument.
      12. If the first command line argument is rotate90, the second is the name of a text file containing an image representation, and the third is the name of a text file to which an image representation will be output, then the program should display a rotated version of the image represented by the text file in the second command line argument and output the rotated image to the text file named by the third command line argument.
      13. If the first command line argument is readInTextFile and the second is the name of a text file containing an image representation, then the program should create a new Pic object corresponding to the image contained in the text file and then display the image in a new frame.

      For example, the figure below illustrates example executions of the Pic program.

      The final line (java Pic display MonaLisa_rotate180_crop.jpg) in the examples above would result in the following image being displayed.

      Since the main method, or some helper method that it may invoke, reads or writes to a file, the method may throw an IOException.

    To aid you in designing and testing your Pic class, we have provided you with a number of helpful methods in the PicOps class. The methods in the PicOps class are all class methods and may be invoked, e.g., by typing PicOps.display("MonaLisa.jpg"), either in the Dr. Java Interactions pane or in your Pic class. The following 8 methods are available in the PicOps class for you to use.

    As an example of how these PicOps methods may be useful to you when designing and testing your Pic class, consider the following example strategy:

    To experiment with a working version of a solution to this problem, run the application Pic_Solutions (provided in the Pic folder in the ps09_programs folder) from the Dr. Java Interactions pane with appropriate command line arguments, e.g., java Pic_Solutions display MonaLisa.txt. Your solution should behave similar to this sample solution application.