Создание миниатюры PDF в iphone - PullRequest
7 голосов
/ 14 апреля 2011

Я новичок в Objective-c для программирования на iPhone.У меня есть приложение, в котором я успешно отображаю PDF в своем UIWebView, но теперь я хочу создать эскиз моего 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 ]

24 голосов
/ 14 апреля 2011

попробуйте следующий метод:

- (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 голосов
/ 04 октября 2016

Swift 3

(Спасибо Prine за 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 голосов
/ 14 ноября 2016

Я придумаю решение, которое использует 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, rotate: 0, preserveAspectRatio: true))
    context.drawPDFPage(page)
    context.restoreGState()

    return context.makeImage().flatMap() { UIImage(cgImage: $0, scale: UIScreen.main.scale, orientation: .up) }
}
2 голосов
/ 14 апреля 2011

Как вы уже знаете, есть 2 способа рендеринга PDF:

  • UIWebView
  • Кварц Рендеринг

Другие ответы на момент написания этого были сосредоточены на Кварце. Есть несколько веских причин для этого, в основном связанных с производительностью, но, на мой взгляд, использование Quartz того стоит. Я бы порекомендовал прочитать эту ветку , чтобы получить лучшее представление о плюсах и минусах.

По-видимому, есть превосходный новый API для рендеринга PDF на основе кварца здесь

ofc вы можете представить PDF через UIWebView и визуализировать большие пальцы с помощью кварца.

Существует также некоторая путаница вокруг больших пальцев, для людей новая магия кварцевого PDF, может показаться, что после некоторого поиска есть apis, которые поддерживают большие пальцы, мы должны проверить, поддерживает ли встроенный большие пальцы. только многие PDF-файлы не имеют их.

Другой вариант - создать большие пальцы самостоятельно (используя кварц), и в сети есть множество примеров этого, включая два ответа выше. Однако, если вы ориентируетесь на iOS 4 или выше, я настоятельно рекомендую использовать блоки. (Также графические контексты являются потокобезопасными начиная с 4).

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

Что я делал в прошлом:

  • Есть ViewController для вашего превью, у него есть прокрутка размер контента подходит для всех ваши страницы. Вставить заполнитель ImageViews в это, если хотите.

  • При загрузке документа откиньте большой палец генератор в фоновом режиме (см. код ниже)

  • Приведенный ниже код вызывает метод drawImageView, который берет индекс страницы, извлекает изображение с диска и помещает его в представление прокрутки

  • Если ваше чувство действительно мотивировано, вы можете реализовать область рендеринга для большого пальца scrollView (только для рендеринга больших пальцев, которые вам нужны - что-то, что вы должны делать для PDF-файла в любом случае)

  • Не забудьте удалить большие пальцы, когда вы закончите, если вы не хотите кешировать ..

#define THUMB_SIZE 100,144</p> <pre><code>-(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 голос
/ 30 апреля 2015

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