Validated by Amaya

zz still needs
Spell check
Grammar check
Publication date

Java OOP Lecture Notes

Mirroring Images

Learn how to mirror images both horizontally and vertically.

Published:  zz-unpublished
By Richard G. Baldwin

Java OOP Notes # JavaExam3-02


Preview

In this lesson, you will learn how to mirror images, both horizontally and vertically.

Program specifications

Write a program named Prob02 that uses the class definition shown in Listing 1 and Ericson's media library along with the image file named Prob02a.jpg (shown in Figure 1) to produce the three graphic output images shown in Figure 2, Figure 3, and Figure 4.

Figure 1. Input file named Prob02a.jpg.
. Input file named Prob02a.jpg.

Figure 2. First output image.
First output image.

Figure 3. Second output image.
Second output image.

Figure 4. Third output image.
Third output image.

New classes

You may define new classes as necessary to cause your program to behave as required, but you may not modify the class definition for the class named Prob02 shown in Listing 1.

Rotate and mirror

The image from the file named Prob02a.jpg is rotated by 35 degrees and it is not scaled. Then the top-left quadrant of the picture containing the rotated image is mirrored into the top-right quadrant. Following this, the top half of the picture is mirrored into the bottom half.

Required output text

In addition to the three output images mentioned above, your program must display your name and the other line of text shown in Figure 5 on the command-line screen

Figure 5. Required output text.

Display your name here.
Picture, filename None height 404 width 425

Viewing tip

I recommend that you open another copy of this document in a separate browser window and use the following links to easily find and view the figures and listings while you are reading about them.

Figures

Listings

Supplemental material

I recommend that you also study the other lessons in my extensive collection of online programming tutorials.  You will find a consolidated index at www.DickBaldwin.com.

Discussion and sample code

Will discuss in fragments

I will discuss and explain this program in fragments. A complete listing of the program is provided in Listing 6 near the end of the lesson.

The driver class named Prob02

The driver class containing the main method is shown in Listing 1.

Listing 1. The driver class named Prob02.

public class Prob02{
  public static void main(String[] args){
    new Prob02Runner().run();
  }//end main method
}//end class Prob02

Instantiate a new object and call its run method

The code in the main method instantiates a new object of the class named Prob02Runner and calls the run method on that object.

When the run method returns, the main method terminates causing the program to terminate.

Beginning of the class named Prob02Runner

The beginning of the class named Prob02Runner, including the constructor, is shown in Listing 2.

Listing 2. Beginning of the class named Prob02Runner.

class Prob02Runner{
  public Prob02Runner(){
    System.out.println("Display your name here.");
  }//end constructor

The constructor displays the student's name, producing the first line of output text shown in Figure 5.

The run method

The run method that is called in Listing 1 is shown in its entirety in Listing 3.

Listing 3. The run method.

  public void run(){
    Picture pix = new Picture("Prob02a.jpg");
    //Add your name and display the output picture.
    pix.addMessage("Display your name here.",10,20);
    //Display the input picture.
    pix.explore();

    pix = rotatePicture(pix,35);
    pix.explore();

    pix = mirrorUpperQuads(pix);
    pix = mirrorHoriz(pix);
    pix.explore();
    System.out.println(pix);
  }//end run

Very familiar code

Except for the two method calls highlighted in yellow in Listing 3, you should already be familiar with all of the code in Listing 3.

The rotatePicture method

For example, the call to the method named rotatePicture is essentially the same as code that I explained in an earlier lesson. Therefore, I won't explain that method again in this lesson. You will find the code for the method named rotatePicture in Listing 6 near the end of the lesson.

Operate on the picture with the rotated image

The original picture is replaced by a picture containing the rotated image shown in Figure 3. From this point forward, all operations are performed on the Picture object containing the rotated image.

The method named mirrorUpperQuads

The method named mirrorUpperQuads that is called in the run method in Listing 3 is shown in Listing 4.

Behavior of the method named mirrorUpperQuads

This method mirrors the upper-left quadrant of a picture into the upper-right quadrant as shown in Figure 6.

Listing 4. The method named mirrorUpperQuads.

