Преобразование PDF в UIImageView

Я нашел код, который дает мне UIImage из PDF файла. Он работает, но у меня есть два вопроса:

  • Есть ли возможность достичь лучшего качества UIImage? (См. Скриншот)
  • Я вижу только первую страницу в UIImageView. Должен ли я вставлять файл в UIScrollView для завершения?
  • Или лучше отображать только одну страницу и использовать кнопки для навигации по страницам?

P.S. Я знаю, что UIWebView может отображать PDF-страницы с некоторыми функциями, но мне это нужно как UIImage или по крайней мере в UIView.

Bad quality Image:

Bad quality Image

Code:

-(UIImage *)image {
UIGraphicsBeginImageContext(CGSizeMake(280, 320)); 

CGContextRef context = UIGraphicsGetCurrentContext();

CFURLRef pdfURL = CFBundleCopyResourceURL(CFBundleGetMainBundle(), CFSTR("ls.pdf"), NULL, NULL);

CGPDFDocumentRef pdf = CGPDFDocumentCreateWithURL((CFURLRef)pdfURL);

CGContextTranslateCTM(context, 0.0, 320);

CGContextScaleCTM(context, 1.0, -1.0);

CGPDFPageRef page = CGPDFDocumentGetPage(pdf, 4);

CGContextSaveGState(context);

CGAffineTransform pdfTransform = CGPDFPageGetDrawingTransform(page, kCGPDFCropBox, CGRectMake(0, 0, 280, 320), 0, true);

CGContextConcatCTM(context, pdfTransform);

CGContextDrawPDFPage(context, page);

CGContextRestoreGState(context);

UIImage *resultingImage = UIGraphicsGetImageFromCurrentImageContext();  
UIGraphicsEndImageContext();
return resultingImage;
}

Ответ 1

Что вы делаете с вызовом CGContextTranslateCTM(context, 0.0, 320);?

Вы должны извлечь правильные метрики в формате pdf, с таким кодом:

 cropBox = CGPDFPageGetBoxRect(page, kCGPDFCropBox);
 rotate = CGPDFPageGetRotationAngle(page);

Кроме того, как вы видите, в pdf может быть информация о ротации, поэтому вам нужно использовать CGContextTranslateCTM/CGContextRotateCTM/CGContextScaleCTM в зависимости от угла.

Вы также можете захотеть скопировать любой контент, который находится за пределами области CropBox, так как в pdf есть различные viewPorts, которые вы обычно не хотите отображать (например, для принтеров, чтобы возможна полная печать) → use CGContextClip.

Затем вы забываете, что в справочнике pdf задается белый цвет фона. Есть много документов, которые не определяют какой-либо фоновый цвет вообще - вы получите странные результаты, если вы не нарисуете белый фон самостоятельно → CGContextSetRGBFillColor и CGContextFillRect.

Ответ 2

Я знаю, что немного опоздал, но я надеюсь, что смогу помочь кому-то еще найти ответ. Что касается заданных вопросов:

  • Я боюсь, что единственный способ добиться лучшего качества изображения - сделать большее изображение и позволить UIImageView изменить его размер для вас. Я не думаю, что вы можете установить разрешение, но использование большего изображения может быть хорошим выбором. Для страницы не потребуется слишком много времени, и изображение будет иметь лучшее качество. PDF файлы отображаются по запросу в зависимости от уровня масштабирования, поэтому они, похоже, имеют "лучшее качество".

  • Что касается рендеринга всех страниц, вы можете получить количество страниц в документе, вызывающих CGPDFDocumentGetNumberOfPages( pdf ), и используя простой цикл for, вы можете конкатрировать все изображения, созданные на одном изображении. Для его отображения используйте UIScrollVIew.

  • На мой взгляд, этот подход лучше, чем выше, но вы должны попытаться его оптимизировать, например, всегда отображая текущую, предыдущую и следующую страницу. Для хороших эффектов перехода прокрутки, почему бы не использовать горизонтальный UIScrollVIew.

Для более общего кода рендеринга я всегда делаю поворот следующим образом:

int rotation = CGPDFPageGetRotationAngle(page);

CGContextTranslateCTM(context, 0, imageSize.height);//moves up Height
CGContextScaleCTM(context, 1.0, -1.0);//flips horizontally down
CGContextRotateCTM(context, -rotation*M_PI/180);//rotates the pdf
CGRect placement = CGContextGetClipBoundingBox(context);//get the flip placement
CGContextTranslateCTM(context, placement.origin.x, placement.origin.y);//moves the the correct place

//do all your drawings
CGContextDrawPDFPage(context, page);

//undo the rotations/scaling/translations
CGContextTranslateCTM(context, -placement.origin.x, -placement.origin.y);
CGContextRotateCTM(context, rotation*M_PI/180);
CGContextScaleCTM(context, 1.0, -1.0);
CGContextTranslateCTM(context, 0, -imageSize.height);

Steipete уже упомянул установку белого фона:

CGContextSetRGBFillColor(context, 1, 1, 1, 1);
CGContextFillRect(context, CGRectMake(0, 0, imageSize.width, imageSize.height)); 

Итак, последнее, что нужно иметь в виду, - это экспортировать изображение, установить максимальное значение. Например:

UIImageJPEGRepresentation(image, 1);