在iPhone中创建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];
}
    

解决方法

请尝试以下方法:
- (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;
} 
    ,迅捷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
}
    ,您可能已经知道有两种渲染PDF的方法: UIWebView 石英渲染 在撰写本文时,其他答案都集中在Quartz上。有许多充分的理由说明这种主要与性能相关的原因,但我认为使用Quartz是值得的。我建议阅读此主题,以更好地了解利弊。 显然这里有一个优秀的基于Quartz的pdf渲染的新颖api ofc,您可以通过UIWebView呈现pdf,并使用石英渲染拇指。 拇指周围还存在一些混淆,对于新的石英pdf魔术师来说,似乎在进行一些搜索后发现有支持拇指的api,但是您应该检查该支持是否仅适用于嵌入式拇指,许多PDF都不会\没有这些。 另一种选择是自己创建拇指(使用石英),网上有很多这样的示例,包括上面的两个答案。但是,如果您的目标是iOS 4或更高版本,我强烈建议您使用块。 (从4开始,图形上下文也是线程安全的)。 生成带有滑块的滑块时,发现性能显着提高。 我过去所做的是: 有一个ViewController 拇指,它的滚动视图 适合所有人的内容大小 您的页面。插入占位符 如果愿意,可以使用ImageViews。 加载文档时,先按一下拇指 后台生成器(请参见代码 下面) 下面的代码调用方法“ 3”,该方法获取页面的索引,从磁盘中获取图像并将其放入滚动视图 如果您确实有动力,可以在拇指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,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);

}
    ,我想出了一个使用
CoreGraphics
和Swift 3.0的解决方案。它的灵感来自于一位亚历山大大帝。我认为我的方法会产生更多的“ Swifty”代码。另外,我的解决方案解决了最终图像的缩放和方向方面的两个问题。 请注意,我的代码使用
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,preserveAspectRatio: true))
    context.drawPDFPage(page)
    context.restoreGState()

    return context.makeImage().flatMap() { UIImage(cgImage: $0,scale: UIScreen.main.scale,orientation: .up) }
}
    ,我只是将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);
    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);
    CGContextConcatCTM(context,CGPDFPageGetDrawingTransform(firstPage,kCGPDFMediaBox,pageRect,true));

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

    var thm:UIImage = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();
    return thm;
}