一、UIKit和Core Graphics的坐标系不同
在iOS中,存在两个坐标系:
- 左上角为原点的坐标系(upper-left-origin,ULO),例如UIKit和Core Animation
- 左下角为原点的坐标系(lower-left-origin,LLO),例如Core Graphics
如下图所示:
由于两个坐标系不同,如果直接在屏幕显示由Core Graphics加载的图片,那么看到的图片效果是「上下颠倒」的。
因此在图片显示之前,需要手动将图片「上下翻转」以达到预期的效果。有两种方式:
-
通过修改CTM(current transformation matrix)来翻转默认坐标系
代码示例:
CGContextSaveGState(graphicsContext); CGContextTranslateCTM(graphicsContext, 0.0, imageHeight); CGContextScaleCTM(graphicsContext, 1.0, -1.0); CGContextDrawImage(graphicsContext, image, CGRectMake(0, 0, imageWidth, imageHeight)); CGContextRestoreGState(graphicsContext);
在图片显示时手动翻转
GPUImage采用的是第二种方式。
二、GPUImage中的texture顶点设置
在OpenGL ES中,texture的原始坐标系如下:
可以看到,左下角是原点,从左到右、从下到上坐标依次递增。
对于用来render的GPUImageView
来说,kGPUImageNoRotation
对应的就是将texture的坐标系上下翻转,其他旋转方式则根据翻转后的坐标系确定。
下面是我总结的不同旋转方式对应的坐标:
对应的代码为:
static const GLfloat noRotationTextureCoordinates[] = {
0.0f, 1.0f,
1.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f,
};
static const GLfloat rotateRightTextureCoordinates[] = {
1.0f, 1.0f,
1.0f, 0.0f,
0.0f, 1.0f,
0.0f, 0.0f,
};
static const GLfloat rotateLeftTextureCoordinates[] = {
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 0.0f,
1.0f, 1.0f,
};
static const GLfloat verticalFlipTextureCoordinates[] = {
0.0f, 0.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
};
static const GLfloat horizontalFlipTextureCoordinates[] = {
1.0f, 1.0f,
0.0f, 1.0f,
1.0f, 0.0f,
0.0f, 0.0f,
};
static const GLfloat rotateRightHorizontalFlipTextureCoordinates[] = {
1.0f, 0.0f,
1.0f, 1.0f,
0.0f, 0.0f,
0.0f, 1.0f,
};
static const GLfloat rotateRightVerticalFlipTextureCoordinates[] = {
0.0f, 1.0f,
0.0f, 0.0f,
1.0f, 1.0f,
1.0f, 0.0f,
};
static const GLfloat rotate180TextureCoordinates[] = {
1.0f, 0.0f,
0.0f, 0.0f,
1.0f, 1.0f,
0.0f, 1.0f,
};
那么对于GPUImageFilter
中的坐标呢?kGPUImageNoRotation
对应的当然是texture的原始坐标系,但是旋转的坐标不能简单地据此确定,而要考虑到最终上下翻转后可以得到预期的效果。举例来说,如果要实现翻转后是右转的效果,那么翻转前对应的应该是左转。其他旋转方式可以类似地推理得到。
下面是我总结的不同旋转对应的坐标:
对应的代码为:
static const GLfloat noRotationTextureCoordinates[] = {
0.0f, 0.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
};
static const GLfloat rotateLeftTextureCoordinates[] = {
1.0f, 0.0f,
1.0f, 1.0f,
0.0f, 0.0f,
0.0f, 1.0f,
};
static const GLfloat rotateRightTextureCoordinates[] = {
0.0f, 1.0f,
0.0f, 0.0f,
1.0f, 1.0f,
1.0f, 0.0f,
};
static const GLfloat verticalFlipTextureCoordinates[] = {
0.0f, 1.0f,
1.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f,
};
static const GLfloat horizontalFlipTextureCoordinates[] = {
1.0f, 0.0f,
0.0f, 0.0f,
1.0f, 1.0f,
0.0f, 1.0f,
};
static const GLfloat rotateRightHorizontalFlipTextureCoordinates[] = {
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 0.0f,
1.0f, 1.0f,
};
static const GLfloat rotateRightVerticalFlipTextureCoordinates[] = {
1.0f, 1.0f,
1.0f, 0.0f,
0.0f, 1.0f,
0.0f, 0.0f,
};
static const GLfloat rotate180TextureCoordinates[] = {
1.0f, 1.0f,
0.0f, 1.0f,
1.0f, 0.0f,
0.0f, 0.0f,
};
三、参考文献
- 官方文档:Coordinate Systems and Drawing in iOS
- GPUImage项目地址:https://github.com/BradLarson/GPUImage