如何以编程方式生成iOS的PDF缩略图?

时间:2010-11-05 16:22:35

标签: ios objective-c pdf cocoa-touch

我们目前正在使用UIWebViews显示PDF内容。理想情况下,我希望能够在UITableView中显示缩略图,而不会同时加载许多不同的UIWebViews ...它们加载一个文档的速度足够慢 - 不要介意10 +!

我该怎么做?

我已经考虑使用UIDocumentInteractionControllerUIWebView来捕获加载文档的屏幕,但这意味着在显示表格之前必须将它们全部缩略图。

4 个答案:

答案 0 :(得分:13)

以下是考虑转换的示例代码。 :)

NSURL* pdfFileUrl = [NSURL fileURLWithPath:finalPath];
CGPDFDocumentRef pdf = CGPDFDocumentCreateWithURL((CFURLRef)pdfFileUrl);
CGPDFPageRef page;

CGRect aRect = CGRectMake(0, 0, 70, 100); // thumbnail size
UIGraphicsBeginImageContext(aRect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
UIImage* thumbnailImage;


NSUInteger totalNum = CGPDFDocumentGetNumberOfPages(pdf);

for(int i = 0; i < totalNum; i++ ) {


    CGContextSaveGState(context);
    CGContextTranslateCTM(context, 0.0, aRect.size.height);
    CGContextScaleCTM(context, 1.0, -1.0);

    CGContextSetGrayFillColor(context, 1.0, 1.0);
    CGContextFillRect(context, aRect);


    // Grab the first PDF page
    page = CGPDFDocumentGetPage(pdf, i + 1);
    CGAffineTransform pdfTransform = CGPDFPageGetDrawingTransform(page, kCGPDFMediaBox, aRect, 0, true);
    // And apply the transform.
    CGContextConcatCTM(context, pdfTransform);

    CGContextDrawPDFPage(context, page);

    // Create the new UIImage from the context
    thumbnailImage = UIGraphicsGetImageFromCurrentImageContext();

    //Use thumbnailImage (e.g. drawing, saving it to a file, etc)

    CGContextRestoreGState(context);

}


UIGraphicsEndImageContext();    
CGPDFDocumentRelease(pdf);

答案 1 :(得分:12)

Apple在CoreGraphics级别提供了大量方法,用于直接绘制PDF内容。据我所知,它没有一个整齐地打包在UIKit级别,所以在这一点上它可能不适合你的项目,特别是如果你不熟悉C级。但是,相关函数是CGContextDrawPDFPage;的正常CoreGraphics方式,还有其他方法可以从数据源创建PDF引用,然后从PDF获取页面引用。然后,您需要处理缩放并转换为您想要的视图,并警告您需要执行水平翻转,因为PDF(和OS X)使用左下角作为原点,而iOS使用左上角。示例代码,在我的头顶:

UIGraphicsBeginImageContext(thumbnailSize);
CGPDFDocumentRef pdfRef = CGPDFDocumentCreateWithProvider( (CGDataProviderRef)instanceOfNSDataWithPDFInside );
CGPDFPageRef pageRef = CGPDFDocumentGetPage(pdfRef, 1); // get the first page

CGContextRef contextRef = UIGraphicsGetCurrentContext();

// ignore issues of transforming here; depends on exactly what you want and
// involves a whole bunch of normal CoreGraphics stuff that is nothing to do
// with PDFs
CGContextDrawPDFPage(contextRef, pageRef);

UIImage *imageToReturn = UIGraphicsGetImageFromCurrentImageContext();

// clean up
UIGraphicsEndImageContext();
CGPDFDocumentRelease(pdfRef);

return imageToReturn;

猜测一下,您可能希望使用CGPDFPageGetBoxRect(pageRef, kCGPDFCropBox)来获取页面的裁剪框,然后找出如何缩放/移动它以适合您的图像大小。

-renderInContext:上的CALayer方法可能更容易实现您的目的(请参阅QA 1703) - 获取屏幕截图的旧方法是UIGetScreenImage,但实际上并非如此官方API,似乎暂时只是因为RedLaser的意外批准而被允许。使用QA中的代码,您可以自己设置从任何其他视图获取UIImage,而不必在屏幕上显示该视图。哪个可能解决了屏幕捕获的一些问题?虽然这意味着您只能支持OS 4.x.

在任何一种情况下,PDF都不会快速绘制。您可能需要填充表格,然后在后台线程上绘制缩略图,在可用时将它们向上推。

,所有CoreGraphics内容都是安全的,所以你无法在后台线程上安全地使用UIKit对象。

答案 2 :(得分:2)

这是一个用于为pdf页面生成UIImage缩略图的快速3方法

static func getThumbnailForPDF(_ urlString:String, pageNumber:Int) -> UIImage? {
    let bundle = Bundle.main
    let path = bundle.path(forResource: urlString, ofType: "pdf")
    let pdfURL = URL(fileURLWithPath: path!)

    let pdf = CGPDFDocument(pdfURL as CFURL )!
    let page = pdf.page(at: pageNumber)!
    let rect = CGRect(x: 0, y: 0, width: 100.0, height: 70.0) //Image size here

    UIGraphicsBeginImageContext(rect.size)
    let context = UIGraphicsGetCurrentContext()!

    context.saveGState()
    context.translateBy(x: 0, y: rect.height)
    context.scaleBy(x: 1.0, y: -1.0)
    context.setFillColor(gray: 1.0, alpha: 1.0)
    context.fill(rect)


    let pdfTransform = page.getDrawingTransform(CGPDFBox.mediaBox, rect: rect, rotate: 0, preserveAspectRatio: true)
    context.concatenate(pdfTransform)
    context.drawPDFPage(page)

    let thumbImage = UIGraphicsGetImageFromCurrentImageContext()
    context.restoreGState()

    UIGraphicsEndImageContext()

    return thumbImage
}

答案 3 :(得分:0)

如果使用PDFKit,则PDFPage的方法称为thumbnail。它在iOS11及更高版本中可用,只需几行代码即可完成工作。这是一种用于在PDFDocument中生成给定页面的缩略图的简单方法。

func makeThumbnail(pdfDocument: PDFDocument?, page: Int) -> UIImage? {
        return pdfDocument?.page(at: page)?.thumbnail(of: CGSize(width: 40, height: 40), for: .artBox)
    }

不幸的是,它缺少官方文档(请参阅https://developer.apple.com/documentation/pdfkit/pdfpage/2869834-thumbnail)。但是,在PDFPage的代码中可以访问一些注释。