add pre-multiplied mode for `{get,set}-argb-pixels'
This commit is contained in:
parent
006d5ef45a
commit
b6445880e2
|
@ -132,20 +132,22 @@
|
||||||
[exact-nonnegative-integer? w]
|
[exact-nonnegative-integer? w]
|
||||||
[exact-nonnegative-integer? h]
|
[exact-nonnegative-integer? h]
|
||||||
[bytes? bstr]
|
[bytes? bstr]
|
||||||
[any? [set-alpha? #f]])
|
[any? [set-alpha? #f]]
|
||||||
|
[any? [pre-mult? #f]])
|
||||||
(let ([bm (internal-get-bitmap)])
|
(let ([bm (internal-get-bitmap)])
|
||||||
(when bm
|
(when bm
|
||||||
(send bm set-argb-pixels x y w h bstr set-alpha?))))
|
(send bm set-argb-pixels x y w h bstr set-alpha? pre-mult?))))
|
||||||
|
|
||||||
(def/public (get-argb-pixels [exact-nonnegative-integer? x]
|
(def/public (get-argb-pixels [exact-nonnegative-integer? x]
|
||||||
[exact-nonnegative-integer? y]
|
[exact-nonnegative-integer? y]
|
||||||
[exact-nonnegative-integer? w]
|
[exact-nonnegative-integer? w]
|
||||||
[exact-nonnegative-integer? h]
|
[exact-nonnegative-integer? h]
|
||||||
[bytes? bstr]
|
[bytes? bstr]
|
||||||
[any? [get-alpha? #f]])
|
[any? [get-alpha? #f]]
|
||||||
|
[any? [pre-mult? #f]])
|
||||||
(let ([bm (internal-get-bitmap)])
|
(let ([bm (internal-get-bitmap)])
|
||||||
(when bm
|
(when bm
|
||||||
(send bm get-argb-pixels x y w h bstr get-alpha?))))
|
(send bm get-argb-pixels x y w h bstr get-alpha? pre-mult?))))
|
||||||
|
|
||||||
(def/public (draw-bitmap-section-smooth [bitmap% src]
|
(def/public (draw-bitmap-section-smooth [bitmap% src]
|
||||||
[real? dest-x]
|
[real? dest-x]
|
||||||
|
|
|
@ -572,7 +572,8 @@
|
||||||
[exact-nonnegative-integer? w]
|
[exact-nonnegative-integer? w]
|
||||||
[exact-nonnegative-integer? h]
|
[exact-nonnegative-integer? h]
|
||||||
[bytes? bstr]
|
[bytes? bstr]
|
||||||
[any? [get-alpha? #f]])
|
[any? [get-alpha? #f]]
|
||||||
|
[any? [pre-mult? #f]])
|
||||||
(unless ((bytes-length bstr) . >= . (* w h 4))
|
(unless ((bytes-length bstr) . >= . (* w h 4))
|
||||||
(raise-mismatch-error (method-name 'bitmap% 'get-argb-pixels)
|
(raise-mismatch-error (method-name 'bitmap% 'get-argb-pixels)
|
||||||
"byte string is too short: "
|
"byte string is too short: "
|
||||||
|
@ -581,10 +582,10 @@
|
||||||
(if alt?
|
(if alt?
|
||||||
(call-with-alt-bitmap
|
(call-with-alt-bitmap
|
||||||
x y w h
|
x y w h
|
||||||
(lambda (bm) (send bm get-argb-pixels 0 0 w h bstr get-alpha?)))
|
(lambda (bm) (send bm get-argb-pixels 0 0 w h bstr get-alpha? pre-mult?)))
|
||||||
(do-get-argb-pixels x y w h bstr get-alpha?))))
|
(do-get-argb-pixels x y w h bstr get-alpha? pre-mult?))))
|
||||||
|
|
||||||
(define/private (do-get-argb-pixels x y w h bstr get-alpha?)
|
(define/private (do-get-argb-pixels x y w h bstr get-alpha? pre-mult?)
|
||||||
;; Fill range that is beyond edge of picture:
|
;; Fill range that is beyond edge of picture:
|
||||||
(if get-alpha?
|
(if get-alpha?
|
||||||
(for* ([i (in-range width (+ x w))]
|
(for* ([i (in-range width (+ x w))]
|
||||||
|
@ -603,7 +604,7 @@
|
||||||
(cairo_surface_flush s)
|
(cairo_surface_flush s)
|
||||||
(let ([data (cairo_image_surface_get_data s)]
|
(let ([data (cairo_image_surface_get_data s)]
|
||||||
[row-width (cairo_image_surface_get_stride s)]
|
[row-width (cairo_image_surface_get_stride s)]
|
||||||
[use-alpha? (or alpha-channel? b&w?)]
|
[use-alpha? (or (and alpha-channel? (not pre-mult?)) b&w?)]
|
||||||
[set-alpha? alpha-channel?])
|
[set-alpha? alpha-channel?])
|
||||||
(let ([w2 (+ x (min (- width x) w))])
|
(let ([w2 (+ x (min (- width x) w))])
|
||||||
(for* ([j (in-range y (min (+ y h) height))])
|
(for* ([j (in-range y (min (+ y h) height))])
|
||||||
|
@ -652,7 +653,8 @@
|
||||||
[exact-nonnegative-integer? w]
|
[exact-nonnegative-integer? w]
|
||||||
[exact-nonnegative-integer? h]
|
[exact-nonnegative-integer? h]
|
||||||
[bytes? bstr]
|
[bytes? bstr]
|
||||||
[any? [set-alpha? #f]])
|
[any? [set-alpha? #f]]
|
||||||
|
[any? [pre-mult? #f]])
|
||||||
(unless ((bytes-length bstr) . >= . (* w h 4))
|
(unless ((bytes-length bstr) . >= . (* w h 4))
|
||||||
(raise-mismatch-error (method-name 'bitmap% 'set-argb-pixels)
|
(raise-mismatch-error (method-name 'bitmap% 'set-argb-pixels)
|
||||||
"byte string is too short: "
|
"byte string is too short: "
|
||||||
|
@ -687,7 +689,9 @@
|
||||||
(if alpha-channel?
|
(if alpha-channel?
|
||||||
(let ([a (bytes-ref bstr pi)]
|
(let ([a (bytes-ref bstr pi)]
|
||||||
[pm (lambda (a v)
|
[pm (lambda (a v)
|
||||||
(quotient (* a v) 255))])
|
(if pre-mult?
|
||||||
|
(min a v)
|
||||||
|
(quotient (* a v) 255)))])
|
||||||
(bytes-set! data (+ ri A) a)
|
(bytes-set! data (+ ri A) a)
|
||||||
(bytes-set! data (+ ri R) (pm a (bytes-ref bstr (+ pi 1))))
|
(bytes-set! data (+ ri R) (pm a (bytes-ref bstr (+ pi 1))))
|
||||||
(bytes-set! data (+ ri G) (pm a (bytes-ref bstr (+ pi 2))))
|
(bytes-set! data (+ ri G) (pm a (bytes-ref bstr (+ pi 2))))
|
||||||
|
|
|
@ -63,7 +63,8 @@ When a @scheme[bits] byte string is provided: Creates a monochrome
|
||||||
[width exact-nonnegative-integer?]
|
[width exact-nonnegative-integer?]
|
||||||
[height exact-nonnegative-integer?]
|
[height exact-nonnegative-integer?]
|
||||||
[pixels (and/c bytes? mutable?)]
|
[pixels (and/c bytes? mutable?)]
|
||||||
[alpha? any/c #f])
|
[just-alpha? any/c #f]
|
||||||
|
[pre-multiplied? any/c #f])
|
||||||
void?]{
|
void?]{
|
||||||
|
|
||||||
Produces the same result as @xmethod[bitmap-dc% get-argb-pixels], but the
|
Produces the same result as @xmethod[bitmap-dc% get-argb-pixels], but the
|
||||||
|
@ -264,7 +265,8 @@ A monochrome bitmap saved as @scheme['png] without a mask bitmap
|
||||||
[width exact-nonnegative-integer?]
|
[width exact-nonnegative-integer?]
|
||||||
[height exact-nonnegative-integer?]
|
[height exact-nonnegative-integer?]
|
||||||
[pixels bytes?]
|
[pixels bytes?]
|
||||||
[alpha? any/c #f])
|
[just-alpha? any/c #f]
|
||||||
|
[pre-multiplied? any/c #f])
|
||||||
void?]{
|
void?]{
|
||||||
|
|
||||||
The same as @xmethod[bitmap-dc% set-argb-pixels], but the
|
The same as @xmethod[bitmap-dc% set-argb-pixels], but the
|
||||||
|
|
|
@ -54,7 +54,8 @@ In older versions, this method smoothed drawing more than
|
||||||
[width exact-nonnegative-integer?]
|
[width exact-nonnegative-integer?]
|
||||||
[height exact-nonnegative-integer?]
|
[height exact-nonnegative-integer?]
|
||||||
[pixels (and/c bytes? (not/c immutable?))]
|
[pixels (and/c bytes? (not/c immutable?))]
|
||||||
[alpha? any/c #f])
|
[just-alpha? any/c #f]
|
||||||
|
[pre-multiplied? any/c #f])
|
||||||
void?]{
|
void?]{
|
||||||
|
|
||||||
Gets a rectangle of pixels in the bitmap, subject to the same rules
|
Gets a rectangle of pixels in the bitmap, subject to the same rules
|
||||||
|
@ -73,15 +74,20 @@ The pixel RGB values are copied into @scheme[pixels]. The first byte
|
||||||
DC. The pixels are in row-major order, left to right then top to
|
DC. The pixels are in row-major order, left to right then top to
|
||||||
bottom.
|
bottom.
|
||||||
|
|
||||||
If @scheme[alpha?] is false, if the bitmap does not have an alpha
|
If @scheme[just-alpha?] is false, if the bitmap does not have an alpha
|
||||||
channel, then the alpha value for each pixel is set to 255. If
|
channel, then the alpha value for each pixel is set to 255. If
|
||||||
@scheme[alpha?] is true, then @italic{only} the alpha value is set
|
@scheme[just-alpha?] is true, then @italic{only} the alpha value is set
|
||||||
for each pixel; if the bitmap has no alpha channel, then the alpha
|
for each pixel; if the bitmap has no alpha channel, then the alpha
|
||||||
value is based on each pixel's inverted RGB average. Thus, when a
|
value is based on each pixel's inverted RGB average. Thus, when a
|
||||||
bitmap has a separate mask bitmap, the same @scheme[pixels] byte
|
bitmap has a separate mask bitmap, the same @scheme[pixels] byte
|
||||||
string is in general filled from two bitmaps: one (the main image)
|
string is in general filled from two bitmaps: one (the main image)
|
||||||
for the pixel values and one (the mask) for the alpha values.
|
for the pixel values and one (the mask) for the alpha values.
|
||||||
|
|
||||||
|
If @racket[pre-multiplied?] is true, @scheme[just-alpha?] is false,
|
||||||
|
and the bitmap has an alpha channel, then RGB values in the result
|
||||||
|
are scaled by the corresponding alpha value (i.e., multiplied by the
|
||||||
|
alpha value and then divided by 255).
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@defmethod[(get-bitmap)
|
@defmethod[(get-bitmap)
|
||||||
|
@ -110,7 +116,8 @@ result is @scheme[#f].
|
||||||
[width exact-nonnegative-integer?]
|
[width exact-nonnegative-integer?]
|
||||||
[height exact-nonnegative-integer?]
|
[height exact-nonnegative-integer?]
|
||||||
[pixels bytes?]
|
[pixels bytes?]
|
||||||
[alpha? any/c #f])
|
[just-alpha? any/c #f]
|
||||||
|
[pre-multiplied? any/c #f])
|
||||||
void?]{
|
void?]{
|
||||||
|
|
||||||
|
|
||||||
|
@ -126,8 +133,9 @@ The pixel RGB values are taken from @scheme[pixels]. The first byte
|
||||||
determine the new pixel values in the DC. The pixels are in row-major
|
determine the new pixel values in the DC. The pixels are in row-major
|
||||||
order, left to right then top to bottom.
|
order, left to right then top to bottom.
|
||||||
|
|
||||||
If @scheme[alpha?] is false, then the alpha value for each pixel is
|
If @scheme[just-alpha?] is false, then the alpha value for each pixel is
|
||||||
used only if the DC's current bitmap has an alpha channel. If @scheme[alpha?] is true, then each
|
used only if the DC's current bitmap has an alpha channel. If
|
||||||
|
@scheme[just-alpha?] is true and the bitmap has no alpha channel, then each
|
||||||
pixel is set based @italic{only} on the alpha value, but inverted to serve
|
pixel is set based @italic{only} on the alpha value, but inverted to serve
|
||||||
as a mask. Thus, when working with bitmaps that have an associated mask
|
as a mask. Thus, when working with bitmaps that have an associated mask
|
||||||
bitmap instead of an alpha channel, the same
|
bitmap instead of an alpha channel, the same
|
||||||
|
@ -135,6 +143,14 @@ If @scheme[alpha?] is false, then the alpha value for each pixel is
|
||||||
(the main image) for the pixel values and one (the mask) for the
|
(the main image) for the pixel values and one (the mask) for the
|
||||||
alpha values.
|
alpha values.
|
||||||
|
|
||||||
|
If @racket[pre-multiplied?] is true, @scheme[just-alpha?] is false,
|
||||||
|
and the bitmap has an alpha channel, then RGB values in
|
||||||
|
@racket[pixels] are interpreted as scaled by the corresponding alpha value
|
||||||
|
(i.e., multiplied by the alpha value and then divided by 255). If an
|
||||||
|
R, G, or B value is greater than its corresponding alpha value (which
|
||||||
|
is not possible if the value is properly scaled), then it is effectively
|
||||||
|
reduced to the alpha value.
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@defmethod[(set-bitmap [bitmap (or/c (is-a?/c bitmap%) false/c)])
|
@defmethod[(set-bitmap [bitmap (or/c (is-a?/c bitmap%) false/c)])
|
||||||
|
|
|
@ -364,6 +364,7 @@
|
||||||
(mk #"\377\377\377\377\377\377\377\377\377\0\0\0\377\0\0\0" 'opaque black white #t))
|
(mk #"\377\377\377\377\377\377\377\377\377\0\0\0\377\0\0\0" 'opaque black white #t))
|
||||||
|
|
||||||
;; ----------------------------------------
|
;; ----------------------------------------
|
||||||
|
;; check get-alpha mode of `get-argb-pixels'
|
||||||
|
|
||||||
(let ()
|
(let ()
|
||||||
(define (get-column-alpha bm x y)
|
(define (get-column-alpha bm x y)
|
||||||
|
@ -378,7 +379,7 @@
|
||||||
(bytes-ref bstr 2))
|
(bytes-ref bstr 2))
|
||||||
3)))
|
3)))
|
||||||
(send abm set-argb-pixels 0 0 2 2 #"0123456789abcdef")
|
(send abm set-argb-pixels 0 0 2 2 #"0123456789abcdef")
|
||||||
(send nbm set-argb-pixels 0 0 2 2 #"0123456789abcdef")
|
(send nbm set-argb-pixels 0 0 2 2 #"0123456789abcdef") ; alphas ignored
|
||||||
|
|
||||||
(test (bytes (char->integer #\0) 0 0 0) 'a0+0 (get-column-alpha abm 0 0))
|
(test (bytes (char->integer #\0) 0 0 0) 'a0+0 (get-column-alpha abm 0 0))
|
||||||
(test (bytes (char->integer #\4) 0 0 0) 'a1+0 (get-column-alpha abm 1 0))
|
(test (bytes (char->integer #\4) 0 0 0) 'a1+0 (get-column-alpha abm 1 0))
|
||||||
|
@ -390,6 +391,34 @@
|
||||||
(test (bytes (avg #"9ab") 0 0 0) 'n0+1 (get-column-alpha nbm 0 1))
|
(test (bytes (avg #"9ab") 0 0 0) 'n0+1 (get-column-alpha nbm 0 1))
|
||||||
(test (bytes (avg #"def") 0 0 0) 'n1+1 (get-column-alpha nbm 1 1)))
|
(test (bytes (avg #"def") 0 0 0) 'n1+1 (get-column-alpha nbm 1 1)))
|
||||||
|
|
||||||
|
;; ----------------------------------------
|
||||||
|
;; check pre-mult mode of `{get,set}-argb-pixels'
|
||||||
|
|
||||||
|
(let ()
|
||||||
|
(define abm (make-object bitmap% 2 2 #f #t))
|
||||||
|
(define nbm (make-object bitmap% 2 2 #f #f))
|
||||||
|
(send abm set-argb-pixels 0 0 2 2 #"30127456b89afcde" #f #t)
|
||||||
|
(send nbm set-argb-pixels 0 0 2 2 #"0123456789abcdef" #f #t) ; alphas ignored
|
||||||
|
|
||||||
|
(define (get-pixels bm pre-mult?)
|
||||||
|
(define bs (make-bytes 16))
|
||||||
|
(send bm get-argb-pixels 0 0 2 2 bs #f pre-mult?)
|
||||||
|
bs)
|
||||||
|
|
||||||
|
(define (unmul b)
|
||||||
|
(define (um v) (quotient (* v 255) (bytes-ref b 0)))
|
||||||
|
(bytes (bytes-ref b 0)
|
||||||
|
(um (bytes-ref b 1))
|
||||||
|
(um (bytes-ref b 2))
|
||||||
|
(um (bytes-ref b 3))))
|
||||||
|
|
||||||
|
(test #"\xFF123\xFF567\xFF9ab\xFFdef" 'no-alpha (get-pixels nbm #f))
|
||||||
|
(test #"\xFF123\xFF567\xFF9ab\xFFdef" 'no-alpha (get-pixels nbm #t))
|
||||||
|
|
||||||
|
(test (apply bytes-append (map unmul '(#"3012" #"7456" #"b89a" #"fcde")))
|
||||||
|
'alpha-normal (get-pixels abm #f))
|
||||||
|
(test #"30127456b89afcde" 'alpha-premult (get-pixels abm #t)))
|
||||||
|
|
||||||
|
|
||||||
;; ----------------------------------------
|
;; ----------------------------------------
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user