iOS улучшает скорость рендеринга PDF

#iphone #ios #ipad #pdf #render

#iPhone #iOS #iPad #PDF #рендеринг

Вопрос:

Я пишу приложение, которое управляет документами для пользователя и (в конечном итоге) публикует PDF-файлы, передаваемые через веб-службу на iPhone / iPad. Это почти исключительно отсканированные PDF-файлы, и они, похоже, ДЕЙСТВИТЕЛЬНО сильно загружают устройство iOS.

Первое решение, которое я придумал, заключалось в том, чтобы просто разместить PDF-файл в UIWebView. Это работает очень, очень хорошо для «сгенерированных» PDF-файлов, но не для отсканированных PDF-файлов (я предполагаю, что разница здесь в растре и векторе?).

Моим следующим решением было внедрить UIDocumentInteractionController, который, как говорили, повышает оперативность. Я могу сообщить, что это, действительно, кажется быстрее, чем UIWebView, но это все еще неприемлемо медленно, даже для небольших файлов PDF на 2 страницы. (Кстати, функция «автоматическое открытие в другом приложении» наряду со встроенной печатью очень удобна!)

Я прочитал один или два поста о фреймворке QuickLook и планирую изучить это, но я также наткнулся на несколько сообщений, в которых говорится о классах CGPDFDocument и тому подобном. Похоже, у них более точный контроль над навигацией по документу (а-ля xPdf), но я понятия не имею, с чего начать. Кроме того, я даже не уверен, обеспечивает ли это преимущество в производительности для того, что я делаю.

Итак, первый вопрос: какой самый быстрый способ рендеринга отсканированных PDF-файлов на iPhone / iPad?

Второй вопрос: Отсканированные PDF-файлы создаются моей компанией, поэтому у меня есть некоторый контроль над настройками генерации PDF. Кто-нибудь знает, какие настройки могут улучшить скорость загрузки файлов PDF на основе изображений?

Спасибо!

(Кстати: сегодня я кодировал 19 часов подряд, так что, если я сбивчив или не имел смысла, пожалуйста, простите меня! :))

Комментарии:

1. У вас есть образец PDF, который вы можете загрузить для нас? Скорее всего, это связано с типом используемого сжатия в формате TIFF (предполагается, что бумага изначально была отсканирована в формате TIFF).

Ответ №1:

Самым быстрым решением будет написать свой собственный пользовательский анализатор pdf и платформу рендеринга, используя классы CGPDFDocument. Секрет сверхбыстрого рендеринга pdf заключается в использовании таких методов, как:

  • Закадровый рендеринг полноразмерных страниц в изображения.
  • Активируйте рисование в CATiledLayer только после определенного уровня масштабирования. Когда пользователь просматривает вашу страницу pdf с масштабированием по умолчанию, нет необходимости активировать рисунок CATiledLayer, потому что это очень дорого. Просто отобразите уже отрисованное изображение за пределами экрана. Когда пользователь начнет увеличивать масштаб, вы можете активировать CATiledLayer.
  • Использование интеллектуального алгоритма для кэширования страниц PDF, отображаемых за пределами экрана. Вы можете кэшировать предыдущую и следующую страницы как изображения, отображаемые за пределами экрана.
  • На быстрых устройствах (iPhone 4 или выше и iPad 2 или выше) вы можете запустить фоновое задание, которое отобразит все страницы за пределами экрана и сохранит их на диске.
  • Кэшируйте регулярно используемую информацию о страницах pdf, такую как: исходная прямая, поворот, повернутая прямая и т.д.
  • Вы будете использовать множество объектов CGPDFPageRef. Важно знать, что это значительно увеличит использование памяти. Небольшая хитрость заключается в закрытии и повторном открытии объекта CGPDFDocumentRef при получении предупреждения о памяти.

Я использовал все вышеупомянутые методы в PDFTouch SDK для iOS, который является разработанным мной фреймворком для быстрого рендеринга pdf!

