CS 140 - Lab 6 Instructions (Harcourt)

Objectives

  1. More practice writing methods in Java.
  2. More practice on manipulating pixels in an image.
  3. Learn about luminence

Method

Part I - Different kinds of grayscale

Grayscale is also know as black-and-white and monochrome and is discussed on pages 122-124 of the book.

  1. In this lab you'll write methods which convert color images into grayscale. In order to inspect your pictures, create individual Picture objects for each one and name the object references appropriately (similar to what we did for Lab 4 where you eventually had 7 separate picture objects displayed).
  2. To get started make a main class called Lab5 (save it in P:\cs140 ) that stores the filename and path
     
             "T:/Harcourt/Spring2008/CS140/gallery/reef.jpg"
         
    into a String object, creates a new Picture from that String object, and then shows the picture.

    Once you write this class, test it and make sure it displays the picture. (If you aren't sure how to write this class, go back and look at Lab4. It is almost identical to the Lab4 class).

  3. Next, you'll need to make sure your Picture class has correct implementations of extractRedChannel , extractGreenChannel , and extractBlueChannel from Lab 4. (If you successfully completed Lab 4, these methods should already be defined).
  4. After this, add the two methods below into your Picture class.
            public void grayScale() {
               Pixel[] pixelArray = this.getPixels();
    
               for (Pixel pixelObj : pixelArray) {
                 int r = pixelObj.getRed();
                 int g = pixelObj.getGreen();
                 int b = pixelObj.getBlue();
                 int val = (r + g + b) / 3;
                 pixelObj.setColor(new Color(val,val,val));
               }
            }
        
            
            public void grayScaleWithLuminence() { 
              Pixel[] pixelArray = this.getPixels(); 
              for (Pixel p : pixelArray) { 
                int val = (int) (0.229 * p.getRed() + 
                                 0.587 * p.getGreen() + 
                                 0.114 * p.getBlue()); 
                p.setColor(new Color(val,val,val)); 
              } 
           } 
    			
  5. The luminence of a color is the amount of light reflected back to our eye. One measure of luminence is simply the sum of the RGB values. So white has the highest luminence of 765 and black the lowest with 0. This should make intuitive sense. However, red (255,0,0) has the same luminence as blue (0,0,255) but research in psychology tells us that our eye perceives blue to be darker than red. So our simple implementation of grayScale that weighs each color by the same amount of one third is too simple. What we should do is decrease blue more than we decrease red to make sure that blue stays darker than red. This is exactly what the above method grayScaleWithLuminence does.

    Carefully review each method above to make sure you understand what each is doing and how they are different. Recall that some of the methods from Lab 4 that extract the red, green, and blue channels also implement different kinds of gray scale.

  6. In your Lab6 class create five additional picture objects from the same filename given in Step 2 and apply a different method to each of the Picture objects. When complete, you should be able to run your Lab6 class and six images will open: the original color picture and five different black-and-white pictures.
  7. Question 1: Compare and contrast the various black-and-white pictures in relation to the original color picture. Look at each picture and figure out which method produced it. Is there one picture that, in your opinion, best captures the essence of the original picture? Which one is it and what do you think it captures that the others don't?

    When you have reached this point check in with your instructor and be prepared to show the six different pictures.

Part II - Darkening a Picture and Preserving Color

Now that we know that the luminence of a pixel is just the sum of the RGB values we should be able to replace each color pixel with a darker shade of the same color. To darken a pixel decrease each RGB value in its color by the same amount.

  1. In the Picture class write a method named darken that decreases the value of each color in a pixel by 25% (that is the same as multiplying by ______?). Call darken from the main method and compare the original picture with the darker version. Use the method grayScale above as a guide to get your started writing darken.
  2. Parameterize the darken method so it takes three double parameters named redScale , greenScale , and blueScale and uses these values as scaling factors for their respective color. This method now lets you scale each color by a different amount. Call your new darken method using three values smaller than one (such as 0.75, 0.5, and 0.9). Here's how you would declare the three parameters in your darken method.
            public void darken(double redScale, 
                               double greenScale,
                               double blueScale) {
               // code goes in here
            }
    					
  3. Question 2: What should happen when you put in a scaling factor greater than one? Hint: what happens to the individual RGB values?
  4. Go ahead and try calling darken with values of 1.25 as parameters. Click on the interactions button after you run the program. What happened? Do you know what went wrong by looking at the first line of the error message?
  5. Get checked off and be prepared to show the parameterized darken method.

Extra Credit

For extra credit you are going to modify your parameterized darken method to fix the problem above of having a color value exceed 255. What darken should do is to make sure that if, after we scale a color, the color value is greater than 255 we use 255 instead of the bigger value. We can do this using a Java if-statement. The code below says that if the value of red is greater than 255 then set the value of red to 255.

      int red = (int) (pixelObj.getRed() * redScale);
      if (red > 255) {
        red = 255;
      }  				

Modify darken with the above code and similar code for the green and blue values. Call darken from main to make sure it works. Use the values of 1.25 for each scaling factor.

Question: What happens when you make the scaling factor big such as 5?