fixed a bug found by random testing
This commit is contained in:
parent
720a86052f
commit
8d2db5f4bf
|
@ -281,13 +281,13 @@
|
|||
;; crops an image to be w x h from (x,y)
|
||||
(define/chk (crop x1 y1 width height image)
|
||||
(check-arg 'crop
|
||||
(x1 . <= . (image-width image))
|
||||
(format "number that is smaller than the width (~a)" (image-width image))
|
||||
(<= 0 x1 (image-width image))
|
||||
(format "number that is between 0 than the width (~a)" (image-width image))
|
||||
1
|
||||
x1)
|
||||
(check-arg 'crop
|
||||
(y1 . <= . (image-height image))
|
||||
(format "number that is smaller than the width (~a)" (image-width image))
|
||||
(<= 0 y1 (image-height image))
|
||||
(format "number that is between 0 and the height (~a)" (image-height image))
|
||||
2
|
||||
y1)
|
||||
(let ([w (min width (- (image-width image) x1))]
|
||||
|
@ -295,14 +295,12 @@
|
|||
(crop/internal x1 y1 w h image)))
|
||||
|
||||
(define (crop/internal x1 y1 width height image)
|
||||
(let* ([iw (min width (get-right image))]
|
||||
[ih (min height (get-bottom image))]
|
||||
[points (rectangle-points iw ih)])
|
||||
(let* ([points (rectangle-points width height)])
|
||||
(make-image (make-crop points
|
||||
(make-translate (- x1) (- y1) (image-shape image)))
|
||||
(make-bb iw
|
||||
ih
|
||||
(min ih (get-baseline image)))
|
||||
(make-bb width
|
||||
height
|
||||
(min height (get-baseline image)))
|
||||
#f)))
|
||||
|
||||
;; place-image : image x y scene -> scene
|
||||
|
@ -432,19 +430,19 @@
|
|||
(translate-dy simple-shape))))])
|
||||
(make-translate dx dy rotated)))]))
|
||||
|
||||
(define-struct ltrb (left top right bottom))
|
||||
(struct ltrb (left top right bottom) #:transparent)
|
||||
(define (union-ltrb ltrb1 ltrb2)
|
||||
(make-ltrb (min (ltrb-left ltrb1) (ltrb-left ltrb2))
|
||||
(min (ltrb-top ltrb1) (ltrb-top ltrb2))
|
||||
(max (ltrb-right ltrb1) (ltrb-right ltrb2))
|
||||
(max (ltrb-bottom ltrb1) (ltrb-bottom ltrb2))))
|
||||
(ltrb (min (ltrb-left ltrb1) (ltrb-left ltrb2))
|
||||
(min (ltrb-top ltrb1) (ltrb-top ltrb2))
|
||||
(max (ltrb-right ltrb1) (ltrb-right ltrb2))
|
||||
(max (ltrb-bottom ltrb1) (ltrb-bottom ltrb2))))
|
||||
|
||||
;; only intersection if they already overlap.
|
||||
(define (intersect-ltrb ltrb1 ltrb2)
|
||||
(make-ltrb (max (ltrb-left ltrb1) (ltrb-left ltrb2))
|
||||
(max (ltrb-top ltrb1) (ltrb-top ltrb2))
|
||||
(min (ltrb-right ltrb1) (ltrb-right ltrb2))
|
||||
(min (ltrb-bottom ltrb1) (ltrb-bottom ltrb2))))
|
||||
(ltrb (max (ltrb-left ltrb1) (ltrb-left ltrb2))
|
||||
(max (ltrb-top ltrb1) (ltrb-top ltrb2))
|
||||
(min (ltrb-right ltrb1) (ltrb-right ltrb2))
|
||||
(min (ltrb-bottom ltrb1) (ltrb-bottom ltrb2))))
|
||||
|
||||
(define/contract (normalized-shape-bb shape)
|
||||
(-> normalized-shape? ltrb?)
|
||||
|
@ -477,33 +475,33 @@
|
|||
[y1 (point-y (line-segment-start simple-shape))]
|
||||
[x2 (point-x (line-segment-end simple-shape))]
|
||||
[y2 (point-y (line-segment-end simple-shape))])
|
||||
(make-ltrb (min x1 x2)
|
||||
(min y1 y2)
|
||||
(+ (max x1 x2) 1)
|
||||
(+ (max y1 y2) 1)))]
|
||||
(ltrb (min x1 x2)
|
||||
(min y1 y2)
|
||||
(+ (max x1 x2) 1)
|
||||
(+ (max y1 y2) 1)))]
|
||||
[(curve-segment? simple-shape)
|
||||
(let ([x1 (point-x (curve-segment-start simple-shape))]
|
||||
[y1 (point-y (curve-segment-start simple-shape))]
|
||||
[x2 (point-x (curve-segment-end simple-shape))]
|
||||
[y2 (point-y (curve-segment-end simple-shape))])
|
||||
(make-ltrb (min x1 x2)
|
||||
(min y1 y2)
|
||||
(+ (max x1 x2) 1)
|
||||
(+ (max y1 y2) 1)))]
|
||||
(ltrb (min x1 x2)
|
||||
(min y1 y2)
|
||||
(+ (max x1 x2) 1)
|
||||
(+ (max y1 y2) 1)))]
|
||||
[(polygon? simple-shape)
|
||||
(points->ltrb (polygon-points simple-shape))]
|
||||
[else
|
||||
(let ([dx (translate-dx simple-shape)]
|
||||
[dy (translate-dy simple-shape)])
|
||||
(let-values ([(l t r b) (np-atomic-bb (translate-shape simple-shape))])
|
||||
(make-ltrb (+ l dx)
|
||||
(+ t dy)
|
||||
(+ r dx)
|
||||
(+ b dy))))]))
|
||||
(ltrb (+ l dx)
|
||||
(+ t dy)
|
||||
(+ r dx)
|
||||
(+ b dy))))]))
|
||||
|
||||
(define (points->ltrb points)
|
||||
(let-values ([(left top right bottom) (points->ltrb-values points)])
|
||||
(make-ltrb left top right bottom)))
|
||||
(ltrb left top right bottom)))
|
||||
|
||||
(define/contract (np-atomic-bb atomic-shape)
|
||||
(-> np-atomic-shape? (values number? number? number? number?))
|
||||
|
|
|
@ -1388,6 +1388,9 @@
|
|||
(check-exn #rx"crop" (λ () (crop 100 100 10 10 (rectangle 20 20 "solid" "black"))))
|
||||
(check-exn #rx"crop" (λ () (crop 9 100 10 10 (rectangle 20 20 "solid" "black"))))
|
||||
(check-exn #rx"crop" (λ () (crop 100 9 10 10 (rectangle 20 20 "solid" "black"))))
|
||||
(check-exn #rx"crop" (λ () (crop -9 9 10 10 (rectangle 20 20 "solid" "black"))))
|
||||
(check-exn #rx"crop" (λ () (crop 9 -9 10 10 (rectangle 20 20 "solid" "black"))))
|
||||
|
||||
(test (crop 20 20 100 100 (rectangle 40 40 "solid" "black"))
|
||||
=>
|
||||
(rectangle 20 20 "solid" "black"))
|
||||
|
@ -1622,8 +1625,8 @@
|
|||
(underlay image image)
|
||||
(underlay/xy image coord coord image)
|
||||
(let ([i image])
|
||||
(crop (min (image-width i) coord)
|
||||
(min (image-height i) coord)
|
||||
(crop (max 0 (min (image-width i) coord))
|
||||
(max 0 (min (image-height i) coord))
|
||||
size
|
||||
size
|
||||
i))
|
||||
|
@ -1672,15 +1675,6 @@
|
|||
(error 'test-image.ss "found differing sizes for ~s:\n ~s\n ~s"
|
||||
img-sexp raw-size norm-size))))
|
||||
|
||||
(define (test-save/load img fn)
|
||||
(let ([t1 (new text%)]
|
||||
[t2 (new text%)])
|
||||
(send t1 insert img)
|
||||
(send t1 save-file fn)
|
||||
(send t2 load-file fn)
|
||||
(let ([s1 (send t1 find-first-snip)]
|
||||
[s2 (send t2 find-first-snip)])
|
||||
(equal? s1 s2))))
|
||||
|
||||
(time
|
||||
(redex-check
|
||||
|
@ -1691,17 +1685,57 @@
|
|||
(to-img (eval (term image) (namespace-anchor->namespace anchor))))
|
||||
#:attempts 1000))
|
||||
|
||||
;; this one is commented out because it catches
|
||||
;; a bug where cropping a shape outside of its
|
||||
;; bounding box leads to strange, bad behavior.
|
||||
(define (test-save/load img fn)
|
||||
(let ([t1 (new text%)]
|
||||
[t2 (new text%)])
|
||||
(send t1 insert img)
|
||||
(send t1 save-file fn)
|
||||
(send t2 load-file fn)
|
||||
(let ([s1 (send t1 find-first-snip)]
|
||||
[s2 (send t2 find-first-snip)])
|
||||
(equal? s1 s2))))
|
||||
|
||||
;; scale-down : image -> image
|
||||
;; scale image so that it is at most 10000 pixels in area
|
||||
(define (scale-down img)
|
||||
(let* ([w (image-width img)]
|
||||
[h (image-height img)]
|
||||
[s (* w h)]
|
||||
[max-s (sqr 100)])
|
||||
(if (< s max-s)
|
||||
img
|
||||
(scale/xy (/ (sqrt max-s) w)
|
||||
(/ (sqrt max-s) h)
|
||||
img))))
|
||||
|
||||
#;
|
||||
(time
|
||||
(let ([fn (make-temporary-file "test-image~a")])
|
||||
(redex-check
|
||||
2htdp/image
|
||||
image
|
||||
(let ([img (to-img (eval (term image) (namespace-anchor->namespace anchor)))])
|
||||
(unless (test-save/load img fn)
|
||||
(error 'test-image.rkt "saving and loading this image fails:\n ~s" (term image))))
|
||||
(let-values ([(ans real cpu gc)
|
||||
(time-apply
|
||||
(λ ()
|
||||
(let ([img (to-img (eval (term image) (namespace-anchor->namespace anchor)))])
|
||||
(test-save/load (scale-down img) fn)))
|
||||
'())])
|
||||
(unless (car ans)
|
||||
(error 'test-image.rkt
|
||||
"saving and loading this image fails:\n ~s"
|
||||
(term image)))
|
||||
(unless (< cpu 2000)
|
||||
(error 'test-image.rkt
|
||||
"saving and loading this image takes too longer than 2 seconds:\n ~s"
|
||||
(term image))))
|
||||
#:attempts 1000)))
|
||||
|
||||
;;This expression was found by the below. Its problematic because it has a negative width.
|
||||
#;
|
||||
(begin
|
||||
(define i
|
||||
(let* ([b (rectangle 17 17 "solid" "black")]
|
||||
[i (overlay/xy b -37 40 b)])
|
||||
(rotate 30 (crop 54 30 20 10 i))))
|
||||
(image-width i) (image-height i) i)
|
||||
|
||||
|
|
|
@ -1019,8 +1019,8 @@ the parts that fit onto @racket[scene].
|
|||
(scale/xy 1 1/2 (flip-vertical (star 40 "solid" "gray"))))]
|
||||
}
|
||||
|
||||
@defproc[(crop [x (and/c real? (<=/c (image-width image)))]
|
||||
[y (and/c real? (<=/c (image-height image)))]
|
||||
@defproc[(crop [x (and/c real? (between/c 0 (image-width image)))]
|
||||
[y (and/c real? (between/c 0 (image-height image)))]
|
||||
[width (and/c real? (not/c negative?))]
|
||||
[height (and/c real? (not/c negative?))]
|
||||
[image image?])
|
||||
|
@ -1029,8 +1029,8 @@ the parts that fit onto @racket[scene].
|
|||
Crops @racket[image] to the rectangle with the upper left at the point (@racket[x],@racket[y])
|
||||
and with @racket[width] and @racket[height].
|
||||
|
||||
The @racket[x] and @racket[y] arguments must be smaller than or equal to
|
||||
the @racket[width] and @racket[height], respectively.
|
||||
The @racket[x] and @racket[y] arguments must be between 0 and
|
||||
the @racket[width] or @racket[height], respectively.
|
||||
|
||||
@image-examples[(crop 0 0 40 40 (circle 40 "solid" "chocolate"))
|
||||
(crop 40 60 40 60 (ellipse 80 120 "solid" "dodgerblue"))
|
||||
|
|
Loading…
Reference in New Issue
Block a user