15110 Spring 2013 [Kaynar/Gunawardena]

Programming Assignment 9 - due Tuesday, April 9

Part I: OLI

[3 points] For part I of this assignment, you will work on a module in the Online Learning Initiative at CMU that will teach you about a new topic called Encryption. This module will help reinforce what we will learn about encryption in the lectures.

In order to get credit for this part, you must complete the module by the deadline for the programming part. We will not be grading you on how many questions you get right in the module. Instead, we will be grading you on whether you completed the module on time or not.

To access the Encryption module:

  1. Go to this URL: http://oli.cmu.edu
    1. If you do not have an account, click on the "Register" link in the upper right. Click on the "CMU users sign in here" link.
    2. If you already have an account, Sign In: Click on the "CMU users sign in here" link.
  2. Enter your course key 15110s13 into the box labeled "Register for a course" as shown at right.
  3. Follow the instructions on the My Courses page to get started on the Encryption module.
  4. You don't have to do then entire module in one sitting; you can leave the web site and resume work on it later.

Part II: Programming Exercises on Bitmap Images

Note: You are responsible for protecting your solutions to these problems from being seen by other students either physically (e.g., by looking over your shoulder) or electronically. (More information can be found in the instructions for Programming Assignment 2.)

Style

Some small portion of your grade will be allocated for style. This means that you are required to keep each line of code under 80 characters in length, to properly indent your code (ask a TA or post to Piazza if you are unsure about how to indent), and to try and use meaningful variable names where appropriate (i.e. if you are adding the elements in a list, use the variable sum instead of x).

For each problem, your job is to write a function that takes an image represented in the PPM format, and modifies something about the image. You may find it useful to refer to Lab8 , which covered bitmap images.

Testing with PPM Images

To test your functions, you will need to download ppm.rb and some images in the ppm format, such as nautical.ppm and scottiedog.ppm into your pa9 directory. Once you do that, you should do the following in irb (replacing remove_red!(m) with a call to your function):

>> load("ppm.rb")
=> true
>> b = load_ppm("nautical.ppm")
=> [[[255, 255, 255], [255, 255, 255] ...
>> remove_red!(b)
=> nil
>> plot(b)
=> nil
becomes

Additional Instructions for Slow Connections

Unfortunately, if you are accessing unix.andrew.cmu.edu, the plot function may take several minutes to send the data to your local window. An alternative that will go faster is to save your modified image, and then view it using the command line program display.

To use display to view your modified image (m from the example above), first save your modified image to a ppm file using the function save_ppm:

>> save_ppm(m, "redless_nautical.ppm")
=> nil

Then in a separate window, establish an ssh session (with X11 forwarding), and in your pa9 directory, run the command:

[andrewid@unix37 pa9]$ display redless_nautical.ppm

Note: you may also be able to improve performance slightly by telling ssh to use compression. If you are using the command-line ssh (e.g., on a Mac), you can use the "-C" switch:

ssh -CX andrewid@unix.andrew.cmu.edu

Creating Additional PPM Files

The ppm.rb functions require images in the ppm format. If you want new images to test, unix.andrew.cmu.edu has programs that can be used to convert more common image formats (including JPEG, PNG, and GIF to PPM). These can be used as follows:

jpegtopnm file.jpg > file.ppm
giftopnm file.gif > file.ppm
pngtopnm file.png > file.ppm
Each of these example commands will create a PPM file called file.ppm from file.jpg, file.gif, or file.png, respectively.

Problems

  1. [2 points] Write a Ruby function blue_filter!(image) (in the file blue_filter.rb) that requires an image array (as defined above) as its parameter and modifies it so that it has only the blue components of the original image.

    Here is an algorithm you can follow. (It is very similar to the one for remove_red.) Make sure you understand how this algorithm works. Don't just translate it to Ruby without thinking about it.

    1. Set num_rows equal to the number of rows in the image.

    2. Set num_columns equal to the number of columns in the image.

    3. For each row in the image do the following:

      1. For each column in the image do the following:

        1. Set red to the red component of the pixel array at the current row and column in the image.

        2. Set green to the green component of the pixel array at the current row and column in the image.

        3. Set blue to the blue component of the pixel array at the current row and column in the image.

        4. Store the pixel array [0, 0, blue] at the current row and column in the image.

    4. Return nil.

    Sample usage:

    >> b = load_ppm("nautical.ppm")
    => [[[255, 255, 255], [255, 255, 255] ...
    >> blue_filter!(b)
    => nil
    >> plot(b)
    => nil
    
    becomes

  2. [2 points] Write a Ruby function red_scale!(image) (in the file red_scale.rb) that requires an image array (as defined above) as its parameter and converts that image to an image consisting only of pixels that are various brightnesses of red. To convert each pixel to "red scale," get the pixel's red, green and blue values and then create a new pixel that contains the average of these 3 values as its red component. For example, if the pixel is [50, 100, 91], then its red scale version is [80, 0, 0].

    Algorithm: For each row and column, store the red, green and blue values of the pixel array for the current row and column and then replace the pixel array at the current row and column with its "red scale" version as defined above.

    Sample usage:

    >> b = load_ppm("nautical.ppm")
    => [[[255, 255, 255], [255, 255, 255] ...
    >> red_scale!(b)
    => nil
    >> plot(b)
    => nil
    
    becomes
  3. [3 points] Write a Ruby function stretch!(image) (in the file stretch.rb) that requires an image array (as defined above) as its parameter and converts it into the same image streched horizontally so that each pixel in the original image is two pixels in the widened image. See sample image below for an example.

    Sample usage:

    >> b = load_ppm("nautical.ppm")
    => [[[255, 255, 255], [255, 255, 255] ...
    >> stretch!(b)
    => nil
    >> plot(b)
    => nil
    
    becomes

Submission

You should have a pa9 directory, containing:

  1. blue_filter.rb,
  2. red_scale.rb,
  3. stretch.rb

Zip up your directory and upload it using the Autolab system.