iosxcodemacospdfnsimage

How to Convert PDF to NSImage and change the DPI?


I have tried to convert PDF Pages to NSImage and save to JPG files successfully. However the output result is as normal 72 DPI. I want to change the DPI to 300 DPI but failed. Below is the code:

- (IBAction)TestButton:(id)sender {

    NSString* localDocuments = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES) objectAtIndex:0];
    NSString* pdfPath = [localDocuments stringByAppendingPathComponent:@"1.pdf"];

    NSData *pdfData = [NSData dataWithContentsOfFile:pdfPath];
    NSPDFImageRep *pdfImg = [NSPDFImageRep imageRepWithData:pdfData];


    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSInteger pageCount = [pdfImg pageCount];



    for(int i = 0 ; i < pageCount ; i++) {
        [pdfImg setCurrentPage:i];
        NSImage *temp = [[NSImage alloc] init];
        [temp addRepresentation:pdfImg];

        CGFloat factor = 300/72; // Scale from 72 DPI to 300 DPI
        //NSImage *img; // Source image
        NSSize newSize = NSMakeSize(temp.size.width*factor, temp.size.height*factor);
        NSImage *scaledImg = [[NSImage alloc] initWithSize:newSize];
        [scaledImg lockFocus];
        [[NSColor whiteColor] set];
        [NSBezierPath fillRect:NSMakeRect(0, 0, newSize.width, newSize.height)];
        NSAffineTransform *transform = [NSAffineTransform transform];
        [transform scaleBy:factor];
        [transform concat];
        [temp drawAtPoint:NSZeroPoint fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0];
        [scaledImg unlockFocus];


        NSBitmapImageRep *rep = [NSBitmapImageRep imageRepWithData:[temp TIFFRepresentation]];
        NSData *finalData = [rep representationUsingType:NSJPEGFileType properties:nil];
        NSString *pageName = [NSString stringWithFormat:@"Page_%ld.jpg", (long)[pdfImg currentPage]];
        [fileManager createFileAtPath:[NSString stringWithFormat:@"%@%@", pdfPath, pageName] contents:finalData attributes:nil];
    }
}

Solution

  • Since OS X 10.8, NSImage has a block based initialiser to draw vector based content into a bitmap.
    The idea is to provide a drawing handler that is called whenever a representation of the image is requested.
    The relation between points and pixels is expressed by passing a NSSize (in points) to the initialiser and to explicitly set the pixel dimensions for the representation:

    NSString* localDocuments = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES) objectAtIndex:0];
    NSString* pdfPath = [localDocuments stringByAppendingPathComponent:@"1.pdf"];
    NSData* pdfData = [NSData dataWithContentsOfFile:pdfPath];
    NSPDFImageRep* pdfImageRep = [NSPDFImageRep imageRepWithData:pdfData];
    CGFloat factor = 300/72;
    NSInteger pageCount = [pdfImageRep pageCount];
    for(int i = 0 ; i < pageCount ; i++)
    {
        [pdfImageRep setCurrentPage:i];
        NSImage* scaledImage = [NSImage imageWithSize:pdfImageRep.size flipped:NO drawingHandler:^BOOL(NSRect dstRect) {
            [pdfImageRep drawInRect:dstRect];
            return YES;
        }];
        NSImageRep* scaledImageRep = [[scaledImage representations] firstObject];
        /*
         * The sizes of the PDF Image Rep and the [NSImage  imageWithSize: drawingHandler:]-context
         * are defined in terms of points.
         * By explicitly setting the size of the scaled representation in Pixels, you 
         * define the relation between points & pixels.
         */
        scaledImageRep.pixelsWide = pdfImageRep.size.width * factor;
        scaledImageRep.pixelsHigh = pdfImageRep.size.height * factor;
        NSBitmapImageRep* pngImageRep = [NSBitmapImageRep imageRepWithData:[scaledImage TIFFRepresentation]];
        NSData* finalData = [pngImageRep representationUsingType:NSJPEGFileType properties:nil];
        NSString* pageName = [NSString stringWithFormat:@"Page_%ld.jpg", (long)[pdfImageRep currentPage]];
        [[NSFileManager defaultManager] createFileAtPath:[NSString stringWithFormat:@"%@%@", pdfPath, pageName] contents:finalData attributes:nil];
    }