  private Picture mirrorUpperQuads(Picture pix){

    Pixel leftPixel = null;
    Pixel rightPixel = null;
    int midpoint = pix.getWidth()/2;
    int width = pix.getWidth();

    for(int row = 0;row < pix.getHeight()/2;row++){
      for(int col = 0;col < midpoint;col++){
        leftPixel = pix.getPixel(col,row);
        rightPixel =
                   pix.getPixel(width-1-col,row);
        rightPixel.setColor(leftPixel.getColor());
      }//end inner loop
    }//end outer loop

    return pix;
  }//end mirrorUpperQuads

Declare four working variables

Listing 4 begins by declaring and initializing four working variables. The purpose of these variables should be obvious on the basis of their names and their initialization expressions.

Copy the pixel colors

Then Listing 4 uses a double nested for loop to copy the colors from the pixels in the upper-left quadrant into the pixels in the upper-right quadrant. This is done in such a way as to form a mirror image about the center point as shown in Figure 6.

The outer loop

The outer loop iterates on the rows of pixels in the top half of the image. Only the top half of the image is processed in this method because the top half will be mirrored into the bottom half later on.

The inner loop

The inner loop iterates on the columns in the left half of the image, copying pixel colors from the left half into the pixels in the right half.

Destruction of pixel colors

The colors in the pixels in the upper-right quadrant are overwritten by this method.

In effect, this method and the one following it destroys all of the pixel colors originally in the right half of the picture of the rotated image and all of the pixel colors originally in the bottom half of the picture.

The final picture shown in Figure 4 contains only pixel from the upper-left quadrant of the picture with the rotated image.

Return a modified Picture object

Finally, the code in Listing 4 returns the modified Picture object to the run method in Listing 3.

At this point, the picture with the rotated image is replaced by the version of the picture returned by the mirrorUpperQuads method.

Picture output from the mirrorUpperQuads method

If you were to display the picture at that point, you would see the image shown in Figure 6. (Showing this picture is not a requirement for the student.)

Figure 6. Picture output from the mirrorUpperQuads method.
. Picture output from the mirrorUpperQuads method.
The upper-left quadrant has been mirrored

As you can see from Figure 6, at this point in the process, the upper-left quadrant has been mirrored into the upper-right quadrant, but the bottom half of the picture is undisturbed. It's time to do something about that.

Call the mirrorHoriz method

The next statement in the run method in Listing 3 is a call to the mirrorHoriz method passing the picture shown in Figure 6 as a parameter.

The method named mirrorHoriz

The method named mirrorHoriz is shown in Listing 5. This method mirrors the top half of a picture into the bottom half of the same picture. It will be used to mirror the top half of the picture in Figure 6 into the bottom half.

Listing 5. The method named mirrorHoriz.

  private Picture mirrorHoriz(Picture pix){

    Pixel topPixel = null;
    Pixel bottomPixel = null;
    int midpoint = pix.getHeight()/2;
    int height = pix.getHeight();

    for(int col = 0;col < pix.getWidth();col++){
      for(int row = 0;row < midpoint;row++){
        topPixel = pix.getPixel(col,row);
        bottomPixel =
                   pix.getPixel(col,height-1-row);
        bottomPixel.setColor(topPixel.getColor());
      }//end inner loop
    }//end outer loop

    return pix;
  }//end mirrorHoriz method

}//end class Prob02Runner

Very similar to the mirrorUpperQuads method

This method is very similar to the previous method named mirrorUpperQuads.

Four working variables and a nested for loop

As before, Listing 5 declares and initializes four working variables. These variables are used in a a nested for loop to copy pixel colors from the top half of the picture into the pixels in the bottom half.

The outer and inner loops

In this case, the outer loop iterates on all of the columns going from left to right.

The inner loop iterates on rows, from the top row to the vertical midpoint, copying the colors from the pixels from the top half into the pixels in the bottom half.

The end of the class

Listing 5 also signals the end of the class named Prob02Runner and the end of the program.

Run the program

I encourage you to copy the code from Listing 6.  Compile the code and execute it.  Experiment with the code, making changes, and observing the results of your changes.  Make certain that you can explain why your changes behave as they do.

Summary

You learned how to mirror images both horizontally and vertically.

Complete program listing

A complete listing of the program discussed in this lesson is shown in Listing 6 below.

Listing 6. Source code for Prob02.

/*File Prob02 Copyright 2008 R.G.Baldwin
*********************************************************/
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.Graphics;

public class Prob02{
  //DO NOT MODIFY THE CODE IN THIS CLASS DEFINITION.
  public static void main(String[] args){
    new Prob02Runner().run();
  }//end main method
}//end class Prob02
//======================================================//

