15110 Fall 2011 [Cortina/von Ronne]
Laboratory 8 - October 20
Overview
In this lab, students will:
Work with bitmap graphics.
Use load_ppm to create a 3-dimensional array
representing a bitmap image loaded from a PPM file.
Use plot to display bitmaps encoded in Ruby arrays.
Implement an image processing algorithm that operates on
these arrays.
Experiment with the MARS virtual machine.
Create a MARS assembly program
Load a MARS assembly program into the MARS virtual machine.
Trace through the program's execution.
Deliverables
- redless_nautical.ppm
- 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.
Activity:
- Download the file nautical.ppm
and store it in your lab8 directory.
- In IRB, load ppm.rb, and use load_ppm to
create a 3-D array for nautical.ppm
- 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.
Activity:
Implement this algorithm as the function remove_red(image).
In IRB, apply this function to the 3d bitmap loaded from nautical.ppm.
Use plot to display the modified image (shown at right).
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:
;redcode
;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
Activity:
Create a file celsius.txt that converts 35 degrees
fahrenheit into celsius.
include MARSLab in IRB
Use make_test_machine(filename) to create a MARS
virtual machine ready to execute the revised celsius program.
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