yuv2rgb.c

来自「实现在linux下的mpeg4编解码」· C语言 代码 · 共 552 行

C
552
字号
/************************************************************************** *                                                                        * * This code has been developed by John Funnell. This software is an      * * implementation of a part of one or more MPEG-4 Video tools as          * * specified in ISO/IEC 14496-2 standard.  Those intending to use this    * * software module in hardware or software products are advised that its  * * use may infringe existing patents or copyrights, and any such use      * * would be at such party's own risk.  The original developer of this     * * software module and his/her company, and subsequent editors and their  * * companies (including Project Mayo), will have no liability for use of  * * this software or modifications or derivatives thereof.                 * *                                                                        * * Project Mayo gives users of the Codec a license to this software       * * module or modifications thereof for use in hardware or software        * * products claiming conformance to the MPEG-4 Video Standard as          * * described in the Open DivX license.                                    * *                                                                        * * The complete Open DivX license can be found at                         * * http://www.projectmayo.com/opendivx/license.php                        * *                                                                        * **************************************************************************//***  Copyright (C) 2001 - Project Mayo * * John Funnell  * Andrea Graziani * * DivX Advanced Research Center <darc@projectmayo.com>***/// yuv2rgb.c //#include <memory.h>#include "portab.h"#include "yuv2rgb.h"/** ***/void (*convert_yuv)(unsigned char *puc_y, int stride_y,	unsigned char *puc_u, unsigned char *puc_v, int stride_uv,	unsigned char *bmp, int width_y, int height_y,	unsigned int stride_out);/** ***//***  /  2568      0   3343  \               |   2568  -0c92  -1a1e   | / 65536 * 8   \  2568   40cf      0  /                  Y -= 16;    U -= 128;    V -= 128;    R = (0x2568*Y + 0x0000*V + 0x3343*U) / 0x2000;    G = (0x2568*Y - 0x0c92*V - 0x1a1e*U) / 0x2000;    B = (0x2568*Y + 0x40cf*V + 0x0000*U) / 0x2000;    R = R>255 ? 255 : R;    R = R<0   ?   0 : R;    G = G>255 ? 255 : G;    G = G<0   ?   0 : G;    B = B>255 ? 255 : B;    B = B<0   ?   0 : B;***/#define _S(a)		(a)>255 ? 255 : (a)<0 ? 0 : (a)#define _R(y,u,v) (0x2568*(y)  			       + 0x3343*(u)) /0x2000#define _G(y,u,v) (0x2568*(y) - 0x0c92*(v) - 0x1a1e*(u)) /0x2000#define _B(y,u,v) (0x2568*(y) + 0x40cf*(v))					     /0x2000struct lookuptable{    int32_t m_plY[256];    int32_t m_plRV[256];    int32_t m_plGV[256];    int32_t m_plGU[256];    int32_t m_plBU[256];};static struct lookuptable lut;void init_yuv2rgb(){    int i;    for(i=0; i<256; i++)    {	if(i>=16)	    if(i>240)		lut.m_plY[i]=lut.m_plY[240];	    else		lut.m_plY[i]=298*(i-16);	else	    lut.m_plY[i]=0;	if((i>=16) && (i<=240))	{	    lut.m_plRV[i]=408*(i-128);	    lut.m_plGV[i]=-208*(i-128);	    lut.m_plGU[i]=-100*(i-128);	    lut.m_plBU[i]=517*(i-128);	}	else if(i<16)	{	    lut.m_plRV[i]=408*(16-128);	    lut.m_plGV[i]=-208*(16-128);	    lut.m_plGU[i]=-100*(16-128);	    lut.m_plBU[i]=517*(16-128);	}	else	{	    lut.m_plRV[i]=lut.m_plRV[240];	    lut.m_plGV[i]=lut.m_plGV[240];	    lut.m_plGU[i]=lut.m_plGU[240];	    lut.m_plBU[i]=lut.m_plBU[240];	}    }}/* all stride values are in _pixels_ */void yuv2rgb_32(uint8_t *puc_y, int stride_y,                 uint8_t *puc_u, uint8_t *puc_v, int stride_uv,                 uint8_t *puc_out, int width_y, int height_y,								unsigned int _stride_out) {	int x, y;	int stride_diff = 4 * (_stride_out - width_y);	if (height_y < 0) {		/* we are flipping our output upside-down */		height_y  = -height_y;		puc_y     += (height_y   - 1) * stride_y ;		puc_u     += (height_y/2 - 1) * stride_uv;		puc_v     += (height_y/2 - 1) * stride_uv;		stride_y  = -stride_y;		stride_uv = -stride_uv;	}	for (y=0; y<height_y; y++) 	{		for (x=0; x<width_y; x++)		{			signed int _r,_g,_b; 			signed int r, g, b;			signed int y, u, v;			y = puc_y[x] - 16;			u = puc_u[x>>1] - 128;			v = puc_v[x>>1] - 128;			_r = _R(y,u,v);			_g = _G(y,u,v);			_b = _B(y,u,v);			r = _S(_r);			g = _S(_g);			b = _S(_b);			puc_out[0] = r;			puc_out[1] = g;			puc_out[2] = b;			puc_out[3] = 0;			puc_out+=4;		}		puc_y   += stride_y;		if (y%2) {			puc_u   += stride_uv;			puc_v   += stride_uv;		}		puc_out += stride_diff;	}}/***/// This be done more efficiently // ( we spend almost as much time only in here// as DivX 3.11 spends on all decoding )void yuv2rgb_24(uint8_t *puc_y, int stride_y,                 uint8_t *puc_u, uint8_t *puc_v, int stride_uv,                 uint8_t *puc_out, int width_y, int height_y,								unsigned int _stride_out) {	int x, y;	int stride_diff = 6*_stride_out - 3*width_y;	if (height_y < 0) {		/* we are flipping our output upside-down */		height_y  = -height_y;		puc_y     += (height_y   - 1) * stride_y ;		puc_u     += (height_y/2 - 1) * stride_uv;		puc_v     += (height_y/2 - 1) * stride_uv;		stride_y  = -stride_y;		stride_uv = -stride_uv;	}	for (y=0; y<height_y; y+=2) 	{		uint8_t* pY=puc_y;		uint8_t* pY1=puc_y+stride_y;		uint8_t* pU=puc_u;		uint8_t* pV=puc_v;		uint8_t* pOut2=puc_out+3*_stride_out;		for (x=0; x<width_y; x+=2)		{			int R, G, B;			int Y;			unsigned int tmp;			R=lut.m_plRV[*pU];			G=lut.m_plGV[*pU];			pU++;			G+=lut.m_plGU[*pV];			B=lut.m_plBU[*pV];			pV++;#define PUT_COMPONENT(p,v,i) 	\    tmp=(unsigned int)(v); 	\    if(tmp < 0x10000) 		\	p[i]=tmp>>8; 		\    else			\	p[i]=(tmp >> 24) ^ 0xff; 			Y=lut.m_plY[*pY];			pY++;			PUT_COMPONENT(puc_out, R+Y, 0);			PUT_COMPONENT(puc_out, G+Y, 1);			PUT_COMPONENT(puc_out, B+Y, 2);			Y=lut.m_plY[*pY];			pY++;			PUT_COMPONENT(puc_out, R+Y, 3);			PUT_COMPONENT(puc_out, G+Y, 4);			PUT_COMPONENT(puc_out, B+Y, 5);			Y=lut.m_plY[*pY1];			pY1++;			PUT_COMPONENT(pOut2, R+Y, 0);			PUT_COMPONENT(pOut2, G+Y, 1);			PUT_COMPONENT(pOut2, B+Y, 2);			Y=lut.m_plY[*pY1];			pY1++;			PUT_COMPONENT(pOut2, R+Y, 3);			PUT_COMPONENT(pOut2, G+Y, 4);			PUT_COMPONENT(pOut2, B+Y, 5);			puc_out+=6;			pOut2+=6;		}		puc_y   += 2*stride_y;		puc_u   += stride_uv;		puc_v   += stride_uv;		puc_out += stride_diff;	}}/***/#define _S(a)		(a)>255 ? 255 : (a)<0 ? 0 : (a)#define _R(y,u,v) (0x2568*(y)  			       + 0x3343*(u)) /0x2000#define _G(y,u,v) (0x2568*(y) - 0x0c92*(v) - 0x1a1e*(u)) /0x2000#define _B(y,u,v) (0x2568*(y) + 0x40cf*(v))					     /0x2000#define _mR	0x7c00#define _mG 0x03e0#define _mB 0x001f#define _Ps555(r,g,b) (((r) << 7) & _mR) | (((g) << 2) & _mG) | (((b) >> 3) & _mB)#define _Ps565(r,g,b) ( ((r & 0xF8) >> 3) | (((g & 0xF8) << 3)) | (((b & 0xF8) << 8)) )void yuv2rgb_555(uint8_t *puc_y, int stride_y,                 uint8_t *puc_u, uint8_t *puc_v, int stride_uv,                 uint8_t *puc_out, int width_y, int height_y,								unsigned int _stride_out) {	int x, y;	unsigned short *pus_out;	int stride_diff = _stride_out - width_y; // expressed in short	if (height_y < 0) {		/* we are flipping our output upside-down */		height_y  = -height_y;		puc_y     += (height_y   - 1) * stride_y ;		puc_u     += (height_y/2 - 1) * stride_uv;		puc_v     += (height_y/2 - 1) * stride_uv;		stride_y  = -stride_y;		stride_uv = -stride_uv;	}	pus_out = (unsigned short *) puc_out;	for (y=0; y<height_y; y++) 	{		for (x=0; x<width_y; x++)		{			signed int _r,_g,_b; 			signed int r, g, b;			signed int y, u, v;			y = puc_y[x] - 16;			u = puc_u[x>>1] - 128;			v = puc_v[x>>1] - 128;			_r = _R(y,u,v);			_g = _G(y,u,v);			_b = _B(y,u,v);			r = _S(_r);			g = _S(_g);			b = _S(_b);			pus_out[0] = _Ps555(b,g,r);			pus_out++;		}		puc_y   += stride_y;		if (y%2) {			puc_u   += stride_uv;			puc_v   += stride_uv;		}		pus_out += stride_diff;	}}/***/void yuv2rgb_565(uint8_t *puc_y, int stride_y,                 uint8_t *puc_u, uint8_t *puc_v, int stride_uv,                 uint8_t *puc_out, int width_y, int height_y,								unsigned int _stride_out) {	int x, y;	unsigned short *pus_out;	int stride_diff = _stride_out - width_y; // expressed in short	if (height_y < 0) {		/* we are flipping our output upside-down */		height_y  = -height_y;		puc_y     += (height_y   - 1) * stride_y ;		puc_u     += (height_y/2 - 1) * stride_uv;		puc_v     += (height_y/2 - 1) * stride_uv;		stride_y  = -stride_y;		stride_uv = -stride_uv;	}	pus_out = (unsigned short *) puc_out;	for (y=0; y<height_y; y++) 	{		for (x=0; x<width_y; x++)		{			signed int _r,_g,_b; 			signed int r, g, b;			signed int y, u, v;			y = puc_y[x] - 16;			u = puc_u[x>>1] - 128;			v = puc_v[x>>1] - 128;			_r = _R(y,u,v);			_g = _G(y,u,v);			_b = _B(y,u,v);			r = _S(_r);			g = _S(_g);			b = _S(_b);			pus_out[0] = (unsigned short) _Ps565(r,g,b);			pus_out++;		}		puc_y   += stride_y;		if (y%2) {			puc_u   += stride_uv;			puc_v   += stride_uv;		}		pus_out += stride_diff;	}}/***/// conversion from 4:2:0 to yuv2, 16 bit yuv output//void yuy2_out(uint8_t *puc_y, int stride_y,   uint8_t *puc_u, uint8_t *puc_v, int stride_uv,   uint8_t *puc_out, int width_y, int height_y,	unsigned int stride_out) { 	int y;	uint8_t* puc_out2;	unsigned int stride_diff = 4 * stride_out - 2 * width_y; // expressed in bytes	if (height_y < 0) {		/* we are flipping our output upside-down */		height_y  = -height_y;		puc_y     += (height_y   - 1) * stride_y ;		puc_u     += (height_y/2 - 1) * stride_uv;		puc_v     += (height_y/2 - 1) * stride_uv;		stride_y  = -stride_y;		stride_uv = -stride_uv;	}	puc_out2 = puc_out + 2 * stride_out;	for (y=height_y/2; y; y--) {		register uint8_t *py, *py2, *pu, *pv;		register int x;		uint32_t tmp;		py = puc_y;		py2 = puc_y + stride_y;		pu = puc_u;		pv = puc_v;		for (x=width_y/2; x; x--) {			tmp = *(py++);			tmp |= *(pu++) << 8;			tmp |= *(py++) << 16;			tmp |= *(pv++) << 24;			*(uint32_t*)puc_out=tmp;			puc_out += 4;			tmp &= 0xFF00FF00;			tmp |= *(py2++);			tmp |= *(py2++) << 16;			*(uint32_t*)puc_out2=tmp;			puc_out2 += 4;		}		puc_y += 2*stride_y;		puc_u += stride_uv;		puc_v += stride_uv;		puc_out += stride_diff;		puc_out2 += stride_diff;	}}/*** YUV 4:2:0 -> UYVY ***/void uyvy_out(uint8_t *puc_y, int stride_y,   uint8_t *puc_u, uint8_t *puc_v, int stride_uv,   uint8_t *puc_out, int width_y, int height_y,	unsigned int stride_out) { 	int y;	uint8_t* puc_out2;	unsigned int stride_diff = 4 * stride_out - 2 * width_y; // expressed in bytes	if (height_y < 0) {		/* we are flipping our output upside-down */		height_y  = -height_y;		puc_y     += (height_y   - 1) * stride_y ;		puc_u     += (height_y/2 - 1) * stride_uv;		puc_v     += (height_y/2 - 1) * stride_uv;		stride_y  = -stride_y;		stride_uv = -stride_uv;	}	puc_out2 = puc_out + 2 * stride_out;	for (y=height_y/2; y; y--) {		register uint8_t *py, *py2, *pu, *pv;		register int x;		uint32_t tmp;		py = puc_y;		py2 = puc_y + stride_y;		pu = puc_u;		pv = puc_v;		for (x=width_y/2; x; x--) {			tmp = *(pu++);			tmp |= *(py++) << 8;			tmp |= *(pv++) << 16;			tmp |= *(py++) << 24;			*(uint32_t*)puc_out=tmp;			puc_out += 4;			tmp &= 0x00FF00FF;			tmp |= *(py2++) << 8;			tmp |= *(py2++) << 24;			*(uint32_t*)puc_out2=tmp;			puc_out2 += 4;		}		puc_y += 2*stride_y;		puc_u += stride_uv;		puc_v += stride_uv;		puc_out += stride_diff;		puc_out2 += stride_diff;	}}// conversion from 4:2:0 to yv2, 12 bit (just remove the edges)//void yuv12_out(uint8_t *puc_y, int stride_y,   uint8_t *puc_u, uint8_t *puc_v, int stride_uv,   uint8_t *puc_out, int width_y, int height_y,	unsigned int stride_out) { 	int i;	unsigned char * pauc_out[3];	if (height_y < 0) {		// we are flipping our output upside-down		height_y = -height_y;		puc_y     += (height_y   - 1) * stride_y ;		puc_u     += (height_y/2 - 1) * stride_uv;		puc_v     += (height_y/2 - 1) * stride_uv;		stride_y  = -stride_y;		stride_uv = -stride_uv;	}	pauc_out[0] = puc_out;	pauc_out[1] = puc_out + stride_out * height_y;	pauc_out[2] = puc_out + stride_out * height_y * 5 / 4;	for (i=0; i<height_y; i++) {				memcpy(pauc_out[0], puc_y, width_y);		pauc_out[0] += stride_out;		puc_y += stride_y;	}	for (i=0; i<height_y/2; i++) {				memcpy(pauc_out[2], puc_u, width_y/2); // U and V buffer must be inverted		memcpy(pauc_out[1], puc_v, width_y/2);		pauc_out[1] += stride_out/2;		pauc_out[2] += stride_out/2;		puc_u += stride_uv;		puc_v += stride_uv;	}}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?