



Study with the several resources on Docsity
Earn points by helping other students or get them with a premium plan
Prepare for your exams
Study with the several resources on Docsity
Earn points to download
Earn points by helping other students or get them with a premium plan
An introduction to an image processing assignment in java. Students will learn how to store and manipulate .jpg images using classes rmoaimage and imageprocessor. They will also implement methods for filtering and transposing images. The assignment includes creating a gui with imagepanels and buttons for image manipulation.
Typology: Assignments
1 / 5
This page cannot be seen from the preview
Don't miss anything!




0. Introduction This assignment deals with .jpg images. You will learn about how images are stored; write code to transpose im- ages; and learn about filtering images. You will learn how a text message can be hidden in an image. You will see a little bit about how GUIS (Graphical User Interfaces) are constructed in Java. Finally, you will have practice with loops and one- and two-dimensional arrays. Download either file a6.zip or the files indicated on the course website and put them into a new folder. Two im- ages are included. Put everything in the same folder. To get an idea of what the program does, do this: (1) Open file ImageGUI in DrJava and compile it. (2) In the Interactions pane, type this: j= new ImageGUI(); A dialog window will open. Navigate to a folder that contains a jpg file and select it. A window will open, with two versions of the image, some but- tons, and a text area. The left image will not change; it is the original image. The right image will change as you click buttons. (3) See what buttons invert and hor reflect do. After any series of clicks on these, you can always click button restore to get back the original file. (4) You can try buttons transpose, ver reflect, and filter, but they won’t work until you write code to make them work. You can use procedure ImageGUI.writeImage to save the modified pictures on your hard drive. We discuss the classes in this assignment and also images. You don’t have to learn all this by heart, but you would do well to study the code, being conscious of how precise the specs are and how well the Java code is written. Section 7 explains what you have to do for this assignment, and Section 8 explains what you have to turn in. 1. Separation of concerns It is important to organize the parts of a program in a logical and coherent way such that it is clear what each part is responsible for and such that interactions are kept reasonable. The larger and more complicated the task of a pro- gram, the more important it is to have a good organization. This program has two main functions: manipulating an image and providing a GUI. These two issues should be separated as much as possible in the program. An object of class java.awt.Image maintains an image. Our own class RmoaImage maintains an image as a one-dimensional array of pixels, storing the pixels of the real two-dimensional array n row-major order (the ele- ments of row 0, then the elements of row 1, then the elements of row 2, etc.). RmoaImage provides methods for manipulating the image, allowing a user to process easily the pixels of an image row by row, column by column, or without regard to what row they are in. Class ImageProcessor provides methods for transforming the image, maintained as an RmoaImage. Im- ageProcessor knows nothing about the GUI; it simply calculates. It has fields that contain (the name of) the original and the transformed RmoaImage. Class ImagePanel provides part of the GUI. A subclass of JPanel, it can display an image through its method paint. When an image is changed in any way, the corresponding JPanel object has to be notified so that it can revise the size of the panel; updating the image and providing this notification are the purposes of method changeImageTo. Class ImageGUI provides the GUI. It places buttons and ImagePanels in the window, and it “listens” to but- ton clicks and acts accordingly, calling appropriate methods in ImageProcessor, then calling on an Im- agePanel to revise its view, and finally repainting the GUI. 2. Class Image and class RmoaImage An instance of class Image can contain a jpg image (or some other formats as well). Just how the image is stored is not our concern; the class hides such details from us. Abstractly, the image consists of a rectangular array of pixels (picture elements), where each pixel entry is an integer that describes the color of the pixel. We show a 3- by-4 array below, with 3 rows and 4 columns, where each Eij is a pixel. E00 E01 E02 E E10 E11 E12 E E20 E21 E22 E
An image with r rows and c columns could be placed in an int [][] array b[0..r-1][0..c-1]. Instead, however, class RmoaImage maintains the pixels in a one-dimensional array rmoArray[0..rc-1]. For the 3- by-4 image shown above, array map would contain the elements in row-major order: E00, E01, E02, E03, E10, E11, E12, E13, E20, … Class RmoaImage provides the representation of an image in its array rmoArray, along with methods for dealing with it. You can change the image by calling its methods getPixel(row,col), setPixel (row, col,v), and SwapPixels(a,b,i,j). So, for a variable im of class RmoaImage, to set a pixel to v, instead of writing something like im[h, k]= v; write image.setPixel(h, k, v);. You can also reference pix- els in row-major order in a one-dimensional array, using methods getPixel(p) and setPixel(p,v). That’s all you need to know in order to manipulate images in this assignment. Here’s more info on class RmoaImage. The constructor has this in it: rmoArray = new int[rc]; // Create the array to contain the images’ pixels PixelGrabber pg= new PixelGrabber(im, 0, 0, c, r, rmoArray, 0, c); pg.grabPixels(); This code stores in pg an instance of class PixelGrabber that has associated image im with our array rmoAr- ray. The third statement, pg.grabPixels();, stores the pixels of the image in rmoArray. Once an RmoaImage roa is created for an Image, methods roa.setPixel, roa.getPixels, and roa.SwapPixels can be used to manipulate the image.
3. Pixels and the RGB system Your monitor uses the RGB (Red-Green-Blue) system for images. Each RGB component is given by a number in the range 0..255 (8 bits). Black is represented by (0, 0, 0), red by (255, 0, 0), green by (0, 255, 0), blue by (0, 0, 255), and white by (255, 255, 255). The number of RGB colors is 2^24 =16,777,216. A pixel is stored in a 32-bit (4 byte) word. The red, green, and blue components each take 8 bits. The remaining 8 bits are used for the “alpha channel”, which is used as a mask to make certain areas of the image transparent —in those software applications that use it. We will not change the alpha channel of a pixel in this assignment. The ele- ments of a pixel are stored in a 32-bit word like this: alpha red green blue Suppose we have the green component (in binary) g = 01101111 and a blue component b = 00000111 , and suppose we want to put them next to each other in a single integer, so that it looks like this in binary: 0110111100000111 This number can be computed using g* 8 + b, but this calculation is inefficient. Java has an instruction that shifts bits to the left, filling the vacated spots with 0 ’s. We give three examples, using 16-bit binary numbers. 0000000001101111 << 1 is 0000000011011110 0000000001101111 << 2 is 0000000110111100 0000000001101111 << 8 is 0110111100000000 Secondly, operation | can be used to “or” individual bits together: 0110111100000000 | 0011 | 0000000010111110 1010 is 0110111110111110 is 1011 Therefore, we can put an alpha component alpha and red-green-blue components (r, (g, and b together into a single 32-bit int value —a pixel— using this expression: (alpha << 24) | (r << 16) | (g << 8) | b Take a look at method ImageProcessor.invert. For each pixel, the method extracts the 4 components of the pixel, inverts the red, green, and blue components (e.g. the inversion of red is 255 – red), reconstructs the pixel using the above formula, and stores the new pixel back in the image. 4. Class ImagePanel Read this section with class ImagePanel open in DrJava. A JPanel is a component that can be placed in a JFrame. We want a JPanel that will contain one Image. So, we make ImagePanel extend JPanel. 8 bits 8 bits 8 bits 8 bits
The transpose algorithm is fairly easy to write in terms of two-dimensional arrays. However, the algorithms will be a bit more complicated when the arrays involved are arrays of pixels making up an image. We suggest that, be- fore writing the code to manipulate the images, you write a static function to produce the transpose of a two- dimensional integer array b[0..r-1, 0..c-1], as well as a procedure to print (in the interaction pane) a rec- tangular array in order to help you debug your work. This practice makes code writing easier. You will then simply translate your code into the RmoaImage framework. The comments in the body of transpose should help you write the body. READ THEM CAREFULY. In ad- dition, use procedure ImageProcessor.hreflect as a model for accessing the elements of an RmoaImage. 7C. Implement method filter. In this method, you change each pixel of the image to consist only of grey, red, green, or blue, depending on the value of parameter color. Produce a “grey-scale image” by making all three com- ponents —red, green, blue— equal to the average of the original red, green, and blue values. (Handy quick test: white pixels stay white and black pixels stay black.) To filter it through red (and similarly through green and blue), make the green and blue components 0. This manipulation requires that you extract the alpha, red, green, and blue components from each pixel, construct the new pixel value, and store it. Look at procedure invert to see how this is done. 7D. Steganography , according to Wikipedia (en.wikipedia.org/wiki/Steganography), “is the art and science of writing hidden messages in such a way that no one apart from the intended recipient even realizes there is a hidden message.” In contrast, in cryptography, the existence of the message is not disguised but the content is obscured. Quite often, steganography deals with messages hidden in pictures. To hide a message, each character of the message can be hidden in one or two pixels of an image by modifying the red, green, and blue values for the pixel(s) so slightly that the change is not noticeable. Each character is represented using the American Standard Code for Information Interchange (ASCII) as a three- digit integer. We allow only characters that can be represented in ASCII —all the obvious characters you can type on your keyboard are ASCII characters. See page 6.5 of the ProgramLive CD for a discussion of ASCII. For the normal letters, digits, and other keyboard characters like $ and @, you can get its ASCII representation by casting the char to int. For example, ( int )'B' evaluates to the integer 66, and ( int )'k' evaluates to 107. We can hide character 'k' in a pixel whose RGB values are 199, 222, and 142 by changing each color compo- nent so that its least significant digit contains a digit of the integer representation 107 of 'k': Original pixel Pixel with 'k' hidden Red Green Blue hide 'k', which is 107 Red Green Blue 199 222 142 19 1 22 0 14 7 This change in each pixel is so slight that it will not —cannot— be noticed just by looking at the image. Decoding the message, the reverse process, requires extracting the last digit of each color value of a pixel and forming the ASCII value of a character from the three extracted values. In the above diagram to the right, extract 1, 0, and 7 to form 107, and cast this integer to char. Extracting the message does not change the image. The message stays in the image forever. Three problems for you to solve. You will write code to store a message m in the pixels of an image in row-major order, starting with pixel 0, 1, 2, … Think about the following issues and solve them. (1) You need some way to recognize that the image actually contains a message. Thus, you need to place something in pixels 0, 1, 2, … that has very little chance of appearing in a real image. You can’t ever be sure that an image without a message doesn’t start with those pixels, but the chances should be extremely small. (2) You have to know where the message ends. You can do this in several ways —place the length of the message in the first pixels in some way (how many pixels can that take?), put some unused character at the end of the message, or use some other scheme. You may assume that the message has fewer than one million characters. (3) The largest value of a color component (e.g. blue) is 255. Suppose the blue component is 252 and you try to hide 107 in this pixel; the blue component should be changed to 257, but this impossible because a color components are ! 255. We ask you to think about this problem, come up with at least two ways to solve the problem, and implement one of them. As you can see, this part of the assignment is less defined than the previous ones. You get to solve some little problems yourself. Part of this assignment will be to document and discuss your solutions.
Your task on part 7D (a) Decide on how you will solve the problems mentioned in points 1, 2, and 3 given above. As you design and im- plement this assignment, write a short essay that documents at least two solutions to each of the three problems men- tioned above, discusses their advantages and disadvantages, and indicates what your solutions are. Advantages could be: easiest to implement, fewest number of pixels used in hiding an image, least time spent in hiding a message — whatever. When you are finished with this assignment, insert this essay as a comment at the beginning of class Im- ageProcessor. Feel free to discuss points 1, 2, and 3 with the course staff. They will not tell you how to solve these problems. But they will discuss your ideas with you. (b) Complete the body of procedures hide and reveal in class ImageProcessor. These two methods will hide a message and reveal the message in the jpg image. When you design method reveal, make sure it attempts to extract the message only if its presence can be detected. In writing these methods, feel free to introduce others as they are needed, but make the additional methods pri- vate because they are not to be called by a user, but only by your program. Debugging hide and reveal can be difficult. We give you some hints on this at the end of this document. A note on static inner classes In class a few times, we created a class simply to collect a few variables together as fields and to provide meth- ods to manipulate them. Class Point, which contains a pair (x, y) of coordinates, was one example of this. If you feel the need to use such a class when writing part 7D, then declare it as a private static class at the end of class ImageProcessor —after the last method but before the “}” that ends the body of the class. Yes, you can declare “inner classes” this way, but make them static, so there is only one copy of it, and private, so that other classes can’t use it. Please introduce such a class ONLY if necessary, and talk to an instructor or a TA before you do it. Part 7D can be done without it, and most people will not need this additional class.
8. What to submit Start early, because you are sure to have questions! Waiting until the deadline will cause you frustration and lack of understanding, instead of the fun that should be felt in completing this assignment. Complete the bodies of proce- dures vreflect, transpose, filter, hide, and reveal in class ImageProcessor. Don’t change any- thing else (other than writing your private helper methods and, if necessary and after discussion, any static inner classes) —don’t declare new fields in the class and don’t change any of the other classes. Insert your essay (see the beginning of part 7D) into file ImageProcessor and submit the file on the CMS by the due date. Writing, testing and debugging hide and reveal Methods hide and reveal can be difficult to debug. Here some hints to help you.