// imageMain.java --- the "array of operations" implementation // with a "rotate the image" operation // // This main() method illustrates how to perform image operations: // - read an image from an input file. The user is asked to type a // file name. The file can be in gif, jpeg or bmp format. // - modify the image // rotate the image // apply a green filter to the top half, // apply a fading green filter across the whole image, // add vertical black bars to the image, // convert to a grayscale image // etc. // write an image to a bmp output file // quit // The user repeatedly selects which operations to apply. // // In this implementation, the operations are defined using an array. // Each element in the ops array is an instance of the abstract class ImageOp. // This class contains two strings and a method. One string is the menu // description. The other string contains the text that the user must // type in order to select the operation. The method contains the code // that carries out the operation. // Some advantages of using an array in this way: // - When a new image operation is added, there is only ONE place in // the code that has to be updated. A new element in the ops array // must be defined: in this part of the source code, all // three components of an image-operation are defined. // (In contrast, using the original code organization, the menu string // has to be typed in one part of the source code, the "user-string- // to-select-an-operation" has to be typed in another part of the source // code, and the method to implement the operation has to be typed in // yet another part of the source code.) // - The image operations can easily be reordered. Just swap the // two elements in the initialization of the ops array. // (In contrast, using the original code organization, several places // in the code have to be changed to reorder image operations.) // // Within the Java code, a colour image is represented using a // three-dimensional array. // The first index selects one row of the image. // The second index selects one column of the image. // The third index selects a colour (RED, GREEN, or BLUE). // For example, "testImage[3][5][RED]" is an integer value in the range // 0 to 255. A 0 indicates that there is no red colour at row 3, column 5 // in testImage. A 255 indicates that there is maximal red colour at // this location. // If RED, GREEN, and BLUE are all 0, the image appears black. If they // are all 255, the image appears white. // import java.util.*; import java.io.*; public class imageMain { // Give names to the constants used for the red, green and blue // values in an image. // The use of final variables is discussed on page 10-11 of the // Main textbook used in CISC124. // Red, green and blue are 8 bit quantities, each with a value // between 0 and 255. In a file, each pixel occupies a 32 bit word. // Since red, green and blue need a total of 24 bits, this leaves // 8 extra bits. These extra bits are called "offset". You never need // to change the value of the offset bits. final static int RED = 0; final static int GREEN = 1; final static int BLUE = 2; final static int OFFSET = 3; // ignore offset; use only red, green, blue // The console is used to receive input typed by the user. In this program, // the user is asked to type file names and command names. static public BufferedReader console = new BufferedReader(new InputStreamReader(System.in)); // --------------------------------- main ----------------------------- // The main method reads an input image file, and allows the user to // select from a set of modifications that can be applied to the image. public static void main(String[] args) { // Declare testImage, which is used to store an image as a 3D array. int[][][] testImage; System.out.println("Welcome to the Image Program."); System.out.println(""); // This program is supposed to be run without any arguments. // If the user supplies arguments, issue an explanatory message. if (args.length!=0) { System.out.println("Usage: java imageProgram"); System.exit(1); // exit. The exit code 1 indicates failure } // Ask the user for a file name and read the contents of this // file into "testImage". // After method "loadImage" completes, the size of the image // is available as follows: // - the number of rows is testImage.length // - the number of columns is testImage[0].length testImage = imageIO.loadImage(); // Repeatedly offer the user a list of operations to choose from. // The set of operations is defined in array ops. This array // is declared and initialized below. while (true) { System.out.println(""); System.out.println("What operation do you want to perform? "); // Go through the ops array to print information about each // of the available operations. The getMenuString() method // provides a string that describes the image operation. // The getTypeThis() method provides a string that the // user is supposed to type to select the image operation. // Print the menu items two per line. for(int i=0; i=0 && newrow=0 && newcol=0 && row=0 && col>>>>"); System.out.println("To get rid of black spots in the image, use method rotateImage2 instead..."); System.out.println("Have a look at the difference between methods rotateImage1 and rotateimage2."); } // end of op() for rotating the image }, // end of new ImageOp // ========================= topHalfGreen =============================== // Make the top half of the image green, while still allowing // red and blue to show through. This is done by visiting // rows 0 to MAXROWS/2. At each visited pixel, the GREEN value // is set to its maximum possible value, which is 255. new ImageOp("Green filter in top half", "TOPGREEN") { public void op(int[][][] img) { final int MAXROWS = img.length; final int MAXCOLS = img[0].length; for (int row=0; row 22) { img[row][col][RED] = 0; img[row][col][GREEN] = 0; img[row][col][BLUE] = 0; } // if col } // for col } // for row System.out.println("Vertical bars have been added."); } // end of op() for verticalBlackBars }, // end of new ImageOp new ImageOp("Convert to gray scale", "GRAY") { // ========================= grayScale =============================== // Convert the image from colour to grayscale. public void op(int[][][] img) { final int MAXROWS = img.length; final int MAXCOLS = img[0].length; for (int row=0; row 22) { img[row][col][RED] = 0; img[row][col][GREEN] = 0; img[row][col][BLUE] = 0; } // if mod } // for col } // for row System.out.println("Diagonal bars have been added."); } // end of op() for diagonalBlackBars }, // end of new ImageOp new ImageOp("Flip upside down", "FLIP") { // ========================= flipUpsideDown ======================== public void op(int[][][] img) { final int MAXROWS = img.length; for (int row=0; row