#lang mzscheme
(require
(lib "list.ss") (lib "image.ss" "htdp") )
(provide image-above
image-above-align-right
image-above-align-left
image-above-align-center
image-beside
image-beside-align-top
image-beside-align-bottom
image-beside-align-center
reflect-vert
reflect-horiz
reflect-main-diag
reflect-other-diag
rotate-cw
rotate-ccw
rotate-180
show-pinhole
(all-from (lib "image.ss" "htdp"))
crop-top
crop-bottom
crop-left
crop-right
)
(define (image-translate image dx dy)
(overlay/xy (rectangle (+ (image-width image) dx)
(+ (image-height image) dy)
'solid
'white)
dx
dy
image))
(define (pinhole-to-bottom img)
(- (image-height img) (pinhole-y img)))
(define (pinhole-to-top img)
(pinhole-y img))
(define (pinhole-to-left img)
(pinhole-x img))
(define (pinhole-to-right img)
(- (image-width img) (pinhole-x img)))
(define (concat-vert under over)
(let [[dy (+ (pinhole-to-bottom over) (pinhole-to-top under))]]
(move-pinhole
(overlay/xy over 0 (round (+ (pinhole-to-bottom over) (pinhole-to-top under))) under)
0 (round (/ dy 2)))))
(define (image-above . images)
(cond [(null? images) (error 'image-above "Expected two or more images; given 0")]
[(null? (cdr images)) (error 'image-above "Expected two or more images; given 1")]
[else (foldl concat-vert (car images) (cdr images))]))
(define (image-above-align-right . images)
(apply image-above
(map (lambda (img)
(move-pinhole img (pinhole-to-right img) 0))
images)))
(define (image-above-align-left . images)
(apply image-above
(map (lambda (img)
(move-pinhole img (- (pinhole-to-left img)) 0))
images)))
(define (concat-horiz right left)
(let [[dx (+ (pinhole-to-right left) (pinhole-to-left right))]]
(move-pinhole
(overlay/xy left dx 0 right)
(round (/ dx 2)) 0)))
(define (image-beside . images)
(cond [(null? images) (error 'image-beside "Expected two or more images; given 0")]
[(null? (cdr images)) (error 'image-beside "Expected two or more images; given 1")]
[else (foldl concat-horiz (car images) (cdr images))]))
(define (image-beside-align-top . images)
(apply image-beside
(map (lambda (img)
(move-pinhole img 0 (- (pinhole-to-top img))))
images)))
(define (image-beside-align-bottom . images)
(apply image-beside
(map (lambda (img)
(move-pinhole img 0 (pinhole-to-bottom img)))
images)))
(define (center-pinhole img)
(put-pinhole img
(quotient (image-width img) 2)
(quotient (image-height img) 2)))
(define (image-beside-align-center . images)
(apply image-beside
(map center-pinhole images)))
(define (image-above-align-center . images)
(apply image-above
(map center-pinhole images)))
(define (show-pinhole img)
(overlay img (circle 2 "solid" "black")))
(define (first-n L n)
(cond [(null? L) ()]
[(<= n 0) ()]
[else (cons (car L)
(first-n (cdr L) (- n 1)))]))
(define (rest-n L n)
(cond [(null? L) ()]
[(<= n 0) L]
[else (rest-n (cdr L) (- n 1))]))
(define (slice L width)
(cond [(null? L) ()]
[else (cons (first-n L width)
(slice (rest-n L width) width))]))
(define (slice-pic picture)
(slice (image->color-list picture)
(image-width picture)))
(define (unslice lists)
(apply append lists))
(define (unslice-pic pixels width height phx phy)
(color-list->image
(unslice pixels)
width height phx phy))
(define (reflect-horiz picture)
(unslice-pic
(map reverse
(slice-pic picture))
(image-width picture)
(image-height picture)
(pinhole-to-right picture)
(pinhole-to-top picture)))
(define (crop-left picture pixels)
(let* ((new-width (max 1 (- (image-width picture) pixels)))
(new-phx (max 0 (- (pinhole-x picture) pixels)))
(real-pixels (- (image-width picture) new-width)))
(unslice-pic
(map
(lambda (row) (rest-n row real-pixels))
(slice-pic picture))
new-width
(image-height picture)
new-phx
(pinhole-y picture))))
(define (crop-top picture pixels)
(let* ((new-height (max 1 (- (image-height picture) pixels)))
(new-phy (max 0 (- (pinhole-y picture) pixels)))
(real-pixels (- (image-height picture) new-height)))
(unslice-pic
(rest-n
(slice-pic picture)
real-pixels)
(image-width picture)
new-height
(pinhole-x picture)
new-phy)))
(define (crop-right picture pixels)
(let* ((new-width (max 1 (- (image-width picture) pixels)))
(new-phx (min (pinhole-x picture) new-width)))
(unslice-pic
(map
(lambda (row) (first-n row new-width))
(slice-pic picture))
new-width
(image-height picture)
new-phx
(pinhole-y picture))))
(define (crop-bottom picture pixels)
(let* ((new-height (max 1 (- (image-height picture) pixels)))
(new-phy (min (pinhole-y picture) new-height)))
(unslice-pic
(first-n
(slice-pic picture)
new-height)
(image-width picture)
new-height
(pinhole-x picture)
new-phy)))
(define (reflect-vert picture)
(unslice-pic
(reverse
(slice-pic picture))
(image-width picture)
(image-height picture)
(pinhole-to-left picture)
(pinhole-to-bottom picture)))
(define (ncons-each L)
(map list L))
(define (transpose rows)
(apply map (cons list rows)))
(define (reflect-main-diag picture)
(unslice-pic
(transpose
(slice-pic picture))
(image-height picture)
(image-width picture)
(pinhole-y picture)
(pinhole-x picture)))
(define (reflect-other-diag picture)
(unslice-pic
(reverse
(transpose
(reverse
(slice-pic picture))))
(image-height picture)
(image-width picture)
(pinhole-to-bottom picture)
(pinhole-to-right picture)))
(define (rotate-cw picture)
(unslice-pic
(transpose
(reverse
(slice-pic picture)))
(image-height picture)
(image-width picture)
(pinhole-to-bottom picture)
(pinhole-to-left picture)))
(define (rotate-ccw picture)
(unslice-pic
(reverse
(transpose
(slice-pic picture)))
(image-height picture)
(image-width picture)
(pinhole-to-top picture)
(pinhole-to-right picture)))
(define (rotate-180 picture)
(unslice-pic
(reverse
(map reverse
(slice-pic picture)))
(image-width picture)
(image-height picture)
(pinhole-to-right picture)
(pinhole-to-bottom picture)))