天天看點

YUV422 to RGB565 Convert

YUV是視訊系統中常用的顔色空間,而顯示通常是按照RGB格式進行輸出顯示的,要使YUV資料格式能夠在顯示屏上顯示,需要将YUV格式轉換為RGB格式,下面給出了YUV422到RGB565顔色空間轉換的簡單描述和程式實作。

1. 轉換公式

YUV轉換為RGB的公式如下:

R = Y + 1.402*(V-128);

G = Y - 0.34414*(U-128) - 0.71414*(V-128); 

B = Y + 1.772*(U-128); 

為了便于在計算機系統中進行處理,我們對公式進行一下簡化:

R = Y + 1.402*(V-128) = y + v + 0.402*v = y + v + ((103 * v) >> 8);

G = Y - 0.34414*(U-128) - 0.71414*(V-128) = y - ((u * 88) >> 8) - ((v * 183) >> 8);

B = Y + 1.772*(U-128) = y + u + (u * 198) >> 8;

即:

R = y + v + ((103 * v) >> 8);

G = y - ((u * 88) >> 8) - ((v * 183) >> 8);

B = y + u + (u * 198) >> 8;

2. 程式實作

根據上面公式可以換算得到R、G、B三個分量數值,得到的數值需要經過範圍轉換以免越界導緻色彩失真。 程式實作如下:

#define RANGE_LIMIT(x) (x > 255 ? 255 : (x < 0 ? 0 : x))

void YUV422ToRGB565(const void* inbuf, void* outbuf, int width, int height)
{
	int rows, cols;
	int y, u, v, r, g, b;
	unsigned char *yuv_buf;
	unsigned short *rgb_buf;
	int y_pos,u_pos,v_pos;

	yuv_buf = (unsigned char *)inbuf;
	rgb_buf = (unsigned short *)outbuf;

	y_pos = 0;
	u_pos = 1;
	v_pos = 3;

	for (rows = 0; rows < height; rows++) {
		for (cols = 0; cols < width; cols++) {
			y = yuv_buf[y_pos];
			u = yuv_buf[u_pos] - 128;
			v = yuv_buf[v_pos] - 128;

			// R = Y + 1.402*(V-128)
			// G = Y - 0.34414*(U-128)
			// B = Y + 1.772*(U-128)
			r = RANGE_LIMIT(y + v + ((v * 103) >> 8));
			g = RANGE_LIMIT(y - ((u * 88) >> 8) - ((v * 183) >> 8));
			b = RANGE_LIMIT(y + u + ((u * 198) >> 8));

			*rgb_buf++ = (((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3));

			y_pos += 2;

			if (cols & 0x01) {
				u_pos += 4;
				v_pos += 4;
			}
		}
	}
}

           

以上是YUV422(YUYV)轉為RGB565的實作,對于其他格式的YUV格式,如YUV420, YUV422P等格式的轉換,其實作都類似,主要的差別在于y, u, v分量的提取上,将程式做簡單的修改就能夠實作對應格式的YUV資料轉換為RGB565資料格式。

繼續閱讀