一、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的坐標系上下翻轉,其他旋轉方式則根據(jù)翻轉后的坐標系確定。
下面是我總結的不同旋轉方式對應的坐標:

對應的代碼為:
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的原始坐標系,但是旋轉的坐標不能簡單地據(jù)此確定,而要考慮到最終上下翻轉后可以得到預期的效果。舉例來說,如果要實現(xiàn)翻轉后是右轉的效果,那么翻轉前對應的應該是左轉。其他旋轉方式可以類似地推理得到。
下面是我總結的不同旋轉對應的坐標:

對應的代碼為:
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