Your interpretation of images is correct. Images are made up of line segments in a unit square where the origin (0, 0) is the bottom left corner and (1, 1) is the top right corner.
A painter maps the image into a frame using the transformation given in the question. The einsten
image above is drawn in the default frame (the unit square) so it appears normal.
You can create and display an image using The SICP Picture Language in three steps:
- define a list of line segments
- create a segment painter from those line segments
- call paint with the new segment painter
I do this with several simple images in by blog post SICP 2.49: Defining Primitive Painters. Here's one simple example using just two line segments:
; The painter that draws an 'X' by connecting opposite corners of the frame.
(define x-segments
(list
(make-segment
(make-vect 0.0 0.0)
(make-vect 0.99 0.99))
(make-segment
(make-vect 0.0 0.99)
(make-vect 0.99 0.0))))
(define x-painter (segments->painter x-segments))
(paint x-painter)
Here's the result when I run that last command in DrRacket:
You can flip and rotate an image by creating new frames for it to be drawn in.
A frame is defined by three vectors:
- the origin
- the bottom edge (edge1)
- the left edge (edge2)
You can use the transform-painter
function given in the text (in the section titled Transforming and combining painters) to transform an existing segment painter using a new origin and edges.
(define (transform-painter painter origin corner1 corner2)
(lambda (frame)
(let ((m (frame-coord-map frame)))
(let ((new-origin (m origin)))
(painter
(make-frame new-origin
(sub-vect (m corner1) new-origin)
(sub-vect (m corner2) new-origin)))))))
For example, if I want to draw the original Einstein image rotated 45 degrees to the left, I just need to pass the einstein
segment painter along with a new origin, bottom edge, and left edge to transform-painter
and it will return a new segment painter. In other words, I need to tell transform-painter
where to draw the bottom left, bottom right, and top left corners of the image, and it will do the work of transforming all of the line segments in the original segment painter.
; rotate an image 45 degrees to the left
(define (rotate-45 painter)
((transform-painter (make-vect 0.5 0.0)
(make-vect 1.0 0.5)
(make-vect 0.0 0.5))
painter))
You can execute the command (paint (rotate-45 einstein))
to see the rotated image.