Frage

This has been driving me mad for months: I have a little app to preview camera raw images. As the files in question can be quite big and stored on a slow network drive I wanted to offer the user a chance to stop the loading of the image.

Handily I found this thread:

Cancel NSData initWithContentsOfURL in NSOperation

and am using Nick's great convenience method to cache the data and be able to issue a cancel request halfway through.

Anyway, once I have the data I use:

NSImage *sourceImage = [[NSImage alloc]initWithData:data];

The problem comes when looking at Nikon .NEF files; sourceImage returns only a thumbnail and not the full size. Displaying Canon .CR2 files and in fact, any other .TIFF's and .JPEG's seems fine and sourceImage is the expected size. I've checked the amount of data that is being loaded (with NSLog and [data length]) and it does seem that all of the Nikon files' 12mb is there for the -initWithData:

If I use

NSImage *sourceImage = [[NSImage alloc]initWithContentsOfURL:myNEFURL];

then I get the full sized image of the Nikon files but of course the app blocks.

So after poking around for what is beginning to feel like my entire life I think I know that the problem is related to the Nikon's metadata stating that the file's DPI is 300 whereas Canon et al is 72.

I hoped a solution would be to lazily access the file with:

NSImage*tempImg = [[NSImage alloc] initByReferencingURL:myNEFURL];

and having seen similar postings here and elsewhere I found a common possible answer of simply

[sourceImage setSize:tempImg.size];

but of course this just resizes the tiny thumbnail up to 3000x2000 or thereabouts.

I've been messing with the following hoping that they would provide a way to get the big picture from the .NEF:

CGImageSourceRef isr = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL);
CGImageRef isrRef = CGImageSourceCreateImageAtIndex(isr, 0, NULL);

and

NSBitmapImageRep *bitMapIR = [[NSBitmapImageRep alloc] initWithData:data];

But checking the sizes on these show similar thumbnail widths and heights. In fact, isrRef returns an even smaller thumbnail, one that is 4.2 times smaller. Perhaps worth noting that 300 / 72 == 4.2, so isrRef is taking account of the DPI on an image where the DPI (possibly) has already been observed.

Please! Can someone [nicely] put me out of my misery and help me get the full-sized image from the loaded data?!?! Currently, I'm special-case'ing the NEF files with a case insensitive search on the file extension and then loading the URL with the blocking methods. I have to take a hit on the app blocking and the search can't be fool-proof in the long run.

As an aside: is this actually a bug in the OS? It does seem like NSImage's -initWithData: and -initWithContentsOfURL: methods use different engines to actually render the image. Would it not be reasonable to have assumed that -initWithURL: simply loads the data which then gets rendered just as though it had been presented to the class with -initWithData: ?

War es hilfreich?

Lösung

It's a bug - confirmed when I did a DTS. Apparently I need to file a bug report. Currently the only way is to use the NSURL methods. Instead of checking the file extension I should probably traverse the meta dictionaries and check the manufacturer's entry for "Nikon", though...

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top