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