diff --git a/collects/mrlib/image-core.ss b/collects/mrlib/image-core.ss index 04627e91..4ca2a2f1 100644 --- a/collects/mrlib/image-core.ss +++ b/collects/mrlib/image-core.ss @@ -90,9 +90,6 @@ has been moved out). (define (image-normalized? p) (send p get-normalized?)) (define (set-image-shape! p s) (send p set-shape s)) (define (set-image-normalized?! p n?) (send p set-normalized? n?)) -(define (image-right image) (bb-right (image-bb image))) -(define (image-bottom image) (bb-bottom (image-bb image))) -(define (image-baseline image) (bb-baseline (image-bb image))) (define (image? p) (or (is-a? p image%) (is-a? p image-snip%) @@ -240,13 +237,12 @@ has been moved out). (define image% (class* snip% (equal<%>) (init-field shape bb normalized?) - (define/public (equal-to? that eq-recur) + (define/public (equal-to? that eq-recur) (or (eq? this that) - (and (eq-recur bb (send that get-bb)) - (let* ([w (ceiling (max (inexact->exact (bb-right bb)) - (inexact->exact (bb-right (send that get-bb)))))] - [h (ceiling (max (inexact->exact (bb-bottom bb)) - (inexact->exact (bb-bottom (send that get-bb)))))] + (and (is-a? that image%) + (same-bb? bb (send that get-bb)) + (let* ([w (round (inexact->exact (bb-right bb)))] + [h (round (inexact->exact (bb-bottom bb)))] [bm1 (make-object bitmap% w h)] [bm2 (make-object bitmap% w h)] [bytes1 (make-bytes (* w h 4) 0)] @@ -341,6 +337,10 @@ has been moved out). (inherit set-snipclass) (set-snipclass snip-class))) +(define (same-bb? bb1 bb2) + (and (= (round (bb-right bb1)) (round (bb-right bb2))) + (= (round (bb-bottom bb1)) (round (bb-bottom bb2))) + (= (round (bb-baseline bb1)) (round (bb-baseline bb2))))) (define scheme/base:read read) (define image-snipclass% @@ -808,9 +808,6 @@ the mask bitmap and the original bitmap are all together in a single bytes! ellipse-rotated-size image? - image-right - image-bottom - image-baseline text->font compare-all-rotations diff --git a/collects/mrlib/private/image-core-bitmap.ss b/collects/mrlib/private/image-core-bitmap.ss index 112af700..9be7037f 100644 --- a/collects/mrlib/private/image-core-bitmap.ss +++ b/collects/mrlib/private/image-core-bitmap.ss @@ -97,16 +97,26 @@ instead of this scaling code, we use the dc<%>'s scaling code. (values (build-bmbytes new-w new-h (λ (x y) - (let* {[pre-image (* (make-rectangular (+ west x) (- nrth y)) + (let* {[pre-image (* (make-rectangular (+ west x 1/2) (- nrth y 1/2)) theta-unrotation)] } (interpolate bmbytes w h (real-part pre-image) (- (imag-part pre-image)))))) new-w - new-h))) - - + new-h))) +;; Why the offsets of 1/2 in `rotate-bytes` and `interpolate`? +;; We consider a pixel's RGB as a point-sample taken from the 'true' image, +;; where the RGB is the sample at the *center* of the square covered by the pixel. +;; (When we assume the sample had been from the NW corner instead of the center, +;; we got weird artifacts upon rotation: +;; Consider a 1x1 bitmap rotated by 90 degrees. +;; The NW corner of our new value would be derived from the *NE* corner of +;; the original bitmap, which is a full pixel-width away from the original sample. +;; So a 1x1 bitmap being rotated would counterintuitively give a different bitmap.) + + + ; interpolate: bytes natnum natum real real -> bytes ; ; Given a bitmap (bytes of size (* w h NUM-CHANNELS)), return a pixel (bytes of size NUM-CHANNELS) @@ -114,10 +124,10 @@ instead of this scaling code, we use the dc<%>'s scaling code. ; where x,y are *real-valued* coordinates in [0,w), [0,h). ; (define (interpolate bmbytes w h x y) - (let* {[x0 (floor/e x)] - [y0 (floor/e y)] - [dx (- x x0)] - [dy (- y y0)] + (let* {[x0 (floor/e (- x 1/2))] + [y0 (floor/e (- y 1/2))] + [dx (- (- x 1/2) x0)] + [dy (- (- y 1/2) y0)] [1-dx (- 1 dx)] [1-dy (- 1 dy)] [nw (bmbytes-ref/safe bmbytes w h x0 y0 )]