How can I get image data from QTKit without color or gamma correction in Snow Leopard?
Asked Answered
D

1

8

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.

Dinge answered 12/1, 2010 at 21:25 Comment(1)
What is the destination of the pixels in your bitmap? What kind of colorspace do you get from [bitmap colorspace]?Lasala
L
2

This is what you're running up against: http://support.apple.com/kb/ht3712 Also described here in reference to QT: http://developer.apple.com/library/mac/#technotes/tn2227/_index.html

There is supposed to be an opt-out flag for ColorSync (which is automatic and silent), but because ColorSync goes back to the "Carbon-iferous era" there's a lot of confusion about how to disable it from a 64-bit app. It may even exist, and just have no documentation. But even Adobe has not figured it out AFAIK (64 bit Photoshop for OS X???) [EDIT: Actually, maybe they did with CS5, or found a workaround... so if you have any friends who work there maybe they can be a resource ;) However, I think even their colors may come out different on 64 bit OS X vs Windows or 32 bit].

The first link tells how to force a gamma value of 1.8 system-wide and non-programmatically. Just pointing it out - it probably is only of limited use for your application, but good to know.

The usual way to disable colorsync is/was

GraphicsImportSetFlags( gi, kGraphicsImporterDontUseColorMatching ); 

But I don't know if that's going to work in a 64-bit application (pretty sure it does not). In fact, a lot of things related to ColorSync are more difficult, maybe not yet possible, in 64-bit. Just search "site:apple.com colorsync 64 bit".

If I find something better I'll edit my answer. Just thought this would help you know the enemy, so to speak.

Another edit: (Re)Tagging your videos might mitigate or eliminate this problem too, since ColorSync treats untagged videos a certain way (see links) and operates on them differently depending on the tags. What is the color profile of the videos? Try sRGB maybe?

Lowenstern answered 4/1, 2012 at 19:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.