Faster alternative to NSImage draw/composite?

  • I have read through Apple's drawing optimization guide and have been
    searching for a way of speeding these operations up, they are unacceptably
    slow. I have several 72dpi PNG image files (about 1024x768 each) which I
    need to draw repeatedly into a standard NSView subclass over time. I would
    like to avoid using OpenGL directly if possible, it seems like there should
    be a faster way of drawing these other than NSImage's draw or composite
    methods.

    Should I be operating on the imageRep's directly? Will that help? Or does
    NSImages caching make that irrelevant after repeated draw calls?

    I'm assuming there must be a more direct way of drawing the .png's raw
    bitmap data in a faster more efficient way but I can't seem to find the
    proper method of doing this? Any help is *greatly* appreciated. Thank you.
  • --- On Sat, 8/2/08, Matt R <silver529ster...> wrote:

    > I have read through Apple's drawing optimization guide
    > and have been
    > searching for a way of speeding these operations up, they
    > are unacceptably
    > slow. I have several 72dpi PNG image files (about 1024x768
    > each) which I
    > need to draw repeatedly into a standard NSView subclass
    > over time. I would
    > like to avoid using OpenGL directly if possible, it seems
    > like there should
    > be a faster way of drawing these other than NSImage's
    > draw or composite
    > methods.

    You might try a CGLayer. It's designed for fast repeated drawing.

    Cheers,
    Chuck
  • I've been doing exactly this recently, and have had excellent success
    with using CALayers (Core Animation). An NSTimer with a fast repeat
    rate is triggering a method that assigns in one of an array of
    CGImageRef's to the layer's contents property has made for a really
    decent "flipbook" style of animation. I've been able to get 60 frames
    per second without issue.

    I believe you can load up the CGImageRef's from NSImage through
    CGBitmapContext and CGBitmapContextCreateImage. I've been working with
    a *cough* different framework to get the images and display them - one
    that's significantly less powerful than a standard Mac desktop - but
    the throughput has been effectively the same.

    -joe

    On Aug 2, 2008, at 3:01 PM, Charles Steinman wrote:
    > --- On Sat, 8/2/08, Matt R <silver529ster...> wrote:
    >
    >> I have read through Apple's drawing optimization guide
    >> and have been
    >> searching for a way of speeding these operations up, they
    >> are unacceptably
    >> slow. I have several 72dpi PNG image files (about 1024x768
    >> each) which I
    >> need to draw repeatedly into a standard NSView subclass
    >> over time. I would
    >> like to avoid using OpenGL directly if possible, it seems
    >> like there should
    >> be a faster way of drawing these other than NSImage's
    >> draw or composite
    >> methods.
    >
    > You might try a CGLayer. It's designed for fast repeated drawing.
    >
    > Cheers,
    > Chuck
  • Hi Matt,

    If you want to post a test app that shows your performance issue, that
    might help.

    However, no, going under NSImage doesn't make things faster unless
    there's are other issues.

    Certainly before trying OpenGL, try setting the
    setPreferredBackingLocation: for your NSWindow to be
    NSWindowBackingLocationVideoMemory.  If the window backing buffer is
    on the video card, then the Quartz drawing primitives are implemented
    through OpenGL.  That is, if you're really just drawing the same image
    over and over without mutating anything, then your image data should
    be  uploaded to the GPU once and drawn with OpenGL.

    -Ken

    On Sat, Aug 2, 2008 at 1:18 PM, Matt R <silver529ster...> wrote:
    > I have read through Apple's drawing optimization guide and have been
    > searching for a way of speeding these operations up, they are unacceptably
    > slow. I have several 72dpi PNG image files (about 1024x768 each) which I
    > need to draw repeatedly into a standard NSView subclass over time. I would
    > like to avoid using OpenGL directly if possible, it seems like there should
    > be a faster way of drawing these other than NSImage's draw or composite
    > methods.
    >
    > Should I be operating on the imageRep's directly? Will that help? Or does
    > NSImages caching make that irrelevant after repeated draw calls?
    >
    > I'm assuming there must be a more direct way of drawing the .png's raw
    > bitmap data in a faster more efficient way but I can't seem to find the
    > proper method of doing this? Any help is *greatly* appreciated. Thank you.
    >
  • Hi,

    If you have a fixed set of images you're repeatedly flipping through
    you can have CoreAnimation do the animation for you, something like
    this:

          CAKeyframeAnimation *anim;
          NSMutableArray *images;
          CGImageRef im;
          int i;

          images = [NSMutableArray array];
          for (i = 0; i < N; i++) {
         im = create_image (i);
         [images addObject:(id)im];
         CGImageRelease (im);
          }

          anim = [CAKeyframeAnimation animation];
          [anim setKeyPath:@"contents"];
          [anim setValues:images];
          [anim setCalculationMode:@"discrete"];
          [anim setRepeatCount:HUGE_VAL];
          [anim setDuration:1.0];

          [layer addAnimation:anim];

    since this runs completely in the background render thread it has a
    better chance of not dropping frames and should use less CPU than
    doing the same thing from a timer. You'll need to change the duration
    value to match your number of images and desired frame rate,

    John

    On Aug 2, 2008, at 3:13 PM, Joseph Heck wrote:

    > I've been doing exactly this recently, and have had excellent
    > success with using CALayers (Core Animation). An NSTimer with a fast
    > repeat rate is triggering a method that assigns in one of an array
    > of CGImageRef's to the layer's contents property has made for a
    > really decent "flipbook" style of animation. I've been able to get
    > 60 frames per second without issue.
    >
    > I believe you can load up the CGImageRef's from NSImage through
    > CGBitmapContext and CGBitmapContextCreateImage. I've been working
    > with a *cough* different framework to get the images and display
    > them - one that's significantly less powerful than a standard Mac
    > desktop - but the throughput has been effectively the same.
    >
    > -joe
    >
    > On Aug 2, 2008, at 3:01 PM, Charles Steinman wrote:
    >> --- On Sat, 8/2/08, Matt R <silver529ster...> wrote:
    >>
    >>> I have read through Apple's drawing optimization guide
    >>> and have been
    >>> searching for a way of speeding these operations up, they
    >>> are unacceptably
    >>> slow. I have several 72dpi PNG image files (about 1024x768
    >>> each) which I
    >>> need to draw repeatedly into a standard NSView subclass
    >>> over time. I would
    >>> like to avoid using OpenGL directly if possible, it seems
    >>> like there should
    >>> be a faster way of drawing these other than NSImage's
    >>> draw or composite
    >>> methods.
    >>
    >> You might try a CGLayer. It's designed for fast repeated drawing.
    >>
    >> Cheers,
    >> Chuck