[plt-scheme] Byte Swapping Bitmap Performance
At Mon, 3 Aug 2009 11:28:49 -0700, Sam Phillips wrote:
> Except that the bytes from cairo_image_surface_get_data come back as
> BGRA, and I have to do a byte swapping operation before setting the
> pixels in the bitmap-dc. Which adds about a second to each screen draw.
>
> Is there a faster way to do this that I'm missing?
1 second sounds like a long time. Can you show the code that you're
using for the swap?
I tried
(define (rgba->argb src)
(let* ([len (bytes-length src)]
[dest (make-bytes len)]) ; could be just src to overwrite
(for ([i (in-range 0 len 4)])
(let ([r (bytes-ref src i)]
[g (bytes-ref src (+ i 1))]
[b (bytes-ref src (+ i 2))]
[a (bytes-ref src (+ i 3))])
(bytes-set! dest i a)
(bytes-set! dest (+ i 1) r)
(bytes-set! dest (+ i 2) g)
(bytes-set! dest (+ i 3) b)))
dest))
which swaps a byte string representing a 1024x768 area in about 0.1
seconds on my machine.
The following version is about twice as fast, because it uses
`bytes-copy!' to shift the RGB part and then a loop to patch the A
part:
(define (rgba->argb2 src)
(let* ([len (bytes-length src)]
[dest (make-bytes len)])
(bytes-copy! dest 1 src 0 (sub1 len))
(for ([i (in-range 0 len 4)])
(let ([a (bytes-ref src (+ i 3))])
(bytes-set! dest i a)))
dest))
Allocation of the new byte string account for about 1/3 of the time for
that second version. So, if it's ok to update the array:
(define (rgba->argb! src)
(let* ([len (bytes-length src)]
[dest src]
[last (bytes-ref src (sub1 len))])
(bytes-copy! dest 1 src 0 (sub1 len))
(for ([i (in-range 0 (- len 4) 4)])
(let ([a (bytes-ref src (+ i 4))])
(bytes-set! dest i a)))
(bytes-set! dest (- len 4) last)))
which takes about 0.025 seconds on my machine for a 1024x768x4 byte
string.
It looks like an implementation of `rgba->argb!' in C would be about 10
times as fast as that last version.