Frage Erstellung von PDF Thumbnail in iPhone


Ich bin neu in Objective-c iPhone Programmierung. Ich habe eine Anwendung, in der ich eine PDF in meiner UIWebView erfolgreich anzeigen kann, aber jetzt möchte ich eine Miniaturansicht meiner PDF erstellen. Mein PDF ist in meinem Ressourcenordner gespeichert.

Also bitte geben Sie mir Code, wie ich ein Thumbnail meiner PDF zeigen kann. Mein Code ist für die Anzeige von PDF-Dateien, die in Button-Funktion aufgenommen wurden:

-(void)show:(id)sender {

    pdfView.autoresizesSubviews = NO;
    pdfView.scalesPageToFit=YES;
    pdfView.autoresizingMask=(UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth);
    [pdfView setDelegate:self];

    NSString *path = [[NSBundle mainBundle] pathForResource:@"com" ofType:@"pdf"];
    NSLog(@"Path of res is%@",path);
    NSURL *url = [NSURL fileURLWithPath:path];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    [pdfView loadRequest:request];
}

6
2018-04-14 05:37


Ursprung


Antworten:


versuchen Sie die folgende Methode:

- (UIImage *)imageFromPDFWithDocumentRef:(CGPDFDocumentRef)documentRef {
    CGPDFPageRef pageRef = CGPDFDocumentGetPage(documentRef, 1);
    CGRect pageRect = CGPDFPageGetBoxRect(pageRef, kCGPDFCropBox);

    UIGraphicsBeginImageContext(pageRect.size);
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextTranslateCTM(context, CGRectGetMinX(pageRect),CGRectGetMaxY(pageRect));
    CGContextScaleCTM(context, 1, -1);  
    CGContextTranslateCTM(context, -(pageRect.origin.x), -(pageRect.origin.y));
    CGContextDrawPDFPage(context, pageRef);

    UIImage *finalImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return finalImage;
} 

23
2018-04-14 06:18



Schnell 3 

(Danke an Prine für Swift 2!)

func getPdfThumb(url:NSURL, pageBase1:Int) -> UIImage? {
    guard let document = CGPDFDocument(url as CFURL) else { return nil }
    guard let firstPage = document.page(at: pageBase1) else { return nil }

    let width:CGFloat = 240.0;

    var pageRect:CGRect = firstPage.getBoxRect(.mediaBox)
    let pdfScale:CGFloat = width/pageRect.size.width
    pageRect.size = CGSize(width: pageRect.size.width*pdfScale, height: pageRect.size.height*pdfScale)
    pageRect.origin = CGPoint.zero

    UIGraphicsBeginImageContext(pageRect.size)

    let context:CGContext = UIGraphicsGetCurrentContext()!

    // White background
    context.setFillColor(red: 1.0,green: 1.0,blue: 1.0,alpha: 1.0)
    context.fill(pageRect)

    context.saveGState()

    // Handle rotation
    context.translateBy(x: 0.0, y: pageRect.size.height)
    context.scaleBy(x: 1.0, y: -1.0)
    context.concatenate(firstPage.getDrawingTransform(.mediaBox, rect: pageRect, rotate: 0, preserveAspectRatio: true))

    context.drawPDFPage(firstPage)
    context.restoreGState()

    let image:UIImage = UIGraphicsGetImageFromCurrentImageContext()!

    UIGraphicsEndImageContext()
    return image
}

2
2017-10-04 09:15



Es gibt, wie Sie vielleicht bereits wissen, 2 Möglichkeiten zum Rendern von PDFs:

  • UIWebView
  • Quarz-Wiedergabe

Die anderen Antworten zum Zeitpunkt des Schreibens haben sich auf Quarz konzentriert. Es gibt eine Reihe von guten Gründen für diese meist Performance bezogen, aber meiner Meinung nach mit Quarz ist es wert. Ich würde empfehlen zu lesen Dieser Thread um eine bessere Vorstellung von den Vor- und Nachteilen zu bekommen.

