CoreGraphics做高性能像素级渲染

用 CADisplayLink 做逐帧刷新

CADisplayLink* displayLink = [CADisplayLink displayLinkWithTarget: self 
                                                         selector: @selector(update)];
[displayLink addToRunLoop: NSRunLoop.mainRunLoop 
                  forMode: NSDefaultRunLoopMode];

刷新方法里,调用渲染的 UIView 的 setNeedsDisplay

- (void)update {
    [self.vv setNeedsDisplay];
}

在渲染的 UIView 子类下,继承 drawLayer

// drawRect 也记得写上,否则失效
- (void)drawRect:(CGRect)rect {
    [super drawRect: rect];
}

- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx {
    CGContextClearRect(ctx, CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height));
    CGContextSaveGState(ctx);
    const int width = 320;
    const int height = 640;
    CGRect drawRect = CGRectMake(0, 0, width, height);
    CGContextTranslateCTM(ctx, 0, self.bounds.size.height);
    CGContextScaleCTM(ctx, self.bounds.size.width / width, -self.bounds.size.height / height); 
    uint32_t pixels[width * height] = { 0 };
    for (size_t i = 0; i < width * height; ++i) {
        pixels[height][width] = 0xffffffff;
    }
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef context = CGBitmapContextCreate(pixels,
                                                 width,
                                                 height,
                                                 8,
                                                 width * 4,
                                                 colorSpace,
                                                 kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little);
    CGColorSpaceRelease(colorSpace);
    CGImageRef imageRef = CGBitmapContextCreateImage(context);
    CGContextRelease(context);
    CGContextDrawImage(ctx, drawRect, imageRef);
    CGContextRestoreGState(ctx);
}

○ 记得继承 drawRect

当我们绘制 CALayer 时,需要使用 UIView 的相关信息,该信息被保存在 CGContextRef 中,而这个信息要调用了 drawRect 后才能使用。

也就是说,UIView 调用 drawRect 后才会进一步调用 drawLayer,因此继承 UIView 时,必须继承实现 drawRect,这样 drawLayer 继承才会被调用。

○ CGContextClearRect

用于清除矩形中绘制的信息。

○ CGContextSaveGState/CGContextRestoreGState

保存和恢复上下文,在绘制图层的开始和结束调用。以避免破坏之前的上下文。

○ CGContextTranslateCTM

扫描二维码关注公众号,回复: 15446464 查看本文章

该函数的作用是将绘图上下文沿x轴和y轴平移指定的距离。

在本例中,CGContextTranslateCTM 为什么是这么调用呢:

`CGContextTranslateCTM(ctx, 0, self.bounds.size.height);` 

这个要配合后面的 CGContextScaleCTM 才能揭晓完整答案。

CGContextTranslateCTM 用于设置屏幕绘制的起始区域,这里用 (0, self.bounds.size.height),即将绘制的起始区域设置在屏幕左下方。

○ CGContextScaleCTM

如果按照上一行代码的设置,绘制的区域显然就“超出屏幕”了。所以需要第二个函数 CGContextScaleCTM,可以看到函数是这么被调用的:

CGContextScaleCTM(ctx, self.bounds.size.width / width, -self.bounds.size.height / height); 

这个函数可以看出是用于屏幕拉伸的,拉伸的比例是横纵向全拉伸满,这个很好理解,但是关键要注意第二个参数:

-self.bounds.size.height / height

第二个参数是负值,这意味着绘制的区域会做反向拉伸,于是画面会被翻转,结合 CGContextTranslateCTM 后,画面的绘制就变成从屏幕左下角作为纵向坐标的起始地址,绘制到屏幕的左上角。

○ CGColorSpaceCreateDeviceRGB/CGColorSpaceRelease

用于创建和释放 RGB 颜色空间对象。创建出来的对象会作为参数给 CGBitmapContextCreate 使用。

○ CGBitmapContextCreate/CGContextRelease

用于创建和释放位图的图形上下文函数,通过这个函数将位图数据传入。

○ CGBitmapContextCreateImage

创建位图。
需要注意的是,这里不需要释放位图,是因为该引用会被用于绘制 UIView,接下来它会进入 UIView 的生命周期管理。

○ CGContextDrawImage

将位图渲染到 UIView 的图层。

猜你喜欢

转载自blog.csdn.net/madaxin/article/details/130337056