Lisp HUG Maillist Archive

Draw images efficiently

Hi,

I’m using an image as a background for an output-pane, and in order to fill the entire pane, I’ve been using a naïve tile approach:

(loop for nx from 0 below (ceiling width image-width) do
      (loop for ny from 0 below (ceiling height image-height) do
            (gp:draw-image port image (+ x (* nx image-width)) (+ y (* ny image-height))))

However, this is pretty slow. I tried experimenting with various image sizes, but drawing a bigger image fewer times seems to take about the same time as drawing a smaller image more times. That suggests the cost of drawing images is (to some extent) proportional to the amount of data being drawn.

Is there any way to optimize image drawing in CAPI?

Erik



_______________________________________________
Lisp Hug - the mailing list for LispWorks users
lisp-hug@lispworks.com
http://www.lispworks.com/support/lisp-hug.html

Re: Draw images efficiently

Answering myself:

While I haven’t found a general solution for this, I did find a way to to this on OS X that I would like to share:


(defmethod nsview ((pane capi:simple-pane))
  (slot-value (slot-value pane 'capi-internals:representation) 'capi-cocoa-library::main-view))

(defun cocoa-set-background (pane image)
  (let* ((view (nsview pane))
         (image (gp:load-image pane image))
         (nsimage (slot-value (slot-value image 'gp::representation) 'gp::image)))
    (objc:invoke view "setWantsLayer:" 1)  ; enable backing layer
    (objc:invoke (objc:invoke view "layer") "setBackgroundColor:" (objc:invoke (objc:invoke "NSColor" "colorWithPatternImage:" nsimage) "CGColor"))))

(setf *pane* (capi:contain (make-instance 'capi:output-pane :background :transparent :display-callback
                                          (lambda (port x y w h)
                                            (gp:draw-rectangle port 10 10 50 50 :filled t :foreground :green)))))

(capi:apply-in-pane-process *pane* 'cocoa-set-background *pane* 'some-image)


This enables a backing layer for the output-pane, that ”shines through” if the background of the pane is set to :transparent.

So far I haven’t yet checked out whether the NSImage needs to be retained, or if the code leeks memory. But it seems to work well at least on my Mac with OS X 10.11.

Erik





> 11 dec. 2017 kl. 10:53 skrev Erik Ronström <erik.ronstrom@doremir.com>:
> 
> Hi,
> 
> I’m using an image as a background for an output-pane, and in order to fill the entire pane, I’ve been using a naïve tile approach:
> 
> (loop for nx from 0 below (ceiling width image-width) do
>      (loop for ny from 0 below (ceiling height image-height) do
>            (gp:draw-image port image (+ x (* nx image-width)) (+ y (* ny image-height))))
> 
> However, this is pretty slow. I tried experimenting with various image sizes, but drawing a bigger image fewer times seems to take about the same time as drawing a smaller image more times. That suggests the cost of drawing images is (to some extent) proportional to the amount of data being drawn.
> 
> Is there any way to optimize image drawing in CAPI?
> 
> Erik
> 
> 


_______________________________________________
Lisp Hug - the mailing list for LispWorks users
lisp-hug@lispworks.com
http://www.lispworks.com/support/lisp-hug.html

Updated at: 2020-12-10 08:30 UTC