Ответ №2:

Возможно, вы захотите уменьшить размер изображения. Большие PDF-файлы действительно доводят iPad / iPhone до предела. Конечно, это означает, что вам нужно рисовать / управлять PDF-файлом самостоятельно, с помощью вызовов Quartz.

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

Ответ №3:

если вы в отчаянии, вы можете повторно обработать файлы pdf на своем сервере, чтобы превратить их в простые файлы изображений (связанные с исходными файлами pdf), а затем загрузить их. таким образом, не нужно выполнять синтаксический анализ «pdf». и затем вы можете разместить на сервере или включить как часть приложения, если объем невелик.

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

Ответ №4:

Используя UIWebView для рендеринга pdf, мы не получим надлежащего контроля над pdf. например, мы не можем перейти на нужную страницу напрямую. и мы не можем выполнить поиск по определенному слову и выделить его.

для правильной обработки PDF-документов лучше использовать классы CGPDF, такие как CGPDFDocumentRef и CGPDFPageRef.

Используя эти классы, у нас есть два варианта обработки PDF-файлов. 1. извлеките страницы pdf в виде изображений по отдельности и отобразите с помощью UIImageView. 2. извлеките содержимое каждой страницы с помощью CGPDFPageRef и создайте PDF для каждой страницы во время выполнения и отобразите в webview. (улучшенное управление PDF и аккуратное отображение)

ниже приведен пример кода для извлечения отдельной страницы в виде изображения.

 -(UIImage *)getPage : (NSString*) filePath{

    const char *myBuffer           = (const char*)filePath;                        // PDF Path
    CFStringRef urlString          = (CFStringRef)myBuffer;
    CFURLRef url                   = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, urlString, 2, NO);  
    CGPDFDocumentRef myDocumentRef = CGPDFDocumentCreateWithURL(url);

    CGPDFPageRef myPageRef         = CGPDFDocumentGetPage(myDocumentRef, 1);
    CGRect pdfcropBox              = CGPDFPageGetBoxRect(myPageRef,kCGPDFCropBox); //kCGPDFCropBox

    UIGraphicsBeginImageContext      (pdfcropBox.size);
    CGContextRef context           = UIGraphicsGetCurrentContext();
    CGContextTranslateCTM            (context,0,pdfcropBox.size.height);// [self pageRect].origin.x,[self pageRect].origin.y [self pageRect].size.height); //320);
    // scale 1:1 100%
    CGContextScaleCTM                (context, 1.0, -1.0);
    CGContextSaveGState              (context);
    CGAffineTransform pdfTransform = CGPDFPageGetDrawingTransform(myPageRef, kCGPDFCropBox, CGRectMake(0, 0, pdfcropBox.size.width,pdfcropBox.size.height), 0, true);  //
    CGContextConcatCTM               (context, pdfTransform);
    CGContextDrawPDFPage             (context, myPageRef);
    CGContextRestoreGState           (context);

    UIImage *resultingImage        = UIGraphicsGetImageFromCurrentImageContext();  
    UIGraphicsEndImageContext        ();
    CGPDFDocumentRelease             (myDocumentRef);

    //CGPDFPageRelease(myPageRef);
        //myPageRef   = nil;
    myDocumentRef = nil;
    urlString     = nil;
    url           = nil;
    return resultingImage;
}
  

Ответ №5:

Вот мои 2 цента за простой и быстрый рендеринг pdf в swift.

SwiftyPDF

  • Подкачка с помощью системного UIPageViewController
  • Масштабирование с помощью функций масштабирования UIScrollView
  • Ускоряет рендеринг PDF-файла путем преобразования страницы в изображение-заполнитель
  • Страница PDF масштабируется и разбивается на небольшие фрагменты. Фрагменты кэшируются в файлы изображений и отображаются поверх изображения-заполнителя (с использованием CATiledLayer)

Все еще WIP