YUV420P旋轉算法

        本次整理了順時針旋轉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;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章