Objectives

Image Manipulation

Manipulating images is common task and there are a large number of image editing tools available, including: Photoshop, Fireworks, and The Gimp (the Gnu Image Manipulation Package is an open source alternative to the closed and more expensive commercial packages). Our simple image processor will not approach these tools in complexity, but it will work in basically the same way they do. Here’s how it will look:

main chimp interface

This GUI displays a bitmap image and provides manipulation tools through a keypress-based interface. This isn’t the greatest of interface designs, but it will serve our purposes for the moment. Here are examples of some of these features:

the image brightened by a set amount (the inverse of dim) the image dimmed by a set amount (the inverse of bright)
flip bright effect dim effect
the image mirrored horizontally the image mirrored vertically
flip
	      horizontal effect flip vertical
	      effect
the negative of the image the image shifted 200 pixels to the right
negative
	      image effect shift effect

You’ll also be able to use the manipulations (and others) in combinations to create a variety of effects, such as the following:

Before: After:
original
	      image image
	      after blur, polarize and negative

Getting Started with Chimp

In this lab, you’ll start with a partially implemented program called ChimpLite.

Exercise 5.1:

Make a copy of the ChimpLite system (see also the lab code distribution directory) and then do the following:

  1. Add your name(s) and the date as a new version. Because you are modifying code that someone else has written, you should leave the original author and version information in the comments and add yours.

  2. Make sure that you can run the code. The “Refresh” (key code 'f') and “Dim” (key code 'd') options should work properly if you press the appropriate key on the keyboard while the system is running. If you’d like to work with a different image, feel free to download one now. As you can see in the code, the system loads an image, determines the image’s width and height, and then sizes the Processing output panel.

  3. When this lab asks you to add a new image manipulation feature, you will mimic what the code already does for its existing features. In particular, you should modify keyPressed() by adding one more appropriate branch to the multi-branch selection statement that handles the key presses (see the comment Add new key press response code here...). Each new branch calls a different image manipulation effect method and you should choose an appropriate character to initiate the given effect.

  4. Review how the dim() method manipulates pixel color values. It uses a double-nested for loop to visit each pixel in the image, the get(x, y) method to return the color value of the pixel at position (x,y), and the set(x, y, newColor) method to reset the pixel at position (x,y) to a new manipulated color value. It uses the color(r, g, b) method to create a new color object with the given red, green and blue intensities.

You will only produce one large program in this lab, so you don’t need to create separate directories for each exercise.

You can also rename the chimpLite program to Chimp if you would like; for this you must rename both the .pde file and the directory.

The Image Manipulation Effects

In this section, you’ll implement a set of new image manipulation effects.

The Brightening/Dimming Effects

The brightening and dimming effects modify the level of intensity of all three color attributes of all pixels in the image in a uniform manner. Increasing the intensity values brightens the image, that is it makes the image lighter or more washed out. Decreasing the intensity values has the opposite effect. As a reminder, here is what the effect does:

the original image: the image brightened by a set amount
(the inverse of dim):
the image dimmed by a set amount
(the inverse of bright):
original image flip bright effect dim effect

dim() implements the dimming effect. Study this implementation and then do the following exercise:

Exercise 5.2:

Create a brighten effect for Chimp that acts as the inverse of the Brighten effect. You’ll have to do the following things:

  1. Add a new option for the brighten effect, making sure to update your documentation.
  2. Add a new brighten() method to implement the effect. This method will be similar to dim().
Work with your code until you have Dim and Bright both working properly.

Refactoring the Brightening/Dimming Methods

One “quick and dirty” approach to implementing the dim effect is to copy the brighten effect and change the + 10 to - 10. Perhaps you used this approach. It works but you may have noticed that you simply copied most the code, creating two methods that are very very similar. In fact, they are too similar. Copied code is usually a indicator of bad design. A better design would “factor out” the common elements of these two similar methods and modularize them into a single method that uses parameters to differentiate the different behaviors.

The process of redesigning and reimplementing code without changing its behavior is called refactoring.

Exercise 5.3:

Refactor the dim and brighten methods to use a common changeBrightness(int) method. Do this as follows:

  1. Implement a changeBrightness(int) method that receives an integer, and modifies the pixel intensity of all the pixels in the image by that amount. This code will be almost identical to the original dim() method, except that it won’t just subtract 10, it will add whatever value is passed in the parameter (a positive number for brighten and a negative number of dim).
  2. Re-implement the dim and brighten key-handling code as simple calls to changeBrightness(int) with the arguments of -10 and +10 respectively.

Work with your code until you have Dim and Bright both working as they did before.

The Negative Effect

The negative effect produces a negative image of the original. A negative image is an image in which all the color values of all the pixels have their intensity values inverted. For example, you can invert the red intensity value of a color object c using the expression 255 - red(c). As a reminder, here is what the effect does:

the original image: the negative of the image
original image negative
	      image effect
Exercise 5.4:

Create a Negative effect for Chimp in a manner similar to the way in which you created the Dim effect.

The Flip Effects

Flip effects mirror the images either a horizontally or vertically. As a reminder, here is what these effects do:

the original image: the image mirrored horizontally the image mirrored vertically
original image flip
	      horizontal effect flip vertical
	      effect

Chimp already has a method for the Flip-Horizontal effect. Study this implementation and then do the following exercise:

Exercise 5.5:

Create a Flip-Vertical effect for Chimp.

The Shift Effect

The shift effect “slides” the image to the left, wrapping it around on itself. As a reminder, here is what the effect does:

the original image: the image shifted 200 pixels to the left
original image shift effect

One way to implement the shift effect is to write something similar to the flip effects. Unfortunately, those solutions assumed that the flipping could be done by simply swapping pixels on either side of a mirroring line, which only really works when the mirroring line bisects the image. Flipping (or shifting) an image with respect to a non-bisecting line would be harder to do that way. In this exercise, we’ll add a couple of index manipulation tricks to help make this task easier:

Exercise 5.6:

Create a Shift-Left effect that “wraps” the image around on itself by 100 pixels. The algorithm for doing this generally follows the algorithms used in the earlier methods, but has some differences:

  1. Create a copy of the image.
  2. Repeat for each image column (i)
    1. Repeat for each image row (j)
      1. Set c = the color of the pixel 100 places to the right of position (i, j) from the image copy.
      2. Set the color of the pixel at position (i, j) of the original image to c.

Note:

  1. Because copying an image’s pixels to itself causes you to overwrite some pixels and thus mess up your shift operation, you must start by making a copy of the original PImage object (i.e., theImage). Note that because the image is a reference object, you can’t just say: PImage imageCopy = theImage; because this would simply copy the reference to the image object rather than copying the image itself. Instead, use the copyImage() method provided in the code:

    PImage imageCopy = copyImage(theImage);
    
  2. While it might seem easy to simply get the pixel 100 spaces to the right, this will cause problems when you start moving beyond the right edge of the image (i.e., when i+100 moves beyond the edge of the image). Instead, use the modulus operator to compute the x coordinate as follows:

    (i + 100) % imageWidth
    

    The % operator automatically wraps an out-of-bounds array index back around to the front of the image.

Keep these notes in mind; they are useful for some of the homework exercises.

Checking In

Submit all the code and supporting files for the exercises in this lab.