NSImage vs. CGLayer/CIImage
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