iOS上使用Quartz 2D绘制Bitmap

2019-08-01  本文已影响0人  土豆吞噬者

Quartz 2D是一个二维绘图引擎,可以在iOS和Mac OS X中使用(不包括内核)。

图形上下文

Quartz中所有对象都被绘制到图形上下文中,包括位图图形上下文(CGBitmapContext),PDF图形上下文(CGPDFContext),窗口图形上下文(仅Mac OS X可用),分层上下文(CGLayer),打印上下文(仅Mac OS X可用)。

图形上下文表示绘图目标,它包含绘图参数和绘图系统执行任何后续绘图命令所需的所有特定于设备的信息。图形上下文定义了基本的绘图属性,例如绘制时使用的颜色,剪切区域,线宽和样式信息,字体信息,合成选项等。

要在iOS应用中绘制图像到屏幕,需要实现UIView对象并的drawRect方法,drawRect不能直接调用,必须使用setNeedsDisplay或setNeedsDisplayInRect通知系统重绘,系统会在下个绘图周期调用drawRect进行重绘,为了提高性能,要尽量避免重绘未改变的区域。在drawRect中通过调用UIGraphicsGetCurrentContext获取其图形上下文。

颜色和颜色空间

Quartz中的颜色由一组值表示,不同的设备以不同的颜色空间解释这些值,颜色空间包括HSB,RGB,CMYK,BGR,如果提供错误的颜色空间,则值表示的颜色也会发生错误。

颜色空间分为通用颜色空间和设备颜色空间,通用颜色空间可以在设备之间移植的方式表示颜色,有精确颜色要求的程序应该使用通用颜色空间,它可以使显示器上的颜色和打印出来的颜色一样好,iOS只支持设备颜色空间。

Quartz 2D坐标系

UIKit使用的坐标系与Quartz 2D坐标系不一样,所以在绘图时需要修改坐标系,如果你使用UIImage的drawInRect绘图则无需考虑这一点,UIImage会自动处理坐标系。

实践发现在iOS12.0以下的系统使用如下代码修改坐标系,然后绘制一个UIView的部分Rect会出错,而drawInRect则不会。

    CGContextTranslateCTM(ctx, 0, rect.size.height);
    CGContextScaleCTM(ctx, 1.0, -1.0);

内存管理

使用Quartz时,如果从包含Copy或Create的函数获取对象,在使用完毕后需要释放该对象。

下面的代码向我们展示了如何将Bitmap数据绘制到UIView:

- (void)drawRect:(CGRect)rect
{
    if (displayBuffer) {
        CGContextRef ctx = UIGraphicsGetCurrentContext();
        CGContextSaveGState(ctx);

        CGContextTranslateCTM(ctx, 0, rect.size.height);
        CGContextScaleCTM(ctx, 1.0, -1.0);

        CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB();
        size_t bytesPerRow = displayWidth*4;
        size_t offset=(rect.origin.y*displayWidth+rect.origin.x)*4;
        CGContextRef bmpctx = CGBitmapContextCreate(&displayBuffer[offset],rect.size.width, rect.size.height, 8, bytesPerRow, cs,kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst);
        CGImageRef image = CGBitmapContextCreateImage(bmpctx);


        CGContextDrawImage(ctx, rect, image);

        CGImageRelease(image);
        CGContextRelease(bmpctx);
        CGColorSpaceRelease(cs);
        CGContextRestoreGState(ctx);
    }
}
- (void)drawRect:(CGRect)rect
{
    if (displayBuffer) {
        CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB();
        size_t bytesPerRow = displayWidth*4;
        size_t offset=(rect.origin.y*displayWidth+rect.origin.x)*4;
        CGContextRef bmpctx = CGBitmapContextCreate(&displayBuffer[offset],rect.size.width, rect.size.height, 8, bytesPerRow, cs,kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst);
        CGImageRef image = CGBitmapContextCreateImage(bmpctx);
        [[UIImage imageWithCGImage:image]drawInRect:rect];
        CGImageRelease(image);
        CGContextRelease(bmpctx);
        CGColorSpaceRelease(cs);
    }
}
上一篇下一篇

猜你喜欢

热点阅读