Functional Problem Solving (CSC 151 2014F) : Readings
Primary: [Front Door] [Schedule] - [Academic Honesty] [Disabilities] [Email] - [FAQ] [Teaching & Learning] [Grading] [Rubric] - [Calendar]
Current: [Assignment] [EBoard] [Lab] [Outline] [Reading]
Sections: [Assignments] [EBoards] [Examples] [Handouts] [Labs] [Outlines] [Readings]
Reference: [Setup] [VM] [Errors] - [Functions A-Z] [Functions By Topic] - [Racket] [Scheme Report (R5RS)] [R6RS] [TSPL4]
Related Courses: [Davis (2013F)] [Rebelsky (2014S)] [Weinman (2014F)]
Misc: [Submit Questions] - [SamR] [Glimmer Labs] [CS@Grinnell] [Grinnell] - [Issue Tracker (Course)]
As you may have noted from our initial discussions of drawing, there are a number of ways to think about how one creates and how one represents an image. And, as we noted in our discussion of computer science, there is a strong relationship between the way we organize or represent information and the algorithms we write to manipulate that information. The representations we have explored so far are rather coarse-grained; that is, they refer to relatively large drawing objects or techniques. Let us now turn our attention to a somewhat finer-grained approach. In particular, we will explore raster graphics, one of the simplest ways to represent and think about images on the computer.
In the raster graphics format, an image is represented as a grid of colors. That is, we segment the image into a large number of uniformly sized squares, which we arrange side-by-side and top-to-bottom, and we assign a color to each square. We call this grouping a “grid” because, well, it looks like the grid on graph paper.
Variations on raster graphics are used in a wide variety of image file formats, including JPG, Bitmap, GIF, and PNG.
When we describe a raster graphics image, we need to indicate the width and height of the image. Because raster images are a grid, we typically indicate the width and height in terms of the number of columns and rows, not in terms of inches. We also need to describe the color at each point in the grid. While there are a number of ways to indicate colors of different grid points, it is easiest if we specify the color of each one separately, particularly if we are going to write programs that process raster graphics images. We call one grid point in an image a pixel.
In essence, we need to assign an index to each point in the grid. When we refer to one pixel on the grid, we do so in terms of its column number and its row number.
Note that GIMP has an interesting perspective on how to number positions in the image. In particular, while column numbers go from left to right (as you might expect), row numbers go from top to bottom, rather than bottom to top. We also start both column numbers and row numbers with 0. When we refer to one position on the grid, we do so in terms of its column number and its row number. Hence, in an image that is 9 pixels wide and 5 pixels high,
Why is (0,0) the top-left position, rather than the bottom-left position, as in the Cartesian plane? One possibility is that images were originally described for television tubes, and televisions scan from top to bottom. Another is that whoever was responsible for designing the notation was familiar with linear algebra, and was using the typical notation for elements of a matrix.
Why do we start counting rows and columns with zero rather than with one? It turns out that some computations are easier with such a numbering system. Computer scientists almost always start counting with 0, rather than with 1.
In summary, we typically number the rows of the grid from top to bottom, and number the columns of the grid from left to right. We also start both column numbers and row numbers with 0.
Of course, in order to write programs that manipulate raster images, we
need to know more than how images and colors are represented - we also
need to know what operations are available.
MediaScript provides a few core operations to build and analyze images.
You've already encountered a few, such as
image-new
,
image-load
,
image-show
,
image-width
,
and image-height
.
Now, let us turn to the procedures that work with individual pixels.
(
extracts the color of a particular pixel in the image. For example,
we might get the initial color of the top-left pixel of an image with
image-get-pixel
image
column
row
)
>
(define sample-image (image-load "..."))
>
(define top-left-color (image-get-pixel sample-image 0 0))
In contrast, (
changes
the color of a particular pixel in the image. We might change the
top-right pixel of the sample image to the same color as the top-left
pixel with
image-set-pixel!
image
column
row
color
)
>
(image-set-pixel! sample-image (- (image-width sample-image) 1) 0 top-left-color)
As you should have figured out by now, the exclamation point at
the end of a procedure indicates that the procedure is intended to
change something, instead of just computing a result. In this case,
image-set-pixel!
changes the image. Because changing
things can be dangerous, Scheme programmers remind themselves that a
procedure changes things by suffixing them with that exclamation point.
Of course, we also want to set pixels using existing
colors. The (
procedure will find the
internal representation of a color for the given name. (As you'll see
in the next reading, those representations are typically RGB colors.)
For example,
color-name->color
color-name
)
>
(define a-color-i-like (color-name->irgb "purple"))
>
a-color-i-like
8388736
We can also use this technique to set colors.
>
(image-set-pixel! sample-image 2 3 (color-name->irgb "darkorange"))
What if we want to find out what color names are available to us? As
you may recall, (
will give a list of every available color,
context-list-colors
)
In addition, (
will give a list of the colors
that include context-list-colors
name
)name
. For example, the following
will list a number of colors whose name includes “red”.
>
(context-list-colors "red")
("darkred" "indianred" "mediumvioletred" "orangered" "palevioletred" "red")
Finally, when we've obtained a color from an image,
we can find the name of a similar
color using (
. Why is it a similar color,
rather than exactly the same color? Because there are sixteen million,
seven hundred seventy seven thousand, two hundred and sixteen different
colors possible in the standard RGB color scheme, and no one is
mentally ill enough to try to name them all (at least so far).
irgb->color-name
color
)
Using an image of your own choosing, run the examples in the reading and verify they have the effects described.
(require gigls/unsafe) (define sample-image (image-load "...")) (image-show sample-image) ; Show original image (define top-left-color (image-get-pixel sample-image 0 0)) (image-set-pixel! sample-image (- (image-width sample-image) 1) 0 top-left-color) (image-show sample-image) ; Show updated image (color-name->irgb "purple") (image-set-pixel! sample-image 2 3 (color-name->irgb "darkorange")) ; Show doubly updated image (context-list-colors "red")