本次整理了順時針旋轉90度、逆時針旋轉90度、逆時針旋轉180度、逆時針旋轉180度再水平翻轉、水平翻轉。如有有需要請留言,我會再添加其他旋轉算法。
算法可以直接看下面的代碼,如果需要代碼中的yuv420p.yuv文件及vs工程可以到這裏下載:https://pan.baidu.com/s/1z2S5o-Oqbf-_oUyFYGz0zg
// Yuv420pRotate.cpp : 定義控制檯應用程序的入口點。
//
#include "stdafx.h"
// clockwise 順時針
// contrarotate 逆時針旋轉
// flip horizontal 鏡像翻轉/水平翻轉
/**
* 順時針旋轉90。
* 取元素:從左下方第一個點開始,從下往上,從左往右取點;
* 放元素:從左上方第一個位置開始放,從左往右,從上往下;把每一列轉換成每一行。
*
* @param yuvFileaName 一幀YUV420P格式的文件
* @param width 圖像的寬
* @param height 圖像的高
*
* @return 空
*/
void clockwiseRotate90(const char* yuvFileaName, int width, int height){
FILE* fp = NULL;
fopen_s(&fp, yuvFileaName, "rb");
unsigned char* yuvbuf = new unsigned char[width*height * 3 / 2];
fread(yuvbuf, width*height * 3 / 2, 1, fp);
fclose(fp);
int idx = 0;
//Y
unsigned char* dstbuf = new unsigned char[width*height * 3 / 2];
for (int i = 0; i <= width - 1; i++){
for (int j = height - 1; j >= 0; j--){
dstbuf[idx++] = *(yuvbuf + (j*width + i));
}
}
//U
unsigned char* uheader = yuvbuf + width*height;
int hw = width / 2;
int hh = height / 2;
for (int i = 0; i <= hw - 1; i++){
for (int j = hh - 1; j >= 0; j--){
dstbuf[idx++] = *(uheader + (j*hw + i));
}
}
//V
unsigned char* vheader = uheader + width*height / 4;
for (int i = 0; i <= hw - 1; i++){
for (int j = hh - 1; j >= 0; j--){
dstbuf[idx++] = *(vheader + (j*hw + i));
}
}
FILE* fpout = NULL;
fopen_s(&fpout, "clockwiseRotate90.yuv", "wb");
fwrite(dstbuf, width*height * 3 / 2, 1, fpout);
fclose(fpout);
delete[] yuvbuf;
delete[] dstbuf;
}
/**
* 逆時針旋轉90。
* 取元素:從右上方第一個點開始,從上往下,從右往左取點;
* 放元素:從左上方第一個位置開始放,從左往右,從上往下;把每一列轉換成每一行。
*
* @param yuvFileaName 一幀YUV420P格式的文件
* @param width 圖像的寬
* @param height 圖像的高
*
* @return 空
*/
void contrarotate90(const char* yuvFileaName, int width, int height)
{
int i, j, k, p;
FILE* fp = NULL;
fopen_s(&fp, yuvFileaName, "rb");
unsigned char* yuvbuf = new unsigned char[width*height * 3 / 2];
fread(yuvbuf, width*height * 3 / 2, 1, fp);
fclose(fp);
unsigned char* dstbuf = new unsigned char[width*height * 3 / 2];
char* dest = (char*)dstbuf;
char* src = (char*)yuvbuf;
// rotate Y
for (j = 0; j < width; j++){
for (i = 1; i <= height; i++){
*dest++ = *(src + i*width - j);
}
}
// rotate U
char *src_u = src + width*height;
for (p = 0; p < width / 2; p++){
for (k = 1; k <= height / 2; k++){
*dest++ = *(src_u + k*width / 2 - p);
}
}
// rotate V
char *src_v = src + width*height * 5 / 4;
for (p = 0; p < width / 2; p++){
for (k = 1; k <= height / 2; k++){
*dest++ = *(src_v + k*width / 2 - p);
}
}
FILE* fpout = NULL;
fopen_s(&fpout, "contrarotate90.yuv", "wb");
fwrite(dstbuf, width*height * 3 / 2, 1, fpout);
fclose(fpout);
delete[] yuvbuf;
delete[] dstbuf;
}
/**
* 逆時針180。
* 取元素:從右下方第一個點開始,從右往左,從下往上取點;
* 放元素:從左上方第一個位置開始放,從左往右,從上往下;
*
* @param yuvFileaName 一幀YUV420P格式的文件
* @param width 圖像的寬
* @param height 圖像的高
*
* @return 空
*/
void contrarotate180(const char* yuvFileaName, int width, int height){
FILE* fp = NULL;
fopen_s(&fp, yuvFileaName, "rb");
unsigned char* yuvbuf = new unsigned char[width*height * 3 / 2];
fread(yuvbuf, width*height * 3 / 2, 1, fp);
fclose(fp);
int idx = 0;
//Y
unsigned char* dstbuf = new unsigned char[width*height * 3 / 2];
for (int i = height - 1; i >= 0; i--){
for (int j = width - 1; j >= 0; j--){
dstbuf[idx++] = *(yuvbuf + (i*width + j));
}
}
//U
unsigned char* uheader = yuvbuf + width*height;
for (int i = height / 2 - 1; i >= 0; i--){
for (int j = width / 2 - 1; j >= 0; j--){
dstbuf[idx++] = *(uheader + (i*width / 2 + j));
}
}
unsigned char* vheader = uheader + width*height / 4;
//V
for (int i = height / 2 - 1; i >= 0; i--){
for (int j = width / 2 - 1; j >= 0; j--){
dstbuf[idx++] = *(vheader + (i*width / 2 + j));
}
}
FILE* fpout = NULL;
fopen_s(&fpout, "contrarotate180.yuv", "wb");
fwrite(dstbuf, width*height * 3 / 2, 1, fpout);
fclose(fpout);
delete[] yuvbuf;
delete[] dstbuf;
}
/**
* 鏡像翻轉/水平翻轉
* 取元素:將右上角的點作爲第一個點,從右往左,從上往下取點;
* 放元素:從左上方第一個位置開始放,從左往右,從上往下;
*
* @param yuvFileaName 一幀YUV420P格式的文件
* @param width 圖像的寬
* @param height 圖像的高
*
* @return 空
*/
void flipHorizontal(const char* yuvFileaName, int width, int height)
{
FILE* fp = NULL;
fopen_s(&fp, yuvFileaName, "rb");
unsigned char* yuvbuf = new unsigned char[width*height * 3 / 2];
fread(yuvbuf, width*height * 3 / 2, 1, fp);
fclose(fp);
int idx = 0;
//Y
unsigned char* dstbuf = new unsigned char[width*height * 3 / 2];
for (int i = 0; i < height; i++){
for (int j = width - 1; j >= 0; j--){
dstbuf[idx++] = *(yuvbuf + (i*width + j));
}
}
//U
unsigned char* uheader = yuvbuf + width*height;
for (int i = 0; i < height / 2; i++){
for (int j = width / 2 - 1; j >= 0; j--){
dstbuf[idx++] = *(uheader + (i*width / 2 + j));
}
}
//V
unsigned char* vheader = uheader + width*height / 4;
for (int i = 0; i < height / 2; i++){
for (int j = width / 2 - 1; j >= 0; j--){
dstbuf[idx++] = *(vheader + (i*width / 2 + j));
}
}
FILE* fpout = NULL;
fopen_s(&fpout, "flipHorizontal.yuv", "wb");
fwrite(dstbuf, width*height * 3 / 2, 1, fpout);
fclose(fpout);
delete[] yuvbuf;
delete[] dstbuf;
}
/**
* 逆時針旋轉180後,再水平翻轉/鏡像。
* 取元素:從左下方第一個點開始,從左往右,從下往上取點;
* 放元素:從左上方第一個位置開始放,從左往右,從上往下;
*
* @param yuvFileaName 一幀YUV420P格式的文件
* @param width 圖像的寬
* @param height 圖像的高
*
* @return 空
*/
void contrarotate180AndFlipHorizontal(const char* yuvFileaName, int width, int height){
FILE* fp = NULL;
fopen_s(&fp, yuvFileaName, "rb");
unsigned char* yuvbuf = new unsigned char[width*height * 3 / 2];
fread(yuvbuf, width*height * 3 / 2, 1, fp);
fclose(fp);
int idx = 0;
//Y 寬
unsigned char* dstbuf = new unsigned char[width*height * 3 / 2];
for (int i = height - 1; i >= 0; i--){
for (int j = 0; j <= width - 1; j++){
dstbuf[idx++] = *(yuvbuf + (i*width + j));
}
}
//U
unsigned char* uheader = yuvbuf + width*height;
for (int i = height / 2 - 1; i >= 0; i--){
for (int j = 0; j <= width / 2 - 1; j++){
dstbuf[idx++] = *(uheader + (i*width / 2 + j));
}
}
//V
unsigned char* vheader = uheader + width*height / 4;
for (int i = height / 2 - 1; i >= 0; i--){
for (int j = 0; j <= width / 2 - 1; j++){
dstbuf[idx++] = *(vheader + (i*width / 2 + j));
}
}
FILE* fpout = NULL;
fopen_s(&fpout, "contrarotate180AndFlipHorizontal.yuv", "wb");
fwrite(dstbuf, width*height * 3 / 2, 1, fpout);
fclose(fpout);
delete[] yuvbuf;
delete[] dstbuf;
}
int _tmain(int argc, _TCHAR* argv[])
{
const char* yuvFileaName = "yuv420p.yuv";
int w = 160;
int h = 128;
clockwiseRotate90(yuvFileaName, w, h);
contrarotate90(yuvFileaName, w, h);
contrarotate180(yuvFileaName, w, h);
flipHorizontal(yuvFileaName, w, h);
contrarotate180AndFlipHorizontal(yuvFileaName, w, h);
return 0;
}