;; The first three lines of this file were inserted by DrScheme. They record metadata ;; about the language level of this file in a form that our tools can easily process. #reader(lib "htdp-advanced-reader.ss" "lang")((modname image-functions) (read-case-sensitive #t) (teachpacks ((lib "universe.ss" "teachpack" "2htdp"))) (htdp-settings #(#t constructor repeating-decimal #t #t none #f ((lib "universe.ss" "teachpack" "2htdp"))))) (require (lib "universe.ss" "2htdp")) ; overlay/xy:nw : image number number image -> scene ; Overlay `pic` onto `bg`, ; where `pic`s northwest corner is offset by `x`,`y`. ; The result is clipped to `bg`s dimensions. ; ; (This function is just like overlay/xy, except that all images ; use their northwest corner as their reference point ("pinhole"). ; The result also has its pinhole in the nw corner (i.e., it's a 'scene').) ; (define (overlay/xy:nw bg x y pic) (place-image (put-pinhole pic 0 0) x y (put-pinhole bg 0 0))) ; reflect-v : (-> image image) ; Reflect an image vertically (that is, make a mirror image). ; (define (reflect-v img) (let* {[w (image-width img)] [h (image-height img)] [new-pinhole-x (- (image-width img) (pinhole-x img) 1)] } (color-list->image (reflect-list-2d-v (image->color-list img) w h) w h new-pinhole-x (pinhole-y img)))) ; reflect-list-2d-v : (-> lst int int) ; Given a list which *represents* a 2-d w-by-h array, ; return that 2-d array with each row reflected vertically ; (mirror-imaged). ; (define (reflect-list-2d-v data w h) (build-list (* w h) (lambda (i) (let* {[row (quotient i w)] [column (remainder i w)] } (list-ref-2d data w h row (- w column 1)))))) ; rotate90 : (-> image image) ; Rotate an image 90 degrees clockwise. ; (define (rotate90 img) (let* {[w (image-width img)] [h (image-height img)] } (color-list->image (rotate90-list-2d (image->color-list img) w h) h w (- h (pinhole-y img) 1) (pinhole-x img)))) ; list-ref-2d : (-> (list-of any) int int int int) ; index into a list, as if it were a w-by-h 2-D array. ; (define (list-ref-2d lst w h r c) (list-ref lst (+ (* r w) c))) ; reflect-list-2d-v : (-> lst int int) ; Given a list which *represents* a 2-d w-by-h array, ; return that 2-d array with each row reflected vertically ; (mirror-imaged). ; (define (rotate90-list-2d data w h) (build-list (* h w) (lambda (i) (let* {[row (quotient i h)] [col (remainder i h)] } (list-ref-2d data w h (- h col 1) row))))) (check-expect (rotate90-list-2d '(a b) 2 1) '(a b)) (check-expect (rotate90-list-2d '(a b) 1 2) '(b a)) (check-expect (rotate90-list-2d '(a b c d e f g h) 4 2) '(e a f b g c h d)) ;; scale-list-2d : list number number number ;; Return `data` scaled by k (viewing it as a w x h image). ;; (define (scale-list-2d data w h k) (let* {(new-w (*flr w k)) (new-h (*flr h k)) } (build-list (* new-w new-h) (lambda (i) (let* {[row (quotient i new-w)] [col (remainder i new-w)] } (list-ref-2d data w h (/flr row k) (/flr col k))))))) ; Versions of * and / that always return ints. ; Needed for converting pixel-locations when ; scaling by non-integers. ; *flr : number number -> number (define *flr (compose floor *)) ; /flr : number number -> number (define /flr (compose floor /)) ;; N.B. this is the same as: ;; (define (/flr a b) (floor (/ a b)) ; scale-image : image number -> image ; Return img, scaled by a factor of k. (>= k 0) ; ; NB We currently do a crude job when (< k 1) ; (no aliasing/blending of pixels). ; (define (scale-image img k) (let* {[w (image-width img)] [h (image-height img)] } (color-list->image (scale-list-2d (image->color-list img) w h k) (*flr w k) (*flr h k) (*flr (pinhole-x img) k) (*flr (pinhole-y img) k))))