NSImage/BitmapRep/format conversions in a WO4.5 application
NSImage/BitmapRep/format conversions in a WO4.5 application
- Subject: NSImage/BitmapRep/format conversions in a WO4.5 application
- From: Ondra Cada <email@hidden>
- Date: Tue, 18 Sep 2001 15:23:40 +0200
Hello,
(sorry I am crossposting this to Cocoa as well, but it seems the problem
spans WO and AppKit both. In Cocoa list please note the question is actually
related to the pre-Cocoa YB.)
I am developing a WO application in Mac OS X Server 1, using WO4.5. The
application needs to render and convert images, so NSView, NSImage, and
NSImageRep seem to be quite indicated.
Well, I've found that NSView can't be rendered without an NSWindow ('tis
strange, IMHO!), and that NSWindows can't be used without an NSApplication. I
also have found that NSApplication, if created in the main thread, would
sometimes (again quite strangely) interfere with WOApplicaiton (or whatever),
crashing the WO application by an irregular way.
That all is solved, and my current code is based on the following pattern (I
know the volatile variables are crap and I should use locks instead; they
are a remnant of legacy code, and they'll be trashed as soon as other things
work):
static volatile NSData *_data;
static volatile id _preview=nil;
@implementation ApplicationServerThread
// this is called from [WOApplication init] to start the thread:
+(void)initializeWithApplication:application {
[NSThread detachNewThreadSelector:@selector(applicationServerThread:)
toTarget:self withObject:application];
}
// this is called from anywhere to render the image
+(NSData*)convertForPreview:input {
_data=nil;
_preview=input; // this triggers the thread
while (_data==nil) [NSThread sleepUntilDate:[NSDate
dateWithTimeIntervalSinceNow:0.01]];
return [(NSData*)_data autorelease];
}
// this is the thread code (simplified, eg. without autoreleasepools)
+(void)applicationServerThread:application {
[NSApplication sharedApplication]; // makes the object needed for
AppKit's services
for (;;) {
while (!_preview) [NSThread sleepUntilDate:[NSDate
dateWithTimeIntervalSinceNow:0.01]];
NSView *view=[OCSCardView viewWithInput:_preview]; // the view
renders the image
_preview=nil;
[[[[NSWindow alloc] initWithContentRect:[view frame]
styleMask:NSBorderlessWindowMask backing:NSBackingStoreNonretained defer:NO]
autorelease] setContentView:view]; // without this, the view refuses to
render itself?!?!? Strange!
_data=[[[[[NSImage alloc] initWith
Data:[view
dataWithEPSInsideRect:[view frame]]] autorelease] TIFFRepresentation]
retain];
}
}
@end
Well, _this_ works quite well, without any problem.
Now comes the tricky part: instead of TIFF _data I would need a GIF or a
PNG. Well, so I tried the standard way of making a NSBitmapImageRep of the
TIFFRepresentation, but in vain -- it does not work -- the data are silently
not made!
Finally, I've added some logs, and now the thing looks this way:
...
const char *names[]={"TIFF","BMP","GIF","JPEG","PNG"};
NSLog(@"image -> %@",o); // o initialized by the [view
dataWithEPSInsideRect:] above
o=[o TIFFRepresentation];
NSLog(@"TIFF -> %d bytes",[o length]);
o=[NSBitmapImageRep imageRepWithData:o];
NSLog(@"rep -> %@",o);
for (i=NSGIFFileType;i<=NSPNGFileType;i++) {
o=[o representationUsingType:i properties:nil];
NSLog(@"%s -> %d bytes",names[i],[o length]);
}
...
The result is quite plain:
...
Sep 18 15:01:13 Visitky[14045] Opening application's URL in Browser:
http://localhost:1256/cgi-bin/WebObjects/Visitky
Sep 18 15:01:13 Visitky[14045] Waiting for requests...
Sep 18 15:01:16 Visitky[14045] Sending lifebeat to port 1085
Sep 18 15:01:18 Visitky[14045] image -> NSImage 0x6b700 Size={600, 375} Reps=(
NSEPSImageRep 0x1c0fe0 Size={600, 375}
ColorSpace=NSCalibratedRGBColorSpace BPS=0 Pixels=0x0 Alpha=NO
)
Sep 18 15:01:18 Visitky[14045] TIFF -> 450202 bytes
Sep 18 15:01:18 Visitky[14045] rep -> NSBitmapImageRep 0x5154e0 Size={600,
375} ColorSpace=NSCalibratedWhiteColorSpace BPS=8 Pixels=600x375 Alpha=YES
Sep 18 15:01:18 Visitky[14045] GIF -> 0 bytes
Sep 18 15:01:18 Visitky[14045] JPEG -> 0 bytes
Sep 18 15:01:18 Visitky[14045] PNG -> 0 bytes
Oops. The representationUsingType:properties: method just keeps returning nil.
Anybody have any idea? Short of making an external tool run by NSTask to
convert images (which I would like to dispense with, since it would bring
problems with shared code -- eg. the OCSCardView uses a number of
Application/Session services to access the data represented by "input") I'm
out of them...
Well I guess if the worst comes to the worst, I could save the TIFF to
/tmp/xxx.tiff, use NSTask to run an external tool to convert it to
/tmp/xxx.gif, and read the result in using dataWithContentsOfFile:, but would
not it be kinda clumsy? :(
---
Ondra Cada
OCSoftware: email@hidden
http://www.ocs.cz
private email@hidden
http://www.ocs.cz/oc