YUV420P旋转算法

人走茶凉 提交于 2020-01-13 19:23:28

        本次整理了顺时针旋转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;
}

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!