Es gibt anscheinend eine ausgezeichnete newish api für Quarz-basierte PDF-Rendering Hier

Ofc könnten Sie die pdf über UIWebView darstellen und die Daumen mit Quarz rendern.

Es gibt auch ein bisschen Verwirrung um die Daumen, für Leute, die neue Quarz-PDF-Magie, könnte es scheinen, dass nach einigem Suchen gibt es Apis, die Daumen stützen, sollten Sie überprüfen, ob die Unterstützung ist eingebettet Nur Daumen, viele PDFs haben diese nicht.

Eine andere Möglichkeit ist, die Daumen selbst zu erstellen (mit Quarz) und es gibt viele Beispiele dafür im Netz, einschließlich der beiden obigen Antworten. Wenn Sie jedoch auf iOS 4 oder höher abzielen, sollten Sie unbedingt Blöcke verwenden. (Auch Grafikkontexte sind threadsicher seit 4).

Ich habe eine signifikante Leistungssteigerung gefunden, als ich Daumen mit Blöcken erzeugte.

Was ich in der Vergangenheit getan habe, ist:

  • Habe einen ViewController für deine Daumen, es hat einen Scrollview, der hat eine für alle geeignete Inhaltsgröße deine Seiten. Platzhalter einfügen ImageViews ist, wenn Sie möchten.

  • Laden Sie beim Laden der Dokumente einen Daumen ab Generator im Hintergrund (siehe Code unten)

  • Der folgende Code ruft eine Methode auf drawImageView Das nimmt den Index der Seite, ergreift das Bild von der Festplatte und legt es in der Bildlaufansicht ab

  • Wenn dein Gefühl wirklich motiviert ist, kannst du einen Render-Bereich auf der Daumenscrollansicht implementieren (nur die benötigten Thumbnails rendern - was du sowieso für die Pdfs machen solltest)

  • Vergessen Sie nicht, die Daumen zu löschen, wenn Sie fertig sind, es sei denn, Sie möchten zwischenspeichern.

#define THUMB_SIZE 100,144

-(void)generateThumbsWithGCD
{

    thumbQueue = dispatch_queue_create("thumbQueue", 0);//thumbQueue = dispatch_queue_t
    NSFileManager *fm = [NSFileManager defaultManager];
    //good idea to check for previous thumb cache with NSFileManager here   

    CGSize thumbSize = CGSizeMake(THUMB_SIZE);
    __block CGPDFPageRef myPageRef;     

    NSString *reqSysVer = @"4.0";   
    NSString *currSysVer = [[UIDevice currentDevice] systemVersion];    

    //need to handle ios versions < 4
    if ([currSysVer compare:reqSysVer options:NSNumericSearch] == NSOrderedAscending) {NSLog(@"UIKIT MULTITHREADING NOT SUPPORTED!");return;}//thread/api saftey

dispatch_async(thumbQueue, ^{

    for (i=1; i<=_maxPages; i++) {      

        //check if worker is valid (class member bool) for cancelations

        myPageRef=[[PDFDocument sharedPDFDocument]getPageData:i];//pdfdocument is a singleton class     

        if(!myPageRef)return;




            NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

            NSString* imageName = [NSString stringWithFormat:@"%@thumb%i.png",documentName,i];  
            NSString* fullPathToFile =  [thumbDocPath stringByAppendingPathComponent:imageName];

            if(![fm fileExistsAtPath:fullPathToFile]){
                //NSLog(@"Not there");
                UIGraphicsBeginImageContext(thumbSize);//thread Safe in iOs4
                CGContextRef context = UIGraphicsGetCurrentContext();//thread Safe in iOs4          
                CGContextTranslateCTM(context, 0, 144);
                CGContextScaleCTM(context, 0.15, -0.15);
                CGContextDrawPDFPage (context, myPageRef);
                UIImage * render = UIGraphicsGetImageFromCurrentImageContext();                     
                UIGraphicsEndImageContext();        
                NSData* imageData= UIImagePNGRepresentation(render);

                if(imageData){
                    NSLog(@"WROTE TO:%@",fullPathToFile);
                    if(![imageData writeToFile:fullPathToFile atomically:NO])NSLog(@"ERROR: Thumb Didnt Save"); //COMMENT OUT TO DISABLE WRITE                  
                }               
            }
            else NSLog(@"Allready There! %@",fullPathToFile);
                    //update progress on thumb viewController if you wish here
            [pool release];
            dispatch_sync(dispatch_get_main_queue(), ^{
            [self drawImageView:i];
        });

    }   
    });
    dispatch_release(thumbQueue);

}


