[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