15110 Fall 2011 [Cortina/von Ronne]

Laboratory 8 - October 20


In this lab, students will:

  1. Work with bitmap graphics.
    1. Use load_ppm to create a 3-dimensional array representing a bitmap image loaded from a PPM file.
    2. Use plot to display bitmaps encoded in Ruby arrays.
    3. Implement an image processing algorithm that operates on these arrays.
  2. Experiment with the MARS virtual machine.
    1. Create a MARS assembly program
    2. Load a MARS assembly program into the MARS virtual machine.
    3. Trace through the program's execution.


  1. redless_nautical.ppm
  2. celsius_trace.txt

Bitmap Images

A 3-D Representation of Bitmaps in Ruby

In PA7, you will be writing functions to process images. An image is simply a two-dimensional array of pixels, where each pixel is an array with three integers representing the red, green and blue values for that pixel. (So if you think about it, an image is really a three-dimensional structure.) For example, here is a 3 X 2 image consisting of a red and green pixel in the top row, a blue and white pixel in the middle row, and two black pixels in the bottom row:

[ [ [255,0,0] , [0,255,0] ] [ [0,0,255] , [255,255,255] ] [ [0,0,0] , [0,0,0] ] ] 

Support Functions

We have developed some Ruby functions to make it easier to work with graphics. These functions are contained in ppm.rb and include load_ppm(filename) (which takes a name of a file in the PPM format and converts it into a the 3-dimensional bitmap representation described above) and plot(image) (which uses the RubyLabs canvas to render the bitmap image). There is also a function save_ppm(image, filename) that will store a 3d bitmap to the specified file.

  1. Download the file nautical.ppm and store it in your lab8 directory.
  2. In IRB, load ppm.rb, and use load_ppm to create a 3-D array for nautical.ppm
  3. Use plot to display the 3-d array as the image shown to the right.

An Image Processing Algorithm: red removal

For each problem in PA7, your job is to write a function that takes an image represented in this format, and returns a new image of the same size that has something about the image changed. As an example, suppose we want to remove the red component from every pixel of an image. We can do this by resetting the red part of each pixel array to 0.

This can be accomplished using the following algorithm:

A. Set num_rows to the number of rows in the image.

B. Set num_columns to the number of columns in the image.

C. For each row in the image, do the following:

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

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

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

        (c)  Store the pixel array [0, green, blue] at the
             current row and column in the image. (typo fixed)

D. Return nil. 
  1. Implement this algorithm as the function remove_red(image).
  2. In IRB, apply this function to the 3d bitmap loaded from nautical.ppm.
  3. Use plot to display the modified image (shown at right).
  4. Use save_ppm to save your redless version of nautical.ppm as redless_nautical.ppm in your lab8 directory.

MARS Virtual Machine

The following MARS assembly code converts 80 degrees fahrenheit into celsius:

;name Celsius
;strategy   cels = (fahr - 32) * 5 / 9

fahr    DAT #80             ; input temperature
cels    DAT #0              ; store result here
ftmp    DAT #0              ; save fahr-32 here
start   MOV fahr, ftmp      ; (1) subtract 32
        SUB #32, ftmp
mult    ADD ftmp, acc       ; (2) multiply by 5
        SUB #1, count
        JMN mult, count
div     SUB #9, acc         ; (3) divide by 9
        SLT #0, acc
        DAT #0              ; stop here when division done
        ADD #1, cels
        JMP div
acc     DAT #0              ; accumulator
count   DAT #5              ; counter
        end start


  1. Create a file celsius.txt that converts 35 degrees fahrenheit into celsius.
  2. include MARSLab in IRB
  3. Use make_test_machine(filename) to create a MARS virtual machine ready to execute the revised celsius program.
  4. If m is the result of make_test_machine, m.step() will cause the virtual machine to execute one step and m.run(n) will cause the virtual machine to execute n steps. Use the step, run(n) to trace through the execution, examining the virtual machine's memory with dump(start,end). Each time the execution reaches the mult label (pc = [ *5 ]), each time execution reach div (pc = [ *8 ]), and when the virtual machine halts, record the values stored at fahr (0), cels (1), ftmp (2), acc (13) and count (14) in celsius_trace.txt.

As an example, here are the first few lines that celsius_trace.txt should hold:

PC	fahr	cels	ftmp	acc	count
*5	35	0	3	0	5
*5	35	0	3	3	4