• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
NSImage vs. CGLayer/CIImage
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

NSImage vs. CGLayer/CIImage


  • Subject: NSImage vs. CGLayer/CIImage
  • From: Manfred Schwind <email@hidden>
  • Date: Tue, 6 Nov 2007 22:30:14 +0100

I'm about to write an easy-to-use but fast little Offscreen class.
The interface for that class is very simply, something like that:

@interface Offscreen : NSObject {
}
- (id)initWithSize:(NSSize)size;
- (void)lockFocus;
- (void)unlockFocus;
- (void)drawInRect:(NSRect)rect operation:(NSCompositingOperation) operation fraction:(float)fraction;
@end


So you can lock the focus into the offscreen to draw something into it and you can draw the offscreen somewhere.
Simple.


I wrote a little test that created such an Offscreen, draws something in it and then draws the offscreen 100 times in the current context (the whole test is done in the drawRect routine of an NSView).

Now I tried two different implementations:

1.) Just using an NSImage. Easy.

2.) Using CGLayerRef and CIImage.

The result is very interesting: NSImage is much faster than CGLayerRef and CIImage. Drawing the same image 100 times takes about 0.25 Seconds when using CGLayerRef/CIImage, but when using NSImage it takes less than 0.01 Seconds. OK, drawing the first image in the CGLayerRef/CIImage method takes longer, but even if I begin the time measurement starting at the second draw call, it still takes 0.1 Seconds. So NSImage is around 10 times faster than CGLayerRef/CIImage.
(Note: currently only tested on 10.4, time is measured with the Microseconds Carbon call to get wall time. Of course the CGLayerRef and the CIImage is just created _once_ and re-used for every drawing call - see also the code below.)


Then I tried to eliminate the use of the CIImage and directly draw the CGLayerRef with CGContextDrawLayerInRect. In this case it's approximately at the same speed as the NSImage solution. But I can not use the operation-Paramater so effectively it's always drawing in NSCompositeSourceOver mode. The NSImage method is very very fast in all operation modes.

Has anybody an idea why the use of CIImage to draw is so slow? How does NSImage do its magic? Are there other ways to draw CGLayerRef or CIImage that support the various compositing operations and alpha?

If you're interested, here are the relevant parts of the implementation (left out dealloc etc.):

1.) NSImage method (image is of kind NSImage):

- (void)lockFocus
{
	[image lockFocus];
}

- (void)unlockFocus
{
	[image unlockFocus];
}

- (void)drawInRect:(NSRect)rect operation:(NSCompositingOperation) operation fraction:(float)fraction
{
[image drawInRect:rect fromRect:NSMakeRect(0.0f, 0.0f, size.width, size.height) operation:operation fraction:fraction];
}


2.) GCLayerRef/CIImage method (image is of kind CIImage):

- (id)initWithSize:(NSSize)theSize
{
if ((self = [super initWithSize:theSize]) != nil) {
layer = CGLayerCreateWithContext([[NSGraphicsContext currentContext] graphicsPort], *(CGSize *)&size, NULL);
layerContext = [[NSGraphicsContext graphicsContextWithGraphicsPort:CGLayerGetContext(layer) flipped:NO] retain];
}
return self;
}


- (void)lockFocus
{
	[image release];
	image = nil;
	oldContext = [NSGraphicsContext currentContext];
	[NSGraphicsContext setCurrentContext:layerContext];
}

- (void)unlockFocus
{
	[NSGraphicsContext setCurrentContext:oldContext];
}

- (void)drawInRect:(NSRect)rect operation:(NSCompositingOperation) operation fraction:(float)fraction
{
if (operation == NSCompositeSourceOver) {
// fast
CGContextDrawLayerInRect([[NSGraphicsContext currentContext] graphicsPort], *(CGRect *)&rect, layer);
} else {
// sloooooow!
if (!image) {
image = [[CIImage alloc] initWithCGLayer:layer];
}
[image drawInRect:rect fromRect:NSMakeRect(0.0f, 0.0f, size.width, size.height) operation:operation fraction:fraction];
}
}


Thanks for any ideas/comments,
Mani
--
http://www.mani.de
iVolume - Loudness adjustment for iTunes.
LittleSecrets - The encrypted notepad.


_______________________________________________

Cocoa-dev mailing list (email@hidden)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden


  • Follow-Ups:
    • Re: NSImage vs. CGLayer/CIImage
      • From: Volker Runkel <email@hidden>
  • Prev by Date: CGLContextObj -> NSOpenGLContext?
  • Next by Date: NSBrowser tooltips (Tiger and Leopard)
  • Previous by thread: CGLContextObj -> NSOpenGLContext?
  • Next by thread: Re: NSImage vs. CGLayer/CIImage
  • Index(es):
    • Date
    • Thread