目录
一、旋转原理
图像旋转就是对应像素点的位置的改变,把对应的像素点修改到指定位置即可实现90度、180度、270度旋转。如下图以4x6为例,每个格子代表一个像素点,格子里面的数字代表当前像素的位置;

SRC
顺时针方向旋转90度
我们以上图为例,顺时针方向旋转90度为例,说明旋转90原理;顺时针方向旋转90度,则宽和高互换,由原来4x6变为6x4;SRC[0]的位置被SRC[20]所替代,形成Rotate90[0],以此类推;最终形成图Rotate90的效果。

Rotate90
SRC像素对应的内存摆放位置如下:

Rotate90像素对应的内存摆放位置如下:

经过对比发现Rotate90第(
x
+
)个像素点对应SRC的应该为第
(
-
+
) ,其中因为进行了90°顺时针旋转所以
的值为
。
可以得出如下公式:
Rotate90[i,j] = SRC[ - j,i];
顺时针方向旋转180度
我们以SRC图顺时针方向旋转180度为例,说明旋转180原理;顺时针方向旋转180度,则宽和高不发生改变,还是原来的4x6;SRC[0]的位置被SRC[23]所替代,形成Rotate180[0],以此类推;最终形成图Rotate180的效果。

Rotate180
SRC像素对应的内存摆放位置如下:

Rotate180像素对应的内存摆放位置如下:

经过对比发现Rotate180第个像素点对应SRC的应该为第
(X
-
)。
可以得出如下公式:
Rotate180[i] = SRC[X
- i];
顺时针方向旋转270度
我们以SRC图顺时针方向旋转270度为例,说明旋转270原理;顺时针方向旋转270度,则宽和高互换,由原来4x6变为6x4;SRC[0]的位置被SRC[3]所替代,形成Rotate270[0],以此类推;最终形成图Rotate270的效果。

Rotate270
SRC像素对应的内存摆放位置如下:

Rotate270像素对应的内存摆放位置如下:
经过对比发现Rotate270第(
,
)个像素点对应SRC的应该为第
(
,W-
)。
可以得出如下公式:
Rotate270[i,j] = SRC[ j x ,
- i];
镜像翻转
我们以SRC图镜像翻转为例,说明镜像翻转原理,宽和高不发生改变,还是原来的4x6;SRC[0]的位置被SRC[3]所替代,形成RotateMirror[0],以此类推;最终形成图RotateMirror的效果。

RotateMirror
SRC像素对应的内存摆放位置如下:

RotateMirror像素对应的内存摆放位置如下:

经过对比发现RotateMirror第(
,
)个像素点对应SRC的应该为第
(W-
,
)。
可以得出如下公式:
Rotate270[i,j] = SRC[ -i ,j];
二、I420旋转原理
原图介绍
以I420宽高为4x8的图为例,Y0~Y31代表Y分量;U0~U7代表U分量;V0~V7代表V分量;
原图如下:

I420 SRC
I420顺时针方向旋转90度
旋转90度概述
我们以上图为例,I420顺时针方向旋转90度为例,说明I420顺时针方向旋转90原理;I420顺时针方向旋转90度,则宽和高互换,由原来4x8变为8x4;Y[0]的位置被Y[24]所替代,U[0]的位置被U[4]所替代,V[0]的位置被V[4]所替代,形成I420Rotate90[0],以此类推;最终形成图I420Rotate90的效果。

I420Rotate90
I420 SRC对应的内存摆放位置如下:

I420Rotate90对应的内存摆放位置如下:

可以得出如下公式:
I420Rotate90_Y[i,j] = SRC_Y[ - j,i];
I420Rotate90_U[i,j] = SRC_U[/2 - j,i];
I420Rotate90_V[i,j] = SRC_V[/2 - j,i];
顺时针旋转90度代码
void RotateI420(uint8_t* src_y, uint8_t* src_u, uint8_t* src_v,
uint8_t* dst_y, uint8_t* dst_u, uint8_t* dst_v,
uint32_t width, uint32_t height, int degree)
{
if (degree == kRotate90)
{
// 第一步我们只转Y
// 旋转90度
int index = 0;
for (int i = 0; i < width; ++i) {
for (int j = height - 1; j >= 0; --j) {
dst_y[index++] = src_y[j * width + i];
}
}
// 第二步我们只转UV
int uv_index = 0;
for (int i = 0; i < width / 2; i++) {
for (int j = height / 2 - 1; j >= 0; j--)
{
dst_u[uv_index] = src_u[width / 2 * j + i];
dst_v[uv_index] = src_v[width / 2 * j + i];
uv_index++;
}
}
}
}
顺时针旋转90度效果

原图

