| [Page 59 (continued)]|
3.6. Working with Media
What if we want to create and manipulate media like pictures or sounds? Just as we created the World and Turtle classes to define what we mean by these to the computer we have created Picture and Sound classes.
3.6.1. Creating a Picture Object
How would you create a picture? The syntax for creating an object is
Try entering the following in the interactions pane.
> System.out.println(new Picture()); Picture, filename null height 100 width 200
It looks like we created a Picture object with a height of 100 and a width of 200, but why don't we see it? New objects of the class Picture aren't shown automatically. You have to ask them to show themselves using the message show(). So let's ask the Picture object to show itself. Oops, we forgot to declare a variable to refer to the Picture object, so we don't have any way to access it. Let's try it again and this time declare a variable for it. The syntax for declaring a variable is type name; or type name = expression;. The type is the name of the class so we will use a type of Picture. What should the name be? Well the name should describe what the object is so let's use picture1.
> Picture picture1 = new Picture(); > picture1.show();
Now we can see the created picture in Figure 3.11.
Figure 3.11. Creating a Picture object using new Picture().
Why doesn't it have anything in it? When you create a Picture object using new Picture() the default width is 200 and the default height is 100 and the default is that all of the pixels in the picture are white. How can we create a picture from data in a file from a digital camera? We can use new Picture(String fileName) which takes an object of the String class which is the fully qualified file name of a file to read the picture information from.
What is the fully qualified file name of a file? The full or complete name of a file is the path to the file as well as the base file name and extension. How can we get the full file name for a file? One way is to use another class we have created for you. The FileChooser class has a class method pickAFile() which will display a dialog window that will help you pick a file.
Common Bug: File Chooser doesn't Appear
If you don't see the window with the file chooser in it after typing in the code above, try minimizing your DrJava window. Sometimes the file chooser comes up behind the DrJava window.
You're probably already familiar with how to use a file chooser or file dialog as shown in Figure 3.12:
Double-click on folders/directories to open them.
Click on the top right iconic button to see the details about the files such as the types of files they are (if you put the cursor over the button and leave it there it will show "Details"). To create a picture we want to pick a file with a type of "JPEG Image". To create a sound we would pick a file with a type of "Wave Sound".
Click on the file name to select it and then click OPEN, or double-click, to select a file.
Figure 3.12. The File Chooser. (This item is displayed on page 60 in the print version)
Once you select a file, what gets returned is the full file name as a string (a sequence of characters). (If you click CANCEL, pickAFile() returns null which is a predefined value in Java that means that it doesn't refer to a valid object). Try it, type the code below after the > in the interactions pane and select a file by clicking the mouse button when the cursor points to the desired file name, then click on the OPEN button.
> System.out.println(FileChooser.pickAFile()); C:\intro-prog-java\mediasources\flower1.jpg
What you get when you finally select a file will depend on your operating system. On Windows, your file name will probably start with C: and will have backslashes in it (e.g., \). There are really two parts to this file name:
The character between words (e.g., the \ between "intro-prog-java" and "mediasources") is called the path separator. Everything from the beginning of the file name to the last path separator is called the path to the file. That describes exactly where on the hard disk (in which directory) a file exists. A directory is like a drawer of a file cabinet and it can hold many files. A directory can even hold other directories.
The last part of the file (e.g., "flower1.jpg") is called the base file name. When you look at the file in the Finder/Explorer/Directory window (depending on your operating system), that's the part you see. The last three characters (after the period) are called the file extension. They identify the encoding of the file. You may not see the extension depending on the settings you have. But, if you show the detail view (top right iconic button on the file chooser) you will see the file types. Look for files of type "JPEG Image".
Files that have an extension of ".jpg" or a type of "JPEG Image" are JPEG files. They contain pictures. (To be picky, they contain data that can be interpreted to be a representation of a picturebut that's close enough to "they contain pictures.") JPEG is a standard encoding (a representation) for any kind of image. The other kind of media files that we'll be using frequently are ".wav" files (Figure 3.13). The ".wav" extension means that these are WAV files. They contain sounds. WAV is a standard encoding for sounds. There are many other kinds of extensions for files, and there are even many other kinds of media extensions. For example, there are also GIF (".gif") files for images and AIFF (".aif" or ".aiff") files for sounds. We'll stick to JPEG and WAV in this text, just to avoid too much complexity.
Figure 3.13. File chooser with media types identified. (This item is displayed on page 62 in the print version)
3.6.2. Showing a Picture
So now we know how to get a complete file name: path and base name. This doesn't mean that we have the file itself loaded into memory. To get the file into memory, we have to tell Java how to interpret this file. We know that JPEG files are pictures, but we have to tell Java explicitly to read the file and make a Picture object from it (an object of the Picture class).
The way we create and initialize new objects in Java is to ask the class to create a new object using new ClassName(parameterList). The class contains the description of the data each object of the class needs to have so it is the thing that knows how to create objects of that class. You can think of a class as a factory for making objects of that class. So, to create a new object of the Picture class from a file name use new Picture(fileName). The fileName is the name of a file as a string. We know how to get a file name using FileChooser.pickAFile().
> System.out.println(new Picture(FileChooser.pickAFile())); Picture, filename c:\intro-prog-java\mediasources\beach-smaller.jpg height 360 width 480
The result from System.out.println suggests that we did in fact make a Picture object, from a given filename and with a given height and width. Success! Oh, you wanted to actually see the picture? We'll need another method! The method to show the picture is named show().
You ask a Picture object to show itself using the method show(). It may seem strange to say that a picture knows how to show itself but in object-oriented programming we treat objects as intelligent beings that know how to do the things that we would expect an object to be able to do, or that someone would want to do to it. We typically show pictures, so in object-oriented programming Picture objects know how to show themselves (make themselves visible).
3.6.3. Variable Substitution
We can now pick a file, make a picture, and show it in a couple of different ways.
We can do it all at once because the result from one method can be used in the next method: new Picture(FileChooser.pickAFile()).show(). That's what we see in Figure 3.14. This code will first invoke the pickAFile() class method of the class FileChooser because it is inside the parentheses. The pickAFile() method will return the name of the selected file as a string. Next it will create a new Picture object with the selected file name. And finally it will ask the created Picture object to show itself.
Figure 3.14. Picking, making, and showing a picture, using the result of each method in the next method. The picture used is beach-smaller.jpg.
The second way is to name each of the pieces by declaring variables. To declare a variable (a name for data) use type name; or type name=expression;.
Making it Work Tip: Types in Java
A type in Java can be any of the predefined primitive types (char, byte, int, short, long, float, double, or boolean) or the name of a class. Java is not a completely object-oriented language in that the primitive types are not objects.
Why are there so many primitive types? The answer has to do with how many bits you want to use to represent a value. The more bits you use the larger the number that you can store. We will only use int, float, double, and boolean in this book. The type int is for integer numbers and takes up 32 bits. The type float is for floating point numbers and takes up 32 bits. The type double is for floating point numbers and takes up 64 bits. The type boolean is for things that are just true or false so a boolean value could be stored in just 1 bit. However, how much space a boolean takes isn't specified in the Java language specifications (it depends on the Virtual Machine). Java uses primitive types to speed calculations.
A class name used as a type can be either a class defined as part of the Java language like (String, JFrame, or BufferedImage) or a class that you or someone else created (like the Picture class we created).
Try the following in the interactions pane. Pick a file name that ends in ".jpg".
> String fileName = FileChooser.pickAFile(); > Picture pictureObj = new Picture(fileName); > pictureObj.show();
As you can see we can name the file that we get from FileChooser.pickAFile() by using (String fileName =). This says that the variable named fileName will be of type String (will refer to an object of the String class) and that the String object that it will refer to will be returned from FileChooser.pickAFile(). In a similar fashion we can create a variable named pictureObj that will refer to an object of the Picture class that we get from creating a new Picture object with the fileName using Picture pictureObj = new Picture(fileName). We can then ask that Picture object to show itself by sending it the show() message using pictureObj.show(). That's what we see in Figure 3.15.
Figure 3.15. Picking, making, and showing a picture, when naming the pieces. The picture shown is tammy.jpg. Tammy is computer science graduate student at Georgia Tech. (This item is displayed on page 65 in the print version)
Making it Work Tip: Java Conventions
By convention all class names in Java begin with an uppercase letter, all variable and method names begin with a lowercase letter. This will help you tell the difference between a class name and a variable or method name. So, Picture is a class name since it starts with a uppercase letter and pictureObj is a variable name since it starts with a lowercase letter. If a name has several words in it, the convention is to uppercase the first letter of each additional word like pickAFile(). A convention is the usual way of doing something, which means that the compiler won't care if you don't do it this way, but other programmers will tar and feather you because it will make your programs harder to understand.
Debugging Tip: Method Names must be Followed by Parentheses!
In Java all methods have to have parentheses after the method name both when you declare the method and when you invoke it. You can't leave off the parentheses even if the method doesn't take any parameters. So, you must type pictureObj.show() not pictureObj.show.
If you try pictureObj.show(), you'll notice that there is no output from this method. Methods in Java don't have to return a value, unlike real mathematical functions. A method may just do something (like display a picture).
3.6.4. Object References
When the type of a variable is int or double or boolean we call that a primitive variable. As you have seen when a primitive variable is declared space is reserved to represent that variable's value and the name is used to find the address of that reserved space. If the type is int then 32 bits of space (4 bytes) is reserved. If the type is double then 64 bits of space (8 bytes) is reserved.
When the type of a variable is the name of a class (like String) then this is called an object variable or object reference. Unlike primitive variables, object variables do not reserve space for the value of the variable. How could they? How much space do you need for an object? How about an object of the class String? How about an object of the class Picture? The amount of space you need for an object depends on the number and types of fields (data) each object of that class has.
Object variables (references) reserve space for a reference to an object of the given class. A reference allows the computer to determine the address of the actual object (it isn't just the address of the object). If the object variable is declared but not assigned to an object the reference is set to null which means that it doesn't refer to any object yet.
3.6.5. Playing a Sound
We can replicate this entire process with sounds.
We still use FileChooser.pickAFile() to find the file we want and get its file name.
We use new Sound(fileName) to make a Sound object using the passed fileName as the file to read the sound information from.
We will use play() to play the sound. The method play() is an object method (invoked on a Sound object). It plays the sound one time. It doesn't return anything.
Here are the same steps we saw previously with pictures:
> System.out.println(FileChooser.pickAFile()); C:\intro-prog-java\mediasources\croak.wav > System.out.println(new Sound(FileChooser.pickAFile())); Sound file: croak.wav length: 17616 > new Sound(FileChooser.pickAFile()).play();
The FileChooser.pickAFile(); allows you to pick a file with a file chooser and the System.out.println that is around this displays the full file name that was picked. The code System.out.println(new Sound(FileChooser.pickA-File())); also allows you to pick a file, then it creates a sound object from the full file name, and finally it displays information about the sound object: the file name, and the length of the sound. We'll explain what the length of the sound means in Chapter 8. The code new Sound(FileChooser.pickAFile()).play(); has you pick a file name, creates the sound object using that file name, and tells that sound object to play.
Please do try this on your own, using WAV files that you have on your own computer, that you make yourself, or that came on your CD. (We talk more about where to get the media and how to create it in future chapters.)
3.6.6. Naming Your Media (and other Values)
The code new Sound(FileChooser.pickAFile()).play() looks awfully complicated and long to type. You may be wondering if there are ways to simplify it. We can actually do it just the way that mathematicians have for centuries: We name the pieces! The results from methods (functions) can be named, and these names can be used as the inputs to other methods.
> String fileName = FileChooser.pickAFile(); > Sound soundObj = new Sound(fileName); > soundObj.play();
3.6.7. Naming the Result of a Method
We can assign names to the results of methods (functions). If we name the result from FileChooser.pickAFile(), each time we print the name, we get the same result. We don't have to rerun FileChooser.pickAFile(). Naming code in order to re-execute it is what we're doing when we define methods (functions), which comes up in Section 3.5.
> String fileName = FileChooser.pickAFile(); > System.out.println(fileName); C:\intro-prog-java\mediasources\beach-smaller.jpg > System.out.println(fileName); C:\intro-prog-java\mediasources\beach-smaller.jpg
Notice that we named the String returned from FileChooser.pickAFile. We can use that name many times and each time it will have the same value (until we change it).
In the below example, we declare variables (assign names) for the file name (a String object) and the Picture object.
> String myFileName = FileChooser.pickAFile(); > System.out.println(myFileName); C:\intro-prog-java\mediasources\katie.jpg > Picture myPicture = new Picture(myFileName); > System.out.println(myPicture); Picture, filename C:\intro-prog-java\mediasources\katie.jpg height 360 width 381
Notice that the algebraic notions of substitution and evaluation work here as well. Executing the code:
Picture myPicture = new Picture(myFileName);
causes the exact same picture to be created as if we had executed: Picture myPicture = new Picture(FileChooser.pickAFile());, because we set myFileName to be equal to the result of FileChooser.pickAFile(). The values get substituted for the names when the expression is evaluated. The code new Picture(myFileName) is an expression which, at evaluation time, gets expanded into:
 Assuming, of course, that you picked the same file.
new Picture ("C:\intro-prog-java\mediasources\katie.jpg")
because C:\intro-prog-java\mediasources\katie.jpg is the name of the file that was picked when FileChooser.pickAFile() was evaluated and the returned value was named myFileName.
We can also replace the method method invocations ("function calls") with the value returned. FileChooser.pickAFile() returns a String objecta bunch of characters enclosed inside of double quotes. We can make the last example work like this, too.
Common Bug: Backslashes and Slashes
You have seen the names of files displayed with backslashes in them, such as C:\intro-prog-java\mediasources\beach.jpg. However, when you create an object of the String class in Java you might not want to use backslashes because they are used to create special characters in strings like tab or newline. You can use slashes '/' instead as a path separator C:/intro-prog-java/mediasources/beach.jpg. Java can still figure out the path name when you use slashes. You can still use backslashes in the full path name, but you need to double each one C:\\intro-prog-java\\mediasources\\ beach.jpg.
> String myFileName = "C:/intro-prog-java/mediasources/katie.jpg"; > System.out.println(myFileName); C:/intro-prog-java/mediasources/katie.jpg > Picture myPicture = new Picture(myFileName); > System.out.println(myPicture); Picture, filename C:/intro-prog-java/mediasources/katie.jpg height 360 width 381
Or even substitute for the name.
> Picture aPicture = new Picture("C:/intro-prog-java/mediasources/katie.jpg"); > System.out.println(aPicture); Picture, filename C:/intro-prog-java/mediasources/katie.jpg height 360 width 381
Computer Science Idea: We can Substitute Names, Values, and Methods
We can substitute a value, a name assigned to that value (the variable name), and the method returning that value interchangeably. The computer cares about the values, not if it comes from a string, a name (a variable), or a method (function) call.
We call statements to the computer that are telling it to do things commands. System.out.println(aPicture); is a command. So is String myFileName = FileChooser.pickAFile();, and aPicture.show(;). These are more than expressions: They're telling the computer to do something.