» Sunday, 26 September A.D. 2010
the essence of pixel conversion
In the spirit of noodling around with code, I present pixel conversion in Lisp:
(defmethod pixel-reader ((format rgba) buffer start)
#'(lambda ()
(multiple-value-prog1 (values (aref buffer start)
(aref buffer (+ start 1))
(aref buffer (+ start 2))
(aref buffer (+ start 3)))
(incf start 4))))
(defmethod pixel-writer ((format rgba) buffer start)
#'(lambda (r g b a)
(setf (aref buffer start) r
(aref buffer (+ start 1)) g
(aref buffer (+ start 2)) b
(aref buffer (+ start 3)) a)
(incf start 4)
(values)))
(defmethod find-converter ((dst-format rgba-float) (src-format rgba-u8))
#'(lambda (r g b a)
(values (float r 1.0f0) (float g 1.0f0) (float b 1.0f0) (float a 1.0f0))))
(defun convert-pixels (dst-format src-format dst-buffer dst-start
src-buffer src-start n-pixels)
(loop with converter = (find-converter dst-format src-format)
with reader = (pixel-reader src-format src-buffer src-start)
with writer = (pixel-writer dst-format dst-buffer dst-start)
repeat n-pixels
do (multiple-value-call writer
(multiple-value-call converter (funcall reader)))))I think that's pretty code, though probably not very efficient. But tweaking it with something like:
(defmethod pixel-writer ((format rgba-float) buffer start)
#'(lambda (rgba-vec)
(replace buffer rgba-vec :start1 start)
(incf start 4)
(values)))
(defmethod find-converter ((dst-format rgba-float) (src-format rgba-u8))
(let ((rgba-vec (make-array 4 :element-type 'single-float)))
#'(lambda (r g b a)
(setf (aref rgba-vec 0) (float r 1.0f0)
(aref rgba-vec 1) (float g 1.0f0)
(aref rgba-vec 2) (float b 1.0f0)
(aref rgba-vec 3) (float a 1.0f0))
rgba-vec)))would eliminate a major source of consing (depending on the implementation, of course; maybe single-floats aren't boxed in your implementation). The small minus is having to repeat the rgba-vec trick for every conversion function, but maybe there's a clever way around that.
posted by Nate @ 9:47PM