1
2018-04-14 08:16



Ich habe den Objective-C-Code einfach in Swift umgeschrieben. Vielleicht kann es jemand anderes benutzen:

func getThumbnail(url:NSURL, pageNumber:Int) -> UIImage {

    var pdf:CGPDFDocumentRef = CGPDFDocumentCreateWithURL(url as CFURLRef);

    var firstPage = CGPDFDocumentGetPage(pdf, pageNumber)

    var width:CGFloat = 240.0;

    var pageRect:CGRect = CGPDFPageGetBoxRect(firstPage, kCGPDFMediaBox);
    var pdfScale:CGFloat = width/pageRect.size.width;
    pageRect.size = CGSizeMake(pageRect.size.width*pdfScale, pageRect.size.height*pdfScale);
    pageRect.origin = CGPointZero;

    UIGraphicsBeginImageContext(pageRect.size);

    var context:CGContextRef = UIGraphicsGetCurrentContext();

    // White BG
    CGContextSetRGBFillColor(context, 1.0,1.0,1.0,1.0);
    CGContextFillRect(context,pageRect);

    CGContextSaveGState(context);

    // ***********
    // Next 3 lines makes the rotations so that the page look in the right direction
    // ***********
    CGContextTranslateCTM(context, 0.0, pageRect.size.height);
    CGContextScaleCTM(context, 1.0, -1.0);
    CGContextConcatCTM(context, CGPDFPageGetDrawingTransform(firstPage, kCGPDFMediaBox, pageRect, 0, true));

    CGContextDrawPDFPage(context, firstPage);
    CGContextRestoreGState(context);

    var thm:UIImage = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();
    return thm;
}

1
2018-04-30 15:17



Ich habe eine Lösung, die verwendet CoreGraphics und Swift 3.0. Es ist sehr inspiriert von dem hier vorgestellten Alexandre. Meiner Meinung nach führt mein Ansatz zu mehr Swifty-Code. Außerdem behebt meine Lösung ein paar Probleme mit der Skalierung und Ausrichtung des resultierenden Bildes.

Beachten Sie, dass mein Code verwendet AVMakeRect(aspectRatio:, insideRect:) und erfordert den Import von AVFoundation.

//pages numbering starts from 1.
func generate(size: CGSize, page: Int) -> UIImage? {
    guard let document = CGPDFDocument(url as CFURL), let page = document.page(at: page) else { return nil }

    let originalPageRect: CGRect = page.getBoxRect(.mediaBox)
    var targetPageRect = AVMakeRect(aspectRatio: originalPageRect.size, insideRect: CGRect(origin: CGPoint.zero, size: size))
    targetPageRect.origin = CGPoint.zero

    UIGraphicsBeginImageContextWithOptions(targetPageRect.size, true, 0)
    defer { UIGraphicsEndImageContext() }
    guard let context = UIGraphicsGetCurrentContext() else { return nil }

    context.setFillColor(gray: 1.0, alpha: 1.0)
    context.fill(targetPageRect)

    context.saveGState()
    context.translateBy(x: 0.0, y: targetPageRect.height)
    context.scaleBy(x: 1.0, y: -1.0)
    context.concatenate(page.getDrawingTransform(.mediaBox, rect: targetPageRect, rotate: 0, preserveAspectRatio: true))
    context.drawPDFPage(page)
    context.restoreGState()

    return context.makeImage().flatMap() { UIImage(cgImage: $0, scale: UIScreen.main.scale, orientation: .up) }
}

0
2017-11-14 12:06