Workaround for offscreen graphics from Cocoa with accessible pixels and alpha channel
Workaround for offscreen graphics from Cocoa with accessible pixels and alpha channel
- Subject: Workaround for offscreen graphics from Cocoa with accessible pixels and alpha channel
- From: Nicolas Normand <email@hidden>
- Date: Fri, 23 Aug 2002 17:56:18 +0200
Hi all,
recently, I tried drawing into an offscreen bitmap from Cocoa without
success. Reading this list among other ones, I realized other people had
a similar problem.
CoreGraphics offscreen
CG offscreen is straightforward from the sample code given in Apple's
doc (Drawing With Quartz 2D: Using Graphics Contexts: Creating Graphics
Contexts):
- create a bitmap graphics context (CGContextRef) with the sample
CreateBitmapContext function
- draw in it
- play with the bitmap
Cocoa offscreen
From what I read, painting into a NSImage is pretty easy (using [image
lockFocus], [image unlockFocus]). Unfortunately, the image
representation that is created (class NSCachedImageRep) won't let you
get the image data (no bitmapData method). The image can be drawn, but
it seems the pixel data can't be accessed.
Somebody pointed up some procedure to get the data:
- create an offscreen window
- draw in it (you can even put some Core Graphics code in there by
getting the proper context with: [[NSGraphicsContext currentContext]
graphicsPort], this is somewhere in Apple's doc)
- create a bitmap representation from the view with:
-initWithFocusedViewRect: (NSBitmapImageRep)
- get the bitmap data with: -bitmapData.
and you're done except you don't get the alpha channel.
My third try was to create a bitmap NSGraphicsContext. The doc only
mentions PDF and PS representation formats for
graphicsContextWithAttributes: and it doesn't mention creating one from
a bitmap or an existing CGContextRef.
It seems to me that a NSGraphicsContext instance is mostly a wrapper to
a CGContextRef also they are not equivalent. So I tried to subclass
NSGraphicsContext with a proper graphicsPort method returning my bitmap
CGContextRef. Unfortunately again, my subclass instance can't be set as
the current graphics context ([NSGraphicsContext
setCurrentContext:bitmapContext] keeps yelling at me).
Workaround
So, if I can't get it to work cleanly, I'll do it some other way.
Each NSGraphicsContext instance seems to store a CGContextRef in bytes
4-7 (first attribute after the isa class pointer). The workaround is to
set the CG context you want in the current NS context, draw, and set it
back to what it was before (I know it's far from clean code, I'm not
proud of it but it was the only working thing I came up with). Here is a
sample code:
typedef struct {
Class isa;
CGContextRef context;
} *graphicsContextInstance;
void
setCGContextInCurrentNSGraphicsContext (CGContextRef newContext) {
((graphicsContextInstance) [NSGraphicsContext
currentContext])->context = newContext;
}
then:
myOffscreenDrawingMethod {
unsigned char *pixels;
CGContextRef bitmapCGContext;
CGContextRef savedCGContext;
// Create a bitmap quartz context (see Apple's documentation
"Drawing With Quartz 2D")
bitmapCGContext = CreateBitmapContext (contentBounds.size.width,
contentBounds.size.height,
(void *)&pixels);
// Save the quartz context from the current cocoa context
savedCGContext = [[NSGraphicsContext currentContext] graphicsPort];
// Set the bitmap context
setCGContextInCurrentNSGraphicsContext (bitmapCGContext);
// Draw in the bitmap context either from Core Graphics of Cocoa
...
// Restore the old quartz context
setCGContextInCurrentNSGraphicsContext (savedCGContext);
}
This code seems to work fine for me, but I don't know if it won't break
in some circumstances (nested drawing situations ?) and I don't feel
very comfortable about using it. I'm still looking for a clean
documented solution if you have one.
Please share any info.
Nicolas Normand
_______________________________________________
cocoa-dev mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored.