2012-06-06 21 views

Respuesta

6

El siguiente método creará una miniatura desde un archivo PDF. Es compatible con RetinaDisplay, por lo que las miniaturas deberían ser especialmente nítidas en dichos dispositivos.

- (UIImage *)buildThumbnailImage 
{ 
    BOOL hasRetinaDisplay = FALSE; // by default 
    CGFloat pixelsPerPoint = 1.0; // by default (pixelsPerPoint is just the "scale" property of the screen) 

    if ([UIScreen instancesRespondToSelector:@selector(scale)]) // the "scale" property is only present in iOS 4.0 and later 
    { 
    // we are running iOS 4.0 or later, so we may be on a Retina display; we need to check further... 
    if ((pixelsPerPoint = [[UIScreen mainScreen] scale]) == 1.0) 
     hasRetinaDisplay = FALSE; 
    else 
     hasRetinaDisplay = TRUE; 
    } 
    else 
    { 
    // we are NOT running iOS 4.0 or later, so we can be sure that we are NOT on a Retina display 
    pixelsPerPoint = 1.0; 
    hasRetinaDisplay = FALSE; 
    } 

    size_t imageWidth = 320; // width of thumbnail in points 
    size_t imageHeight = 460; // height of thumbnail in points 

    if (hasRetinaDisplay) 
    { 
    imageWidth *= pixelsPerPoint; 
    imageHeight *= pixelsPerPoint; 
    } 

    size_t bytesPerPixel = 4; // RGBA 
    size_t bitsPerComponent = 8; 
    size_t bytesPerRow = bytesPerPixel * imageWidth; 

    void *bitmapData = malloc(imageWidth * imageHeight * bytesPerPixel); 

    // in the event that we were unable to mallocate the heap memory for the bitmap, 
    // we just abort and preemptively return nil: 
    if (bitmapData == NULL) 
    return nil; 

    // remember to zero the buffer before handing it off to the bitmap context: 
    bzero(bitmapData, imageWidth * imageHeight * bytesPerPixel); 

    CGContextRef theContext = CGBitmapContextCreate(bitmapData, imageWidth, imageHeight, bitsPerComponent, bytesPerRow, 
                CGColorSpaceCreateDeviceRGB(), kCGImageAlphaPremultipliedLast); 

    CGPDFDocumentRef pdfDocument = MyGetPDFDocumentRef(); // NOTE: you will need to modify this line to supply the CGPDFDocumentRef for your file here... 
    CGPDFPageRef pdfPage = CGPDFDocumentGetPage(pdfDocument, 1); // get the first page for your thumbnail 

    CGAffineTransform shrinkingTransform = 
    CGPDFPageGetDrawingTransform(pdfPage, kCGPDFMediaBox, CGRectMake(0, 0, imageWidth, imageHeight), 0, YES); 

    CGContextConcatCTM(theContext, shrinkingTransform); 

    CGContextDrawPDFPage(theContext, pdfPage); // draw the pdfPage into the bitmap context 
    CGPDFDocumentRelease(pdfDocument); 

    // 
    // create the CGImageRef (and thence the UIImage) from the context (with its bitmap of the pdf page): 
    // 
    CGImageRef theCGImageRef = CGBitmapContextCreateImage(theContext); 
    free(CGBitmapContextGetData(theContext)); // this frees the bitmapData we malloc'ed earlier 
    CGContextRelease(theContext); 

    UIImage *theUIImage; 

    // CAUTION: the method imageWithCGImage:scale:orientation: only exists on iOS 4.0 or later!!! 
    if ([UIImage respondsToSelector:@selector(imageWithCGImage:scale:orientation:)]) 
    { 
    theUIImage = [UIImage imageWithCGImage:theCGImageRef scale:pixelsPerPoint orientation:UIImageOrientationUp]; 
    } 
    else 
    { 
    theUIImage = [UIImage imageWithCGImage:theCGImageRef]; 
    } 

    CFRelease(theCGImageRef); 
    return theUIImage; 
} 

