Как я могу программно сгенерировать миниатюру PDF с iOS? - PullRequest
11 голосов
/ 05 ноября 2010

Мы отображаем PDF-контент, используя UIWebViews на данный момент.В идеале я хотел бы иметь возможность отображать миниатюры в UITableView без одновременной загрузки множества различных UIWebViews ... они достаточно медленно загружают один документ - не говоря уже о 10 +!

Как мне поступитьо том, как это сделать?

Я думал о захвате экрана документа, загруженного с использованием UIDocumentInteractionController или UIWebView, но это означает, что перед отображением таблицы все они должны быть наколенниками.

Ответы [ 3 ]

13 голосов
/ 22 января 2011

Вот пример кода с учетом преобразования.:)

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);
12 голосов
/ 05 ноября 2010

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-файлы просто не отрисовываются так быстро.Вам, вероятно, нужно заполнить таблицу, а затем нарисовать миниатюры в фоновом потоке, подталкивая их вверх, когда они доступны.На самом деле вы не можете безопасно использовать объекты UIKit в фоновых потоках, но все вещи CoreGraphics безопасны.

2 голосов
/ 16 марта 2017

Вот быстрый метод 3 для создания миниатюры UIImage для страницы в формате PDF

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
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...