class Prob02Runner{
  public Prob02Runner(){
    System.out.println("Display your name here.");
  }//end constructor
  //----------------------------------------------------//
  public void run(){
    Picture pix = new Picture("Prob02a.jpg");
    //Add your name and display the output picture.
    pix.addMessage("Display your name here.",10,20);
    //Display the input picture.
    pix.explore();

    pix = rotatePicture(pix,35);
    pix.explore();

    pix = mirrorUpperQuads(pix);
    pix = mirrorHoriz(pix);
    pix.explore();
    System.out.println(pix);
  }//end run
  //----------------------------------------------------//

  private Picture rotatePicture(Picture pix,
                                double angle){

    //Set up the rotation transform
    AffineTransform rotateTransform =
                                    new AffineTransform();
    rotateTransform.rotate(Math.toRadians(angle),
                           pix.getWidth()/2,
                           pix.getHeight()/2);

    //Get the required dimensions of a rectangle that will
    // contain the rotated image.
    Rectangle2D rectangle2D =
           pix.getTransformEnclosingRect(rotateTransform);
    int resultWidth = (int)(rectangle2D.getWidth());
    int resultHeight = (int)(rectangle2D.getHeight());

    //Set up the translation transform that will translate
    // the rotated image to the center of the new Picture
    // object.
    AffineTransform translateTransform =
                                    new AffineTransform();
    translateTransform.translate(
                      (resultWidth - pix.getWidth())/2,
                      (resultHeight - pix.getHeight())/2);

    //Concatenate the two transforms so that the image
    // will first be rotated around its center and then
    // translated to the center of the new Picture object.
    translateTransform.concatenate(rotateTransform);
    //Create a new Picture object to contain the results
    // of the transformation.
    Picture result = new Picture(
                              resultWidth,resultHeight);

    //Get the graphics context of the new Picture object,
    // apply the transform to the incoming picture and
    // draw the transformed picture on the new Picture
    // object.
    Graphics2D g2 = (Graphics2D)result.getGraphics();
    g2.drawImage(pix.getImage(),translateTransform,null);

    return result;
  }//end rotatePicture
  //----------------------------------------------------//

  //This method mirrors the upper-left quadrant of a
  // picture into the upper-right quadrant.
  private Picture mirrorUpperQuads(Picture pix){
    Pixel leftPixel = null;
    Pixel rightPixel = null;
    int midpoint = pix.getWidth()/2;
    int width = pix.getWidth();
    for(int row = 0;row < pix.getHeight()/2;row++){
      for(int col = 0;col < midpoint;col++){
        leftPixel = pix.getPixel(col,row);
        rightPixel =
                   pix.getPixel(width-1-col,row);
        rightPixel.setColor(leftPixel.getColor());
      }//end inner loop
    }//end outer loop

    return pix;
  }//end mirrorUpperQuads
  //----------------------------------------------------//

  //This method mirrors the top half of a picture into
  // the bottom half.
  private Picture mirrorHoriz(Picture pix){
    Pixel topPixel = null;
    Pixel bottomPixel = null;
    int midpoint = pix.getHeight()/2;
    int height = pix.getHeight();
    for(int col = 0;col < pix.getWidth();col++){
      for(int row = 0;row < midpoint;row++){
        topPixel = pix.getPixel(col,row);
        bottomPixel =
                   pix.getPixel(col,height-1-row);
        bottomPixel.setColor(topPixel.getColor());
      }//end inner loop
    }//end outer loop

    return pix;
  }//end mirrorHoriz
  //----------------------------------------------------//

}//end class Prob02Runner


Copyright

Copyright 2010, Richard G. Baldwin.  Reproduction in whole or in part in any form or medium without express written permission from Richard Baldwin is prohibited.

About the author

Richard Baldwinis a college professor (at Austin Community College in Austin, TX) and private consultant whose primary focus is object-oriented programming using Java and other OOP languages.

Richard has participated in numerous consulting projects and he frequently provides onsite training at the high-tech companies located in and around Austin, Texas.  He is the author of Baldwin's Programming Tutorials, which have gained a worldwide following among experienced and aspiring programmers. He has also published articles in JavaPro magazine.

In addition to his programming expertise, Richard has many years of practical experience in Digital Signal Processing (DSP).  His first job after he earned his Bachelor's degree was doing DSP in the Seismic Research Department of Texas Instruments.  (TI is still a world leader in DSP.)  In the following years, he applied his programming and DSP expertise to other interesting areas including sonar and underwater acoustics.

Richard holds an MSEE degree from Southern Methodist University and has many years of experience in the application of computer technology to real-world problems.

Baldwin@DickBaldwin.com

-end-