1. Trang chủ
  2. » Công Nghệ Thông Tin

Programming with Java, Swing and Squint phần 10 ppsx

35 293 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 35
Dung lượng 2,44 MB

Nội dung

Figure 11.7: The JFileChooser “Open File” dialog box new File( System.getProperty( "user.dir" ) ) will cause the dialog to start in the directory containing the program being executed. The File class is a part of the standard java libraries used to represent file path names. The construction shown here creates a new File object from the String returned by asking the System.getProperty method to look up "user.dir", a request to find the users’ home directory. To use the File class, you will have to include an import for "java.io.*" in your .java file. To display the dialog associated with a JFileChooser, a program must execute an invocation of the form chooser.showOpenDialog( this ) Invoking showOpenDialog displays the dialog box and suspends the program’s execution until the user clicks “Open” or “Cancel”. The invocation returns a value indicating whether the user clicked “Ope n” or “Cancel”. The value returned if “Open” is clicked is associated with the name JFileChooser.APPROVE OPTION. Therefore, programs that use this method typically include the invocation in an if statement of the form if ( chooser.showOpenDialog( this ) == JFileChooser.APPROVE OPTION ) { code to access and process the selected file } Finally, a String containing the name of the file selected by the user can be extracted from the JFileChooser using an invocation of the form chooser.getSelectedFile().getAbsolutePath() The getSelectedFile method asks the JFileChooser to return a File object describing the file chosen by the user. The getAbsolutePath method asks this File object to produce a String encoding the file’s path name. A program that uses a JFileChooser and an SImage constructor to load and display an image is shown in Figure 11.8. A picture of the interface produced by this program is s hown in Figure 11.9. 310 import javax.swing.*; import squint.*; import java.awt.*; import java.io.*; // An image viewer that allows a user to select an image file and // then displays the contents of the file on the screen public class ImageAndLikeness extends GUIManager { // The dimensions of the program’s window private final int WINDOW_WIDTH = 400, WINDOW_HEIGHT = 500; // Component used to display images private JLabel imageDisplay = new JLabel( ); // Dialog box through which user can select an image file private JFileChooser chooser = new JFileChooser( new File( System.getProperty( "user.dir" ) )); // Place the image display label and a button in the window public ImageAndLikeness() { this.createWindow( WINDOW_WIDTH, WINDOW_HEIGHT ); contentPane.add( imageDisplay ); contentPane.add( new JButton( "Choose an image file" ) ); } // When the button is clicked, display image selected by user public void buttonClicked() { if ( chooser.showOpenDialog( this ) == JFileChooser.APPROVE_OPTION ) { String imageFileName = chooser.getSelectedFile().getAbsolutePath(); SImage pic = new SImage( imageFileName ); imageDisplay.setIcon( pic ); } } } Figure 11.8: A simple image viewer 311 Figure 11.9: A picture of the Maguires displayed by the program in Figure 11.8 11.7 Think Negative We have seen that we can use a constructor to turn an array of brightness values into an SImage. It is also possible to turn an SImage into an array containing the brightness values of its pixels using a method named getPixelArray. This method is the final tool we need to write programs that process images. We can now create an SImage from a file on our disk, get an array containing its brightness values, change the values in this array to brighten, rotate, scale, crop, or otherwise modify the image, and then create a new SImage from the modified array of values. Perhaps the simplest type of image manipulation we can perform using these tools is a trans- formation in which each pixel’s brightness value is replaced by a new value that is a function, f, of the original value. That is, for each position in our array, we set pixels[x][y] = f( pixels[x][y] ) As an example of such a transformation, we w ill show how to convert an image into its own negative. Long, long ago, before there were computers, MP3 players, and digital cameras, people took pictures using primitive cameras and light sensitive film like the examples shown in Figure 11.10. In fact, some photographers still use such strange devices. The film used in non-digital cameras contains chemicals that react to light in such a way that, after being “developed” with other chemicals, the parts of the film that were not exposed to light become transparent while the areas that had been exposed to light remain opaque. As a result, after the film is developed, the image that is seen is bright where the actual scene was dark and dark where the scene was bright. These images are called negatives. Figure 11.11 shows an image of what the negative of the picture in Figure 11.1 might lo ok like. As an example of image manipulation, we will write a program to modify the brightness values of an image’s pixel so that the resulting values describe the negative of the original image. A sample of the interface our program will provide is shown in Figure 11.12. 312 Figure 11.10: Some antiques: A film camera and rolls of 120 and 35mm film Figure 11.11: A negative image Figure 11.12: Interface for a program that creates negative images 313 The function that describes how pixel values should be changed to produce a negative is simple. The value 0 should become 255, the value 255 should become 0, and everything in between should be scaled linearly. The appropriate function is therefore f(x) = 255 − x It is easy to apply this function to any single pixel. The statement pixels[x][y] = 255 - pixels[x][y]; will do the job. All we need to do is use loops to execute this statement for every pair of possible x and y values. To execute a statement for every possible value of x and y, we need som e way to easily determine the correct range of index values for an image’s table of pixels. The SImage class provides two methods that help. The methods getWidth and getHeight will return the number of columns and rows of pixels in an image repectively. Thus, we can use a loop of the form: int x = 0; while ( x < pixels.getWidth() ) { // Do something to all the pixels in column x x++; } to execute some statements for each possible x value. To execute some code for every possible combination of x and y values, we simply put a similar loop that steps through the y values inside of this loop. The result will look like: int x = 0; while ( x < pixels.getWidth() ) { int y = 0; while ( y < pixels.getHeight() ) { // Do something to pixels[x][y] y++; } x++; } This is an example of a type of nested loop that is frequently used when processing two dimensional arrays. The complete program to display negative images is shown in Figure 11.13. The nested loops are placed in the buttonClicked me thod between an instruction that uses getPixelArray to access the brightness values of the original image and a statement that uses an SImage construction to create a new image from the modified array of pixel values. 314 // A program that can display an image and its negative in a window public class NegativeImpact extends GUIManager { private final int WINDOW_WIDTH = 450, WINDOW_HEIGHT = 360; // The largest brightness value used for a pixel private final int BRIGHTEST_PIXEL = 255; // Used to display the original image and the modified version private JLabel original = new JLabel( ), modified = new JLabel( ); // Dialog box through which user can select an image file private JFileChooser chooser = new JFileChooser( ); // Place two empty labels and a button in the window initially public NegativeImpact() { this.createWindow( WINDOW_WIDTH, WINDOW_HEIGHT ); contentPane.add( original ); contentPane.add( modified ); contentPane.add( new JButton( "Show Images" ) ); } // Let the user pick an image, then display the image and its negative public void buttonClicked() { if ( chooser.showOpenDialog( this ) == JFileChooser.APPROVE_OPTION ) { String imageFileName = chooser.getSelectedFile().getAbsolutePath(); SImage pic = new SImage( imageFileName ); original.setIcon( pic ); // Replace every pixel’s value by its negative equivalent int [][] pixels = pic.getPixelArray(); int x = 0; while ( x < pic.getWidth() ) { int y = 0; while ( y < pic.getHeight() ) { pixels[x][y] = 255 - pixels[x][y]; y++; } x++; } modified.setIcon( new SImage( pixels ) ); } } } Figure 11.13: A program to display images and their negatives 315 11.8 for by for Each of the nested loops used in Figure 11.13 has the general form: int variable = initial value; while ( termination condition ) { statement(s) to do some interesting work . . . statement to change the value of variable; } Loops following this pattern are so common, that Java provides a shorthand notation for writing them. In Java, a statement of the form for ( α; β; γ ) { σ } where α and γ are statements or local variable declarations, 4 β is any boolean expression, and σ is any sequence of 0 or more statements and declarations, is defined to be equivalent to the statements α; while ( β ) { σ; γ } A statement using this abbreviated form is called a for loop. In particular, the for loop for ( int x = 0; x < pixels.getWidth(); x++ ) { statement(s) to process column x } is equivalent to the while loop int x = 0; whilte ( x < pixels.getWidth() ) { statement(s) to process column x x++; } To illustrate this, a version of the buttonClicked method from Figure 11.13 that has been revised to use for loops in place of its nested while loops is shown in Figure 11.14 We will be writing loops like this frequently enough that the bit of typing saved by using the for loop will be appreciated. More importantly, as you bec ome familiar with this notation, the for loop has the advantage of placing three key components of the loop right at the beginning where they are easy to identify. These include: 4 In all of our examples, α and γ will each be a single declaration or statement, but in general Java allows one to use lists of statements and declarations separated by commas where we have written α and γ. 316 // Let the user pick an image, then display the image and its negative public void buttonClicked() { if ( chooser.showOpenDialog( this ) == JFileChooser.APPROVE_OPTION ) { String imageFileName = chooser.getSelectedFile().getAbsolutePath(); SImage pic = new SImage( imageFileName ); original.setIcon( pic ); // Replace every pixel’s value by its negative equivalent int [][] pixels = pic.getPixelArray(); for ( int x = 0; x < pic.getWidth(); x++ ) { for ( int y = 0; y < pic.getHeight(); y++ ) { pixels[x][y] = 255 - pixels[x][y]; } } modified.setIcon( new SImage( pixels ) ); } } Figure 11.14: Code from Figure 11.13 revised to use for loops • the initial value, • the te rmination condition, and • the way the lo op moves from one step to the next There is, by the way, no requirement that all the components of a for loop’s header fit on one line. If the components of the header become complicated, is it good style to format the header so that they appear on separate lines as in: for ( int x = 0; x < pixels.getWidth(); x++ ) { statement(s) to process column x } 11.9 Moving Experiences An alternative to changing the brightness values of an image’s pixels is to simply move the pixels around. For example, most image processing programs provide the ability to rotate images or to flip an image vertically or horizontally. We can perform these operations by moving values from one position in a pixel array to another. To start, consider how to write a program that can tip an image on its side by rotating the picture 90 ◦ counterclockwise. We will structure the program and its interface very much like the 317 Figure 11.15: Window of a program that can rotate an image counterclockwise program to display an image and its negative shown in Figure 11.13. When the user clicks the button in this new program’s window, it will allow the user to select an image file, then it will display the original image and a rotated version of the image side by side in its window. A sample of this interface is shown if Figure 11.15. The only differences between the program that displayed negative images and this program will be found in the code that manipulates pixel values in the buttonClicked method. If the original image loaded by this program is m pixels wide and n pixels high, then the rotated image will be n pixels wide and m pixels high. As a result, we cannot create the new image by just moving pixel values around in the array c ontaining the original image’s brightness values. We have to create a new array that has n columns and m rows. Assuming the original image is named pic, the needed array can be constructed in a local variable declaration: int [][] result = new int[pic.getHeight()][pic.getWidth()]; Then, we can use a pair of nested loops to copy every value found in pixels into a new position within result. At first glance, it might seem that we can move the pixels as desired by repeate dly executing the instruction result[y][x] = pixels[x][y]; // WARNING: This is not correct! Unfortunately, if we use this statement, the image that results when our program is applied to the cow picture in Figure 11.15 will look like what we see in Figure 11.16. To understand why this would happen and how to rotate an image correctly, we need to do a little bit of analytic cow geometry. Figure 11.17 shows an image of a cow and a correctly rotated version of the same image. Both are accompanied by x and y axes corresponding to the scheme used to number pixel values in an array describing the image. Let’s chase the cow’s tail as its pixels move from the original image on the left to the rotated image on the right. In the original image, the y coordinates of the pixels that make up the tail fall between 20 and 30. If you lo ok at the image on the right, it is clear that the x coordintes of the tail’s new 318 Figure 11.16: A cow after completing a double flip Figure 11.17: Geometry of pixel coordinate changes while rotating an image position fall in the same range, 20-30. It seems as if y-coordinates from the original image become x-coordinates in the rotated image. On the other hand, in the original image, the x coordinates of the pixels that make up the tail fall between 200 and 210. The y coordinates of the same pixels in the rotated version fall in a very different range, 0 to 10! Similarly, if you look at the x-coordinate of the edge of the cow’s right ear in the original image it is about 10. In the rotated image, the edge of the same ear has an x coordinate of 200. It appears that small x coordinates become large y coordinates and large x coordinates become small y coordinates. What is happening to the x coordinates is similar to what happened to brightness values when we made negative images. To convert the brightness value of a pixel into its negative value, we subtracted the original value from the maximum possible brightness value, 255. Similarly, to convert an x coordinate to a y coordinate in the rotated image, we need to subtract the x coordinate from the maximum possible x coordinate in the original image. The maximum x coordinate in our cow image is 210. Using this value, the x coordinate of the tip of the tail, 207, become 210 − 207 = 3, a very small value as expected. Similarly, the x coordinate of the ear, 10, becomes 210 − 10 = 200. Therefore, the statement we should use to move pixel values to their new locations is result[y][(pic.getWidth() - 1) - x] = pixels[x][y]; 319 [...]... nested loops, see loops, nested NetConnection, 92 107 construction, 96–97, 106 in, 97, 106 hasNextLine, see hasNextLine nextLine, see nextLine nextInt, see nextInt next, see next methods addMessageListener, 104 , 107 close, 100 , 107 out, 97, 106 println, see println network event handling, 103 new, 20 next, 100 , 104 , 106 nextInt, 102 nextLine, 97 104 , 106 not, logical, 185 NullPointerException, 77 NumberFormatException,... 175 with doubles, 189 with ints, 188, 189 domain name, 88 Domain Name System, 88 double, 185–192 Double.parseDouble, 193 Eclipse, 15–18 else, 117 empty list, 288 endsWith, 209, 217 equal sign, 35 equals, 204–208, 217 error logic, 28 syntax, 27 escape sequence, 65 event, 7 event-driven programming, 7 event-handling methods, 14, 74, 156 buttonClicked, 14, 74 connectionClosed, 104 dataAvailable, 103 focusGained,... arrays that describe the image’s redness, greenness, and blueness, process each of them using scaleBrightnesses, and finally construct a new image with the results The code to do this is shown in Figure 11.37 For those who want to replace the somewhat repetitive code in Figure 11.37 with some loops, the SImage class provides an alternate method of working with the three arrays describing the colors that... accumulating loops, see loops, accumulating accumulator, 246 actual parameters, 13, 73 correspondence with formals, 142–144 add, 13, 72 addItem, 53, 71 addItemAt, 71 addition, 175 addMessageListener, 104 , 107 address IP, 88–89 algorithm, 3 American Standard Code for Information Interchange, see ASCII and, logical, 183 append, 64, 70 application protocol, 87 arguments, 13 arrays, 299–337 length, 326 constructions,... 34–37 right hand side, 46 AWT, see Abstract Windowing Toolkit back slash, 65 base 2, 124 base case, 268 binary, 124 block, 121 BlueJ, 15–18 boolean, 179, 192–194 as conditions, 194, 226 buttonClicked, 14, 74 byte code, 16 char, 214–216 class, 10, 135–168 as types, 182 338 body, 11 constructor, see constructor header, 10 instance, 12 client/server paradigm, 83 clients, 83–84 close, 100 , 107 code, 16... but practical and one that is more subtle and a bit esoteric First, Java provides a way for a program to determine the number of elements in any array If x is the name of an array, then x.length describes the number of elements in the array.5 We did not introduce this feature earlier, because it is difficult to understand how to use this feature with a two dimensional array before understanding that two... The location of the block to be averaged is provided through the parameters left and top that specify the coordinates of the left and top edges of the block The parameter size determines how wide and high the block should be As a result, the expressions left + size and top + size describe the coordinates of the right and bottom edges of the block These expressions are used in the termination conditions... 179–182 boolean, see boolean char, see char numeric, see double, float, int, long, short primitive value, 182 print, 99, 107 println, 97 100 , 106 private, 34, 166 private method, 166 program, 1, 6 programming, 7, 30 protocols, 82 application, 87 chat, see OSCAR mail, see SMTP, IMAP, and POP transport, 87, see TCP web, see HTTP public, 34 quotient, 188 recursion, 259–298 base case, 268 recursive case,... the same dimensions The first table is interpreted as the redness values for a new image’s pixels The second and third are interpreted as the greenness and blueness values respectively Therefore, if we declare 333 // A program that allows a user to select an image file and displays // the original and a series of copies ranging from 1/2 to 1/12 the original public class CheaperByTheDozen extends GUIManager... specified by giving the indices of its upper left corner and its size To add up the values in such a block, we will use a pair of doubly nested loops to iterate over all pairs of x and y coordinates that fall within the block These loops will look very much like the nested loops we have seen in early examples except that they will not start at 0 and they must stop when they reach the edges of the block . cow image is 210. Using this value, the x coordinate of the tip of the tail, 207, become 210 − 207 = 3, a very small value as expected. Similarly, the x coordinate of the ear, 10, becomes 210 − 10 = 200. Therefore,. shorthand notation for writing them. In Java, a statement of the form for ( α; β; γ ) { σ } where α and γ are statements or local variable declarations, 4 β is any boolean expression, and σ is any. JFileChooser and an SImage constructor to load and display an image is shown in Figure 11.8. A picture of the interface produced by this program is s hown in Figure 11.9. 310 import javax .swing. *; import

Ngày đăng: 12/08/2014, 23:22

TỪ KHÓA LIÊN QUAN