Even though digital pictures have millions of pixels, modern computers are so fast that they can process all of them quickly. You will write methods in the Picture class that will modify digital pictures. The Picture class inherits from the SimplePicture class, which implements to DigitalPicture interface as shown in the "Unified Modeling Language" class diagram in Figure 5, below.
A UML class diagram shows classes and the relationships between them.
DigitalPicture is an interface. An interface often only has public abstract methods. An abstract method is not allowed to have a body. Notice that none of the methods declared in DigitalPicture have a body. Soo... what good is that?
Interfaces are useful for separating WHAT from HOW. An interface specifies WHAT an object needs to do, but not HOW it does it. Therefore, you actually can't directly use them to create objects. Rather, you can have your object-making class 'implement' or 'realize' an interface. This is what SimplePicture does with DigitalPicture.
A normal, non-abstract class provides the information for all the empty methods that are declared in the interface (either directly, or by inheriting the info from a parent class).
You can in fact declare a new object of a type that is an interface. But to make it work, you have to make that variable refer to an object of a class that implements the interface.
So you can do this: DigitalPicture p = new SimplePicture();
For another example, Java has a List interface with empty methods for things lists should do, like add, remove, get, etc. But to create a List object, you need to make, for an example, an ArrayList
List<String> nameList = new ArrayList<String> ();
Why wouldn't you just make nameList be an ArrayList in the first place?? Well, there are other classes in Java that implement the List interface. By declaring nameList to be of type List<String> instead of ArrayList<String>, it's easy to change your mind and use another class that implements the same interface. You would have a lot of the same method names, for example, so your code would largely still work.
DigitalPicture declares a method called getPixels2D, which returns a 2-dimensional array of Pixel objects. SimplePicture implements that interface, so it will have that method in it. Picture inherits from SimplePicture, so you can use getPixels2D on any Picture object.
Here's what we'll do with that:
You can loop through all the Pixel objects in the two-dimensional array to modify the picture. You can get and set the red, green, and/or blue value for a Pixel object. You can also get and/or set the Color value for a Pixel object. You can create a new Color object using a constructor that takes the red, green, and blue values as integers as shown below.
Color myColor = new Color(255,30,120);
What do you think you will see if you modify the beach picture in the images folder to set all the blue values to zero? Do you think you will still see a beach? Run the main method in the Picture class. The body of the main method will create a Picture object named beach from the “beach.jpg” file, open an explorer on a copy of the picture (in memory), call the method that sets the blue values at all pixels to zero, and then open an explorer on a copy of the resulting picture.
The following code is the main method from the Picture class. public static void main(String[] args)
{ Picture beach = new Picture("beach.jpg");
beach.explore();
beach.zeroBlue();
beach.explore();
beach.zeroBlue();
} beach.explore();
The following code is the zeroBlue method in the Picture class. public void zeroBlue()
{ Pixel[][] pixels = this.getPixels2D();
for (Pixel[] rowArray : pixels)
for (Pixel[] rowArray : pixels)
{ for (Pixel pixelObj : rowArray)
{ pixelObj.setBlue(0);
}}}