views:

77

answers:

3

Hello, I am trying to convert an NSImage to a CIImage. When I do this, there seems to be a huge loss in image quality. I think it is because of the "TIFFRepresentation". Does anyone have a better method? Thanks a lot.

NSImage *image = [[NSImage alloc] initWithData:[someSource dataRepresentation]];

NSData  * tiffData = [image TIFFRepresentation];
CIImage *backgroundCIImage = [[CIImage alloc] initWithData:tiffData];

CIContext *ciContext = [[NSGraphicsContext currentContext] CIContext];  
[ciContext drawImage:backgroundCIImage atPoint:CGPointZero fromRect:someRect];
A: 

Try replacing the line

NSData  * tiffData = [image TIFFRepresentation];

with

NSData  * tiffData = [image TIFFRepresentationUsingCompression: NSTIFFCompressionNone factor: 0.0f];

because the documentation states that TIFFRepresentation uses the TIFF compression option associated with each image representation, which might not be NSTIFFCompressionNone. Thus, you should be explicit about wanting the tiffData uncompressed.

Jon Rodriguez
I tried that and got the same result as before (degraded quality).
David
A: 

Your problem is indeed converting to TIFF. PDF is a vector format, while TIFF is bitmap, so a TIFF will look blurry at larger sizes.

Your best bet is probably to get a CGImage from the NSImage and create the CIImage from that. Either that or just create the CIImage from the original data.

Chuck
CGImages and CIImages are rasters, too. The questioner cannot perform this task without converting to a raster image, since the destination he wants is a raster image. (That said, going through CGImage instead of a TIFF representation probably is the correct solution, for performance reasons if nothing else.)
Peter Hosey
A: 

I finally solved the problem. Basically, I render the pdf document two times its normal resolution offscreen and then capture the image displayed by the view. For a more detailed image, just increase the scaling factor. Please see the code below for the proof of concept. I didn't show the CIImage but once you get the bitmap, just use the CIImage method to create the CIImage from the bitmap.

    NSImage *pdfImage = [[NSImage alloc] initWithData:[[aPDFView activePage] dataRepresentation]];
    NSSize size = [pdfImage size];
    NSRect imageRect = NSMakeRect(0, 0, size.width, size.height);
    imageRect.size.width *= 2; //Twice the scale factor
    imageRect.size.height *= 2; //Twice the scale factor

    PDFDocument *pageDocument = [[[PDFDocument alloc] init] autorelease];
    [pageDocument insertPage:[aPDFView activePage] atIndex:0];

    PDFView *pageView = [[[PDFView alloc] init] autorelease];
    [pageView setDocument:pageDocument];
    [pageView setAutoScales:YES];

    NSWindow *offscreenWindow = [[NSWindow alloc] initWithContentRect:imageRect 
                                                            styleMask:NSBorderlessWindowMask
                                                              backing:NSBackingStoreRetained
                                                                defer:NO];

    [offscreenWindow setContentView:pageView];
    [offscreenWindow display];
    [[offscreenWindow contentView] display]; // Draw to the backing buffer

    // Create the NSBitmapImageRep
    [[offscreenWindow contentView] lockFocus];

    NSBitmapImageRep* rep = [[NSBitmapImageRep alloc] initWithFocusedViewRect:imageRect];

    // Clean up and delete the window, which is no longer needed.
    [[offscreenWindow contentView] unlockFocus];

    [compositeImage TIFFRepresentation]];
    NSData *imageData = [rep representationUsingType: NSJPEGFileType properties: nil];
    [imageData writeToFile:@"/Users/David/Desktop/out.jpg" atomically: YES];

    [offscreenWindow release];
David