IOS开发--------pdf渲染的小窍门

本文介绍如何使用CoreGraphics和CATiledLayer解决iOS应用中PDF页面放大模糊及渲染速度慢的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我们都知道,在iPhone/iPad显示pdf的基本方法有两个,一个是使用UIWebView直接加载pdf文件,另一个是使用Core Graphics进行渲染(姑且称之为CGPDF方法)。UIWebView的方法是简单,只需加载pdf,其他诸如放大翻页等问题通通交给UIWebView去头痛吧。但其缺点是性能较慢,功能有限,比如要实现搜索,添加笔记等功能就比较难。而使用CGPDF方法,功能就没有限制(虽然pdf解析方面,苹果提供的文档实在有限),使用Core Graphics进行渲染,性能上也比UIWebView要提高许多,只不过翻页,放大缩小等功能都需要自己实现

有关pdf放大缩小,翻页等功能可以使用UIScrollView实现,不在本文讨论的范围之内。笔者在项目中使用了CGPDF的过程中,曾遇到两个小问题,因此,在这里总结一下:

1. 页面放大后变得不清晰

先看看我程序中的渲染代码,可以放在- (void)drawRect:(CGRect)rect 或者 -(void)drawLayer:(CALayer*)layer inContext:(CGContextRef)context 中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
- (void)drawRect:(CGRect)rect
{
    CGContextRef context = UIGraphicsGetCurrentContext();

    // fill in the white background for pdf page
    CGContextSetRGBFillColor( context, 1.0, 1.0, 1.0, 1.0 );
    CGContextFillRect( context, CGContextGetClipBoundingBox( context ));
    CGContextSaveGState(context);

    // Flip the context so that the PDF page is rendered
    // right side up.
    CGContextTranslateCTM( context, 0.0, self.bounds.size.height );
    CGContextScaleCTM( context, 1.0, -1.0 );

    // Scale the context so that the PDF page is rendered
    // at the correct size for the zoom level.
    CGAffineTransform pdfXfm =
    CGPDFPageGetDrawingTransform( _page.page, kCGPDFMediaBox, self.bounds, 0, true );
    CGContextConcatCTM( context, pdfXfm );

    CGContextSetInterpolationQuality(context, kCGInterpolationHigh);
    CGContextSetRenderingIntent(context, kCGRenderingIntentDefault);
    CGContextDrawPDFPage( context, _page.page );

    CGContextRestoreGState(context);
}


简单地说,这段代码就是使用Core Graphics进行pdf的渲染,可是我的pdf放大后为什么不清晰呢?先看看放大pdf后可以使其清晰的部分代码吧:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
- (id)initWithPdfPage:(PDFPage*)page
{
    if ((self = [super initWithFrame:CGRectMake(0, 0, page.size.width, page.size.height)]))
    {
        CATiledLayer* layer = (CATiledLayer *)[self layer];

        layer.levelsOfDetail = 4;
        layer.levelsOfDetailBias = 4;
        layer.tileSize = CGSizeMake(1024.0, 1024.0);
    }
    return self;
}

+ (Class)layerClass
{
return [CATiledLayer class];
}


其秘诀就在CATiledLayer,简单地说就是CATiledLayer将不同等级的tiles(拼贴)缓存起来,而CGContextDrawPDFPage则根据最合适的放大等级将pdf渲染出来。

根据文档CATiledLayer可以更高效,高质量地渲染pdf文档,但我则遇到了第二个问题。

2. 页面渲染速度慢,而且呈块状渲染

简而言之就是pdf页面一块一块地慢慢渲染出来,效果非常不好。这是怎么回事?经过一番研究发现是CATiledLayer的动画效果在作怪。每个Tile的渲染据说都有0.25s的动画时间,其结果就是pdf文档一块一块地出现了。要怎样解决这个问题呢?最为直接的方法就是把0.25s的动画时间直接设置为0。下面是代码(采用继承CATiledLayer的方法):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@interface FastCATiledLayer : CATiledLayer
@end

@implementation FastCATiledLayer
+(CFTimeInterval)fadeDuration 
{
    return 0.0;
}

+ (Class)layerClass 
{
    return [FastCATiledLayer class];   
}

- (id)initWithPdfPage:(PDFPage*)page 
{
    if ((self = [super initWithFrame:CGRectMake(0, 0, page.size.width, page.size.height)])) 
    {
        FastCATiledLayer* layer = (FastCATiledLayer *)[self layer];
        layer.levelsOfDetail = 4;
    layer.levelsOfDetailBias = 4;
    layer.tileSize = CGSizeMake(1024.0, 1024.0);
    }
    return self;
}

@end
注:PDFPage是我自己的一个类。

from:http://www.hksilicon.com/kb/cn/articles/26030/pdf

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值