首先看看网上关于Quartz 2D的一段话:
Quartz 2D 绘制模型定义了两种独立的坐标空间:用户空间(用于表现文档页)和设备空间(用于表现设备的本地分辨率)。用户坐标空间用浮点数表示坐标,与设备空间的像素分辨率没有关系。当我们需要一个点或者显示文档时, Quartz会将用户空间坐标系统映射到设备空间坐标系统。
下面说下自己的个人见解和分析:
由于坐标空间分为用户空间和设备空间两种,所以坐标系也分为两种。一种是CGContext绘图时的坐标系,以左下角为原点,y正轴向上,x正轴向右。另一种是设备空间的坐标系,以左上角为原点,y正轴向下,x正轴向右。
其中用户空间有一个绘图上下文,可以将其想象成一张画布。如果要在当前上下文中画图片,就要使用CGContextDrawImage方法,先看看直接使用该方法的情况:
- (void)drawRect:(CGRect)rect { CGContextRef context = UIGraphicsGetCurrentContext(); UIImage *image = [UIImage imageNamed:@"addText.png"]; CGRect rect1 = CGRectMake(100.0, 100.0, 100.0, 100.0); CGContextDrawImage(context, rect1, [image CGImage]); // drawImage(context, [image CGImage], rect1); }
原来的图片为:
运行结果如下:
每个方格为100 * 100的规格。也就是image的位置是(100, 100, 100, 100),但是图片反过来了。如何在上下文中绘图,才能正确地映射到设备空间中?需要先做一些变换:
- (void)drawRect:(CGRect)rect { CGContextRef context = UIGraphicsGetCurrentContext(); UIImage *image = [UIImage imageNamed:@"addText.png"]; CGRect rect1 = CGRectMake(100.0, 100.0, 100.0, 100.0); // CGContextDrawImage(context, rect1, [image CGImage]); drawImage(context, [image CGImage], rect1); } void drawImage(CGContextRef context, CGImageRef image , CGRect rect){ CGContextSaveGState(context); CGContextTranslateCTM(context, rect.origin.x, rect.origin.y); CGContextTranslateCTM(context, 0, rect.size.height); CGContextScaleCTM(context, 1.0, -1.0); CGContextTranslateCTM(context, -rect.origin.x, -rect.origin.y); CGContextDrawImage(context, rect, image); CGContextRestoreGState(context); }
运行结果为:
之后来分析一下变化过程,先看看用户空间到设备空间的变换:
再来看看以上代码变换的详细过程,假设要在设备空间的(a, b, c, d)位置画一个矩形。
1.原来的画布
2.平移画布:CGContextTranslateCTM(context, rect.origin.x, rect.origin.y)
3.平移画布:CGContextTranslateCTM(context,0, rect.size.height);
4.翻转画布:CGContextScaleCTM(context,1.0, -1.0);
5.平移画布:CGContextTranslateCTM(context, -rect.origin.x, -rect.origin.y);
在画布上参照画布的坐标系(蓝色的坐标系)的(a, b, c, d)位置绘图:CGContextDrawImage(context, rect, image);
6.将用户空间中的图像映射到设备空间中
其中画布就是一个绘图上下文,绘图操作的结果在这里展现。用户空间有一个属于自己的坐标系,画布有一个独立于用户空间的坐标系,设备空间也有自己的坐标系,其中画布的坐标系是可变的,例如平移,翻转等,另外两个是固定的。
在进行上下文变换时,画布的位置是变化的,注意画布的坐标系翻转后,往(-c, -d)方向作平移,是相对自己的坐标系做平移的(即蓝色的坐标系),而不是原来黑色标识的用户空间坐标系。
同样地,在画布上画图时就是根据画布自己的坐标系在上面画图。
在画布上画好图后,将图像从用户空间映射到设备空间时,参照的坐标系是用户空间坐标系和设备空间坐标系。
在创建PDF文档时,PDF上下文和输出的PDF文档的坐标系是一致的。
以上部分参考了:Quartz 2D编程指南(5) - 变换
代码参考了:讨论CGContextDrawImage
以上经过Demo的测试和分析,分析过程的图是自己做的,纯属个人的一些见解。