顺时针旋转90°
I420顺时针方向旋转180度
旋转180度概述
我们以I420原图为例,I420顺时针方向旋转180度为例,说明旋转180原理;顺时针方向旋转180度,则宽和高不发生改变,还是原来的4x8;Y[0]的位置被Y[31]所替代,U[0]的位置被U[7]所替代,V[0]的位置被V[7]所替代,以此类推;最终形成图I420Rotate180的效果。
I420Rotate180
I420 SRC对应的内存摆放位置如下:

I420Rotate180对应的内存摆放位置如下:

可以得出如下公式:
I420Rotate180_Y[i,j] = SRC_Y[ i,w - j];
I420Rotate180_U[i,j] = SRC_U[i,W/2 - j];
I420Rotate180_V[i,j] = SRC_V[i,W/2 - j];
顺时针旋转180度代码
void RotateI420(uint8_t* src_y, uint8_t* src_u, uint8_t* src_v,
uint8_t* dst_y, uint8_t* dst_u, uint8_t* dst_v,
uint32_t width, uint32_t height, int degree)
{
if (degree == kRotate180) {
// 第一步我们只转Y
// Y旋转180度
int index = 0;
for (int i = width * height-1; i >= 0 ; --i) {
dst_y[index++] = src_y[i];
}
// 第一步我们只转UV
// UV旋转180度
int uv_index = 0;
for (int i = width / 2 * height / 2; i >= 0; i--) {
dst_u[uv_index] = src_u[i];
dst_v[uv_index] = src_v[i];
uv_index++;
}
}
}
顺时针旋转180度效果

原图

I420顺时针方向旋转270度
旋转180度概述
我们以上图为例,I420顺时针方向旋转270度为例,说明I420顺时针方向旋转270原理;I420顺时针方向旋转270度,则宽和高互换,由原来4x8变为8x4;Y[0]的位置被Y[7]所替代,U[0]的位置被U[3]所替代,V[0]的位置被V[3]所替代,形成I420Rotate270[0],以此类推;最终形成图I420Rotate270的效果。

I420Rotate270
I420 SRC对应的内存摆放位置如下:

I420Rotate270对应的内存摆放位置如下:

可以得出如下公式:
I420Rotate270_Y[i,j] = SRC_Y[ i * w,j];
I420Rotate270_U[i,j] = SRC_U[i * W/2, j];
I420Rotate270_V[i,j] = SRC_V[i * W/2 , j];
顺时针旋转270度代码
void RotateI420(uint8_t* src_y, uint8_t* src_u, uint8_t* src_v,
uint8_t* dst_y, uint8_t* dst_u, uint8_t* dst_v,
uint32_t width, uint32_t height, int degree)
{
if (degree == kRotate270)
{
// 第一步我们只转Y
// 旋转270度
int index = 0;
for (int i = width-1; i >= 0; --i) {
for (int j = 0; j < height; ++j) {
dst_y[index++] = src_y[j * width+i];
}
}
// 第一步我们只转UV
// 旋转270度
int uv_index = 0;
for (int i = width / 2-1; i >= 0; i--) {
for (int j = 0; j< height / 2; j++)
{
dst_u[uv_index] = src_u[width / 2 * j+i];
dst_v[uv_index] = src_v[width / 2 * j+ i];
uv_index++;
}
}
}
}
顺时针旋转270度效果

原图

I420Rotate270
I420左右镜像翻转
我们以I420原图为基础,进行左右镜像翻转为例,说明左右镜像翻转原理;镜像翻转则宽和高不发生改变,还是原来的4x8;Y[0]的位置被Y[7]所替代,U[0]的位置被U[3]所替代,V[0]的位置被V[3]所替代,以此类推;最终形成图I420RotateMirror的效果。

I420RotateMirror
I420 SRC对应的内存摆放位置如下:

I420RotateMirror对应的内存摆放位置如下:

可以得出如下公式:
I420RotateMirror_Y[i,j] = SRC_Y[ i , w-j];
I420RotateMirror_U[i,j] = SRC_U[i , W/2- j];
I420RotateMirror_V[i,j] = SRC_V[i , W/2 - j];
顺时针镜像翻转度代码
void RotateI420(uint8_t* src_y, uint8_t* src_u, uint8_t* src_v,
uint8_t* dst_y, uint8_t* dst_u, uint8_t* dst_v,
uint32_t width, uint32_t height, int degree)
{
if (degree == kRotate90) {
// 第一步我们只转Y
int index = 0;
for (int i = 0; i < width; ++i) {
for (int j = height - 1; j >= 0; --j) {
dst_y[index++] = src_y[j * width + i];
}
}
int uv_index = 0;
for (int i = 0; i < width / 2; i++) {
for (int j = height / 2 - 1; j >= 0; j--)
{
dst_u[uv_index] = src_u[width / 2 * j + i];
dst_v[uv_index] = src_v[width / 2 * j + i];
uv_index++;
}
}
}
}
左右镜像翻转效果

原图


被折叠的 条评论
为什么被折叠?



