Frage

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];
    }
}
War es hilfreich?

Lösung

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];
}

Andere Tipps

You can set the resolution saved in an image file's metadata by setting the size of the NSImageRep to something other than the image's size

[pngImageRep setSize:NSMakeSize(targetWidth, targetHeight)]

where you have to initialize targetWidth and targetHeight to the values you want

Edit: and I guess you wanted to write "scaledImg" not "temp"

NSBitmapImageRep *rep = [NSBitmapImageRep imageRepWithData:[scaledImg TIFFRepresentation]];

Edit 2: on second thought this will get you a larger image but only as a stretched out version of the smaller one. The approach in weichsel's answer with the modification below is probably what you really want (but the code above is still valid for setting the metadata)

NSSize newSize = NSMakeSize(pdfImageRep.size.width * factor,pdfImageRep.size.height * factor);
NSImage* scaledImage = [NSImage imageWithSize:newSize flipped:NO drawingHandler:^BOOL(NSRect dstRect) {
    [pdfImageRep drawInRect:dstRect];
    return YES;
}];
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top