iOS - Создание PDF из UIView путем рендеринга теряет качество - PullRequest
8 голосов
/ 30 октября 2011

Я использовал следующие методы для создания PDF из UIView. Все они создают PDF, но теряют качество:

Метод 1:

@implementation UIView(PDFWritingAdditions)

- (void)renderInPDFFile:(NSString*)path
{
    CGRect mediaBox = self.bounds;
    CGContextRef ctx = CGPDFContextCreateWithURL((__bridge_retained CFURLRef)[NSURL fileURLWithPath:path], &mediaBox, NULL);
    CGPDFPageRef page;
    CGContextDrawPDFPage(ctx, page);

    CGPDFContextBeginPage(ctx, NULL);

    // Also tried following commented lines but no luck
    //    CGContextSetFlatness(ctx, 0.1);
    //    CGContextSetAllowsAntialiasing(ctx, YES);
    //    CGContextSetAllowsFontSmoothing(ctx, YES);
    //    CGContextSetInterpolationQuality(ctx, kCGInterpolationHigh);
    CGContextScaleCTM(ctx, 1, -1);
    CGContextTranslateCTM(ctx, 0, -mediaBox.size.height);
    [self.layer renderInContext:ctx];
    CGPDFContextEndPage(ctx);
    CFRelease(ctx);
}

@end

Метод 2:

- (void)createPDFfromUIView:(UIView*)aView saveToDocumentsWithFileName:(NSString*)aFilename
{
    // Creates a mutable data object for updating with binary data, like a byte array
    NSMutableData *pdfData = [NSMutableData data];

    // Points the pdf converter to the mutable data object and to the UIView to be converted
    UIGraphicsBeginPDFContextToData(pdfData, aView.bounds, nil);
    UIGraphicsBeginPDFPage();
    CGContextRef pdfContext = UIGraphicsGetCurrentContext();


    // draws rect to the view and thus this is captured by UIGraphicsBeginPDFContextToData

    [aView.layer renderInContext:pdfContext];

    // remove PDF rendering context
    UIGraphicsEndPDFContext();

    // Retrieves the document directories from the iOS device
    NSArray* documentDirectories = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES);

    NSString* documentDirectory = [documentDirectories objectAtIndex:0];
    NSString* documentDirectoryFilename = [documentDirectory stringByAppendingPathComponent:aFilename];

    // instructs the mutable data object to write its context to a file on disk
    [pdfData writeToFile:documentDirectoryFilename atomically:YES];
    NSLog(@"documentDirectoryFileName: %@",documentDirectoryFilename);
}

Я думаю, что мне не хватает некоторых настроек для контекста pdf, не уверен. Также я создал изображение в формате png из UIView следующим методом, который точно такого же качества:

- (UIImage *)imageFromView:(UIView *)view
{
    UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.opaque, 0.0);
    [view.layer renderInContext:UIGraphicsGetCurrentContext()];

    UIImage * img = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();
    // Retrieves the document directories from the iOS device
    NSArray* documentDirectories = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES);

    NSString* documentDirectory = [documentDirectories objectAtIndex:0];
    NSString* documentDirectoryFilename = [documentDirectory stringByAppendingPathComponent:@"pdf.png"];

    // instructs the mutable data object to write its context to a file on disk
    [UIImagePNGRepresentation(img) writeToFile:documentDirectoryFilename atomically:YES];
    NSLog(@"documentDirectoryFileName: %@",documentDirectoryFilename);
    return img;
}

Может кто-то увидеть, что я делаю не так? Спасибо.

Ответы [ 3 ]

2 голосов
/ 01 ноября 2011

Использует ли это дисплей сетчатки? Это может быть предметом содержимого. Посмотрите на этот пост

EDIT Хорошо, теперь, когда вы разместили фотографии до и после, я вижу, что вы хотите, чтобы счет-фактура UIView отображалась в виде хороших, высококачественных векторных изображений для печати в вашем PDF.

Я почти уверен, что [CALayer renderInContext] всегда создает растровые данные, поэтому вам, вероятно, лучше создавать PDF вручную. И если вы говорите о налоговых накладных, действительно ли вы хотите изменить макет при следующем обновлении iOS?

Однако вы можете посмотреть на этот ответ , который неохотно предлагает использовать UIView в качестве системы шаблонов для макета вашего PDF.

0 голосов
/ 05 ноября 2013

edit ок, это не совсем та же проблема, но я думаю, что решение будет похожим

Я думаю, что это обманка Высокое качество UIImage из PDF

Смотрите мой ответ там:

https://stackoverflow.com/a/14152516/210171

Когда вы спрашиваете PDF о размере страницы, вы получаете ширину / высоту для 72 PPI. Вы можете попытаться создать контекст, который масштабируется с помощью масштабное преобразование. Например, если вы хотите визуализировать с разрешением 300 точек на дюйм, добавьте масштаб преобразовать в масштаб на 300.0/72.0.

Если вы экспортируете как TIFF, вы сможете инкапсулировать окончательный ИЦП (300) сгенерированного изображения.

0 голосов
/ 24 сентября 2012

Глядя на ваши примеры изображений, я не уверен, что ваши ожидания верны ... Ваше окно предварительного просмотра частично увеличено, в то время как вы рисуете растровое изображение в своем PDF - так вы увидите «неровные края» при увеличении. Если вы просматриваете фактический размер (из меню просмотра в Preview или Cmd-0), вы должны увидеть более или менее идентичное изображение со своим скриншотом.

Однако, что вы действительно хотите сделать, это не просто отобразить растровое изображение UIView в контекст PDF, а вместо этого сделать чертеж и макет CoreGraphics непосредственно в контексте PDF. Посмотрите этот урок http://www.raywenderlich.com/6818/how-to-create-a-pdf-with-quartz-2d-in-ios-5-tutorial-part-2 для примера. Это обеспечит четкость текста и линий при увеличении, а также обеспечит качественный продукт при печати на бумаге. Кварц2D векторная графика - ваш друг здесь, так как вы никогда не получите высокое качество с растровым изображением, по крайней мере, без создания огромного файла PDF ...

...