Usted tendrá que suministrar una CGPDFDocumentRef correspondiente a su archivo PDF, algo así como lo siguiente. (Esto se supone que existe el archivo en test.pdf haz principal de la aplicación.)

CGPDFDocumentRef MyGetPDFDocumentRef() 
{ 
    NSString *inputPDFFile = [[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:@"test.pdf"]; 
    const char *inputPDFFileAsCString = [inputPDFFile cStringUsingEncoding:NSASCIIStringEncoding]; 
    //NSLog(@"expecting pdf file to exist at this pathname: \"%s\"", inputPDFFileAsCString); 

    CFStringRef path = CFStringCreateWithCString(NULL, inputPDFFileAsCString, kCFStringEncodingUTF8); 

    CFURLRef url = CFURLCreateWithFileSystemPath(NULL, path, kCFURLPOSIXPathStyle, 0); 
    CFRelease (path); 

    CGPDFDocumentRef document = CGPDFDocumentCreateWithURL(url); 
    CFRelease(url); 

    if (CGPDFDocumentGetNumberOfPages(document) == 0) 
    { 
    printf("Warning: No pages in pdf file \"%s\" or pdf file does not exist at this path\n", inputPDFFileAsCString); 
    return NULL; 
    } 

    return document; 
} 

Por último, se puede visualizar la imagen en miniatura en una UIImageView, así:

UIImageView *thumbnailImageView = [[UIImageView alloc] initWithImage:[self buildThumbnailImage]]; 

    [self.view addSubview:thumbnailImageView]; 
+0

Gracias a todos! ¡Lo intentaré lo más pronto posible! ¡La primera vez que uso stackoverflow, es simplemente increíble! – iconso

6

Como parte de un proyecto en el que estaba trabajando, modifiqué el código de Inwit para usarlo con variables en sus llamadas. Me imaginé que iba a publicar aquí para ayudar a cualquier persona que estaba buscando una solución similar:

llamarlos:

//Assume all your PDFs you want to create thumbnails for are in an array. This method saves the paths to all PDFs in your main bundle as NSStrings. 
_pdfs = [[NSBundle mainBundle] pathsForResourcesOfType:@"pdf" inDirectory:nil]; 

//To be called in the cellForItemAtIndexPath method or a similar method where you want to create a thumbnail for the image: 
NSString *loc = [_pdfs objectAtIndex:indexPath.row];  
UIImage *cellImage = [self buildThumbnailImage:MyGetPDFDocumentRef(loc)]; 

El método y la función C:

- (UIImage *)buildThumbnailImage:(CGPDFDocumentRef)pdfDocument 
{ 
    BOOL hasRetinaDisplay = FALSE; // by default 
    CGFloat pixelsPerPoint = 1.0; // by default (pixelsPerPoint is just the "scale" property of the screen) 

    if ([UIScreen instancesRespondToSelector:@selector(scale)]) // the "scale" property is only present in iOS 4.0 and later 
    { 
     // we are running iOS 4.0 or later, so we may be on a Retina display; we need to check further... 
     if ((pixelsPerPoint = [[UIScreen mainScreen] scale]) == 1.0) 
      hasRetinaDisplay = FALSE; 
     else 
      hasRetinaDisplay = TRUE; 
    } 
    else 
    { 
     // we are NOT running iOS 4.0 or later, so we can be sure that we are NOT on a Retina display 
     pixelsPerPoint = 1.0; 
     hasRetinaDisplay = FALSE; 
    } 

    size_t imageWidth = 320; // width of thumbnail in points 
    size_t imageHeight = 460; // height of thumbnail in points 

    if (hasRetinaDisplay) 
    { 
     imageWidth *= pixelsPerPoint; 
     imageHeight *= pixelsPerPoint; 
    } 

    size_t bytesPerPixel = 4; // RGBA 
    size_t bitsPerComponent = 8; 
    size_t bytesPerRow = bytesPerPixel * imageWidth; 

    void *bitmapData = malloc(imageWidth * imageHeight * bytesPerPixel); 

    // in the event that we were unable to mallocate the heap memory for the bitmap, 
    // we just abort and preemptively return nil: 
    if (bitmapData == NULL) 
     return nil; 

    // remember to zero the buffer before handing it off to the bitmap context: 
    bzero(bitmapData, imageWidth * imageHeight * bytesPerPixel); 

    CGContextRef theContext = CGBitmapContextCreate(bitmapData, imageWidth, imageHeight, bitsPerComponent, bytesPerRow, 
                CGColorSpaceCreateDeviceRGB(), kCGImageAlphaPremultipliedLast); 

    //CGPDFDocumentRef pdfDocument = MyGetPDFDocumentRef(); // NOTE: you will need to modify this line to supply the CGPDFDocumentRef for your file here... 
    CGPDFPageRef pdfPage = CGPDFDocumentGetPage(pdfDocument, 1); // get the first page for your thumbnail 

    CGAffineTransform shrinkingTransform = 
    CGPDFPageGetDrawingTransform(pdfPage, kCGPDFMediaBox, CGRectMake(0, 0, imageWidth, imageHeight), 0, YES); 

    CGContextConcatCTM(theContext, shrinkingTransform); 

    CGContextDrawPDFPage(theContext, pdfPage); // draw the pdfPage into the bitmap context 
    CGPDFDocumentRelease(pdfDocument); 

    // 
    // create the CGImageRef (and thence the UIImage) from the context (with its bitmap of the pdf page): 
    // 
    CGImageRef theCGImageRef = CGBitmapContextCreateImage(theContext); 
    free(CGBitmapContextGetData(theContext)); // this frees the bitmapData we malloc'ed earlier 
    CGContextRelease(theContext); 

    UIImage *theUIImage; 

    // CAUTION: the method imageWithCGImage:scale:orientation: only exists on iOS 4.0 or later!!! 
    if ([UIImage respondsToSelector:@selector(imageWithCGImage:scale:orientation:)]) 
    { 
     theUIImage = [UIImage imageWithCGImage:theCGImageRef scale:pixelsPerPoint orientation:UIImageOrientationUp]; 
    } 
    else 
    { 
     theUIImage = [UIImage imageWithCGImage:theCGImageRef]; 
    } 

    CFRelease(theCGImageRef); 
    return theUIImage; 
} 


CGPDFDocumentRef MyGetPDFDocumentRef(NSString *inputPDFFile) 
{ 
    //NSString *inputPDFFile = [[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:@"test.pdf"]; 

    const char *inputPDFFileAsCString = [inputPDFFile cStringUsingEncoding:NSASCIIStringEncoding]; 
    //NSLog(@"expecting pdf file to exist at this pathname: \"%s\"", inputPDFFileAsCString); 

    CFStringRef path = CFStringCreateWithCString(NULL, inputPDFFileAsCString, kCFStringEncodingUTF8); 

    CFURLRef url = CFURLCreateWithFileSystemPath(NULL, path, kCFURLPOSIXPathStyle, 0); 
    CFRelease (path); 

    CGPDFDocumentRef document = CGPDFDocumentCreateWithURL(url); 
    CFRelease(url); 

    if (CGPDFDocumentGetNumberOfPages(document) == 0) 
    { 
     printf("Warning: No pages in pdf file \"%s\" or pdf file does not exist at this path\n", inputPDFFileAsCString); 
     return NULL; 
    } 

    return document; 
} 
+0

¿Podemos obtener la primera instantánea de archivo para doc, Xls, CSV, etc. podemos obtener esos – kiri

+0

La vista previa en PDF en el código anterior se representa utilizando Core Graphics para representar la primera página del PDF (https://developer.apple. com/library/mac/documentation/GraphicsImaging/Reference/CGPDFPage /). Core Graphics no ofrece una característica similar para representar tipos de documentos de oficina, por lo que para implementar vistas previas de documentos deberá implementar su propio código de representación para crear vistas previas. Este método no se puede modificar fácilmente para su propósito. – jonschneider

Cuestiones relacionadas