在iphone中创建pdf缩略图

时间:2011-04-14 05:37:28

标签: iphone objective-c pdf

我是Objective-c iPhone编程的新手。我有一个应用程序,我在UIWebView中成功显示PDF,但现在我想创建我的PDF的缩略图。我的PDF存储在我的资源文件夹中。

所以请给我一些代码,说明如何显示我的PDF缩略图。我的代码用于显示PDF是按钮功能:

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

5 个答案:

答案 0 :(得分:24)

尝试以下方法:

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

答案 1 :(得分:3)

Swift 3

(感谢Prine for 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 :(得分:2)

您可能已经了解了两种渲染PDF的方法:

  • UIWebView
  • 石英渲染

撰写本文时的其他答案主要集中在Quartz上。这主要与性能相关有很多很好的理由,但在我看来,使用Quartz是值得的。我建议阅读this thread以更好地了解专业人士和缺点。

对于基于Quartz的pdf渲染here

,显然有一个非常好的新api

ofc你可以通过UIWebView呈现pdf并使用quartz渲染大拇指。

还有一些关于拇指的讨论,对于人们新的石英pdf魔法,似乎在搜索后有支持拇指的api你应该检查是否支持嵌入只有拇指,很多PDF都没有这些。

另一个选择是自己制作拇指(使用石英),网上有很多这样的例子,包括上面的两个答案。但是,如果您的目标是iOS 4或更高版本,我强烈建议您使用块。 (从4开始,图形上下文也是线程安全的。)

当我使用块生成大拇指时,我发现性能显着提高。

我过去所做的是:

  • 为您设置一个ViewController 它有一个滚动视图 适合所有人的内容大小 你的网页。插入占位符 如果你愿意,可以使用ImageViews。

  • 在文档加载时,启动拇指 发生器在后台(见代码 下文)

  • 下面的代码调用方法drawImageView,该方法获取页面的索引,从磁盘中抓取图像并将其放入滚动视图

  • 如果您的感觉真的很有动力,您可以在拇指scrollView上实现渲染范围(只渲染您需要的拇指 - 无论如何您应该为pdf做的事情)

  • 完成后不要忘记删除拇指,除非您要缓存..

#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);

}

-(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); }

答案 3 :(得分:2)

我想出了一个使用CoreGraphics和Swift 3.0的解决方案。它受到了Alexandre的启发。在我看来,我的方法导致更多的“Swifty”#39;码。此外,我的解决方案修复了结果图像缩放和方向的几个问题。

请注意,我的代码使用AVMakeRect(aspectRatio:, insideRect:)并要求导入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) }
}

答案 4 :(得分:1)

我刚刚将Objective-C代码重写为Swift。也许其他人都可以使用它:

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