[ab] Fast pixel access

Anthony Fairchild anthonyf at blarg.net
Sun Nov 26 17:56:32 CST 2006


Hello again,

I've been playing around with lispbuilder-SDL a bit over the holiday
weekend and started writing a simple jigsaw puzzle-like game.  I'm
very happy with what I have so far but I'm running into a bit of
slowness when doing direct pixel manipulation, specifically, rotating
images.

I've looked at rotozoom in the gfx package and I could not get it to
work (that's another issue altogether).  Rotating an image seemed like
such a simple thing anyway, so I wrote my own
likely-over-complicated-and-bug-ridden function to do it:

(defun rotate-surface(surf degrees)
  "rotates a surface 0, 90, 180, or 270 degrees"
  (let ((degrees (normalize-degrees degrees)))
    (if (= 0 degrees)
        ;; in the case of 0 degrees, just copy surface
        (copy-and-blit-surface surf)
        ;; else do rotation
        (let* ((w (surf-w surf))
               (h (surf-h surf))
               (new-w (if (or (= 90 degrees)
                              (= 270 degrees)) h w))
               (new-h (if (or (= 90 degrees)
                              (= 270 degrees)) w h))
               (new-surf (create-surface new-w new-h :surface surf))
               (new-x (case degrees
                        (90  #'(lambda (x y)(declare (ignore x))(+ (1-
new-w) (- 0 y))))
                        (180 #'(lambda (x y)(declare (ignore y))(+ (1-
new-w) (- 0 x))))
                        (270 #'(lambda (x y)(declare (ignore x))y))))
               (new-y (case degrees
                        (90  #'(lambda (x y)(declare (ignore y))x))
                        (180 #'(lambda (x y)(declare (ignore x))(+ (1-
new-h) (- 0 y))))
                        (270 #'(lambda (x y)(declare (ignore y))(+ (1-
new-h) (- 0 x)))))))
          (loop :for x :from 0 :to (1- w)
             :do (loop :for y :from 0 :to (1- h)
                    :do (let ((pixel (get-pixel :position (point x y)
                                                      :surface surf)))
                          (draw-pixel (funcall new-x x y)
                                      (funcall new-y x y) :surface new-surf
                                      :color (sdl:sdl_maprgb
(sdl:pixelformat sdl:*default-surface*)
                                                             (color-r pixel)
                                                             (color-g pixel)
                                                             (color-b pixel)))
                          #+nil(draw-point :position (point (funcall new-x x y)
                                                     (funcall new-y x y))
                                      :surface new-surf
                                      :color pixel))))
          new-surf))))

The function works but the pixel access is very slow.  It seems like I
need some way to directly access the surface memory, perhaps with a 2d
byte array?  Maybe this is not possible with CFFI, or maybe the
solution is right under my nose and I'm not seeing it.

Any suggestions?

Thanks,

Anthony


More information about the application-builder mailing list