How can I get image data from QTKit without color or gamma correction in Snow Leopard?
- by Nick Haddad
Since Snow Leopard, QTKit is now returning color corrected image data from functions like QTMovies frameImageAtTime:withAttributes:error:. Given an uncompressed AVI file, the same image data is displayed with larger pixel values in Snow Leopard vs. Leopard.
Currently I'm using frameImageAtTime to get an NSImage, then ask for the tiffRepresentation of that image. After doing this, pixel values are slightly higher in Snow Leopard.
For example, a file with the following pixel value in Leopard:
[0 180 0]
Now has a pixel value like:
[0 192 0]
Is there any way to ask a QTMovie for video frames that are not color corrected? Should I be asking for a CGImageRef, CIImage, or CVPixelBufferRef instead? Is there a way to disable color correction altogether prior to reading in the video files?
I've attempted to work around this issue by drawing into a NSBitmapImageRep with the NSCalibratedColroSpace, but that only gets my part of the way there:
// Create a movie
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys :
nsFileName, QTMovieFileNameAttribute,
[NSNumber numberWithBool:NO], QTMovieOpenAsyncOKAttribute,
[NSNumber numberWithBool:NO], QTMovieLoopsAttribute,
[NSNumber numberWithBool:NO], QTMovieLoopsBackAndForthAttribute,
(id)nil];
_theMovie = [[QTMovie alloc] initWithAttributes:dict error:&error];
// ....
NSMutableDictionary *imageAttributes = [NSMutableDictionary dictionary];
[imageAttributes setObject:QTMovieFrameImageTypeNSImage forKey:QTMovieFrameImageType];
[imageAttributes setObject:[NSArray arrayWithObject:@"NSBitmapImageRep"] forKey: QTMovieFrameImageRepresentationsType];
[imageAttributes setObject:[NSNumber numberWithBool:YES] forKey:QTMovieFrameImageHighQuality];
NSError* err = nil;
NSImage* image = (NSImage*)[_theMovie frameImageAtTime:frameTime withAttributes:imageAttributes error:&err];
// copy NSImage into an NSBitmapImageRep (Objective-C)
NSBitmapImageRep* bitmap = [[image representations] objectAtIndex:0];
// Draw into a colorspace we know about
NSBitmapImageRep *bitmapWhoseFormatIKnow = [[NSBitmapImageRep alloc]
initWithBitmapDataPlanes:NULL
pixelsWide:getWidth()
pixelsHigh:getHeight()
bitsPerSample:8
samplesPerPixel:4
hasAlpha:YES
isPlanar:NO
colorSpaceName:NSCalibratedRGBColorSpace
bitmapFormat:0
bytesPerRow:(getWidth() * 4)
bitsPerPixel:32];
[NSGraphicsContext saveGraphicsState];
[NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithBitmapImageRep:bitmapWhoseFormatIKnow]];
[bitmap draw];
[NSGraphicsContext restoreGraphicsState];
This does convert back to a 'Non color corrected' colorspace, but the color values NOT are exactly the same as what is stored in the Uncompressed AVI files we are testing with. Also this is much less efficient because it is converting from RGB - "Device RGB" - RGB.
Also, I am working in a 64-bit application, so dropping down to the Quicktime-C API is not an option.
Thanks for your help.