[mcclim-devel] how to do pixel-by-pixel output?
Nikodemus Siivola
nikodemus at random-state.net
Wed Jan 23 04:32:34 UTC 2008
On 1/23/08, Andy Hefner <ahefner at gmail.com> wrote:
> On Jan 22, 2008 6:28 PM, Nikodemus Siivola <nikodemus at random-state.net> wrote:
>
> > Below is what I have now, and it sucks royally: DRAW-PIXEL* calls take ~8
> > seconds on a 400*600 region, and everything else takes < 1 second... (on CLX
> > backend.)
>
> Switching from draw-point* to medium-draw-point* with (setf
> medium-ink) is likely to be a little faster, but still pretty
> hopeless.
>
> > What I would like (and what the above tries to do, but fails) is to get hold of
> > a some sort of object onto which I can efficiently blast colors pixel
> > by pixel, and then update the screen using a convenient-for-me interval.
>
> The existing McCLIM image facilities can (I presume) efficiently
> transfer RGB images, but not in the incremental manner you require.
> Something analogous to xlib:put-image or xlib:put-raw-image seems
> ideal for filling stripes of your pixmap. As a quick and dirty
> solution, I have some old code at
> http://vintage-digital.com/hefner/mcclim/medium-draw-pixels.lisp which
> is a thin wrapper around xlib:put-image and will (probably) work with
> your pixmap, taking a two-dimensional '(unsigned-byte 32) array of
> packed RGB values as input. X11 being what it is, you might have to
> twiddle the :bits-per-pixel (some machines want 32, others 24).
Perfect -- this runs in < 1 second.
(defun render-scene (scene sheet)
(let* ((region (sheet-region sheet))
(width (bounding-rectangle-width region))
(height (bounding-rectangle-height region))
(end (- width 1))
(image (make-array (list 1 width) :element-type '(unsigned-byte 32))))
(raylisp::render scene (raylisp::scene-default-camera scene)
width height
(lambda (color x y)
(declare (type (simple-array single-float (3)) color)
(type fixnum x y))
;; FIXME: Gamma...
(let ((r (floor (* 255 (aref color 0))))
(g (floor (* 255 (aref color 1))))
(b (floor (* 255 (aref color 2)))))
(setf (aref image 0 x) (logior (ash r 16) (ash g 8) b))
(when (= x end)
(with-sheet-medium (medium sheet)
(medium-draw-pixels* medium image 0 y)))))
:normalize-camera t)))
Apropos: while figuring out how use your code I came across
RGB-IMAGE-DESIGN, and managed to make it work for usable well as well
-- code below runs in < 2 seconds.
(defun render-scene (scene medium)
(let* ((region (sheet-region medium))
(width (bounding-rectangle-width region))
(height (bounding-rectangle-height region))
(end (- width 1))
(data (make-array (list 1 width) :element-type '(unsigned-byte 32))))
(raylisp::render scene (raylisp::scene-default-camera scene)
width height
(lambda (color x y)
(declare (type (simple-array single-float (3)) color)
(type fixnum x y))
;; FIXME: Gamma...
(let ((r (floor (* 255 (aref color 0))))
(g (floor (* 255 (aref color 1))))
(b (floor (* 255 (aref color 2)))))
(setf (aref data 0 x) (logior (ash b 16) (ash g 8) r))
(when (= x end)
(let (design)
(unwind-protect
(progn
(setf design (climi::make-rgb-image-design
(make-instance
'climi::rgb-image
:width width
:height 1
:data data)))
(draw-design medium design :y y))
(climi::free-image-design design))))))
:normalize-camera t)))
I can live with CLIMI:: prefixes, etc... but is either of these
expected to land in CLIM-EXTENSIONS anytime soon?
> If you can live without the incremental display, you could display the
> entire image using make-image and draw-image.
...unfortunately incremental display is the only real of having a GUI
on this thing -- it doesn't matter for images that render fast, but
ones that take longer I want to see in progress, so I can abort if
there's something wrong without waiting the whole thing out.
More information about the mcclim-devel
mailing list