ARM平台YUV转RGB888

ARM平台YUV转RGB888(转)

前段时间,公司有个嵌入式的项目,我做的其中有一项是yuv视频到rgb888图像的转换。我主要是参照一位牛人的博客做的: http://blog.csdn.net/housisong/archive/2007/10/31/1859084.aspx

      YUV422p To RGB888 C语言版本接口说明:

  1. /****************************************YUV422P_To_RGB24.c**************************/  
  2. //模块功能:将YUV422_PLANAR图像数据转换成RGB24格式   
  3. typedef unsigned char BYTE// [0..255]   
  4. /* 
  5.  * 接口说明: 
  6.  * 功能:构建查询表,转换模块运行前必须进行的初始化操作 
  7.  */  
  8. void YUV422P_To_RGB24_init();  
  9. /* 
  10.  *接口说明: 
  11.  *功能:将YUV422P图像数据转换成RGB24格式 
  12.  *参数: 
  13.  *            pY: YUV422P图像数据Y的起始指针 
  14.  *            pU: YUV422P图像数据U的起始指针 
  15.  *            pV: YUV422P图像数据V的起始指针 
  16.  *        DstPic: 转换成的RGB24图像数据的起始指针 
  17.  *         width: 图像宽度 
  18.  *        height: 图像高度 
  19.  *返回值:成功返回0,失败返回-1 
  20.  *注意:DstPic所指向的缓冲区必须事先分配好,其大小应该为 width*height*3 
  21.  */  
  22. int YUV422P_To_RGB24(BYTE* pY, BYTE* pU, BYTE* pV, BYTE* DstPic, int width, int height);  
 

 

      实现:

  1. //使用整数运算(定点数运算)来代替浮点运算   
  2. const int csY_coeff_16 = 1.164383 * (1 << 16);  
  3. const int csU_blue_16 = 2.017232 * (1 << 16);  
  4. const int csU_green_16 = (-0.391762) * (1 << 16);  
  5. const int csV_green_16 = (-0.812968) * (1 << 16);  
  6. const int csV_red_16 = 1.596027 * (1 << 16);  
  7. //颜色查表   
  8. static BYTE _color_table[256 * 3];  
  9. static const BYTE* color_table = &_color_table[256];  
  10. //查表   
  11. static int Ym_tableEx[256];  
  12. static int Um_blue_tableEx[256];  
  13. static int Um_green_tableEx[256];  
  14. static int Vm_green_tableEx[256];  
  15. static int Vm_red_tableEx[256];  
  16. //颜色饱和函数   
  17. inline long border_color(long color) {  
  18.     if (color > 255)  
  19.         return 255;  
  20.     else if (color < 0)  
  21.         return 0;  
  22.     else  
  23.         return color;  
  24. }  
  25. //采用查找表进行计算时,必须运行的初始化函数   
  26. void YUV422P_To_RGB24_init() {  
  27.     int i;  
  28.     for (i = 0; i < 256 * 3; ++i)  
  29.         _color_table[i] = border_color(i - 256);  
  30.     for (i = 0; i < 256; ++i) {  
  31.         Ym_tableEx[i] = (csY_coeff_16 * (i - 16)) >> 16;  
  32.         Um_blue_tableEx[i] = (csU_blue_16 * (i - 128)) >> 16;  
  33.         Um_green_tableEx[i] = (csU_green_16 * (i - 128)) >> 16;  
  34.         Vm_green_tableEx[i] = (csV_green_16 * (i - 128)) >> 16;  
  35.         Vm_red_tableEx[i] = (csV_red_16 * (i - 128)) >> 16;  
  36.     }  
  37. }  
  38. inline void YUVToRGB24_Table(BYTE *p, const BYTE Y0, const BYTE Y1,  
  39.         const BYTE U, const BYTE V) {  
  40.     int Ye0 = Ym_tableEx[Y0];  
  41.     int Ye1 = Ym_tableEx[Y1];  
  42.     int Ue_blue = Um_blue_tableEx[U];  
  43.     int Ue_green = Um_green_tableEx[U];  
  44.     int Ve_green = Vm_green_tableEx[V];  
  45.     int Ve_red = Vm_red_tableEx[V];  
  46.     int UeVe_green = Ue_green + Ve_green;  
  47.     *p = color_table[(Ye0 + Ve_red)];  
  48.     *(p + 1) = color_table[(Ye0 + UeVe_green)];  
  49.     *(p + 2) = color_table[(Ye0 + Ue_blue)];  
  50.     *(p + 3) = color_table[(Ye1 + Ve_red)];  
  51.     *(p + 4) = color_table[(Ye1 + UeVe_green)];  
  52.     *(p + 5) = color_table[(Ye1 + Ue_blue)];  
  53. }  
  54. int YUV420P_To_RGB24(BYTE* pY, BYTE* pU, BYTE* pV, BYTE* DstPic, int width,  
  55.         int height) {  
  56.     int y, x, x_uv;  
  57.     BYTE* pDstLine = DstPic;  
  58.     if ((width % 2) != 0 || (height % 2) != 0)  
  59.         return (-1);  
  60.     for (y = 0; y < height; ++y) {  
  61.         //DECODE_PlanarYUV211_Common_line(pDstLine, pY, pU, pV,width);   
  62.         for (x = 0; x < width; x += 2) {  
  63.             x_uv = x >> 1;  
  64.             YUVToRGB24_Table(&pDstLine[x * 3], pY[x], pY[x + 1], pU[x_uv],  
  65.                     pV[x_uv]);  
  66.         }  
  67.         pDstLine += width * 3; //RGB888   
  68.         pY += width; //YUV422   
  69.         if (y % 2 == 1) {  
  70.             pU += width / 2;  
  71.             pV += width / 2;  
  72.         }  
  73.     }  
  74.     return 0;  
  75. }  
 

 

      经测试发现,在hi3512(arm 926ej-s,267MHz)平台上运行时,该yuv转rgb模块的速度不是很快,大概20帧/秒。为了提高效率,核心解码模块我采用了arm汇编,重写了YUVToRGB24_Table模块。

YUV420P_To_RGB24_asm.c代码:

  1. extern int YUVToRGB24_Assemble(unsigned char *pDstLine, unsigned char **yuv, int width);  
  2. //使用整数运算(定点数运算)来代替浮点运算   
  3. const int csY_coeff_16 = 1.164383 * (1 << 16);  
  4. const int csU_blue_16 = 2.017232 * (1 << 16);  
  5. const int csU_green_16 = (-0.391762) * (1 << 16);  
  6. const int csV_green_16 = (-0.812968) * (1 << 16);  
  7. const int csV_red_16 = 1.596027 * (1 << 16);  
  8. //查表   
  9. int  Ym_tableEx[256];  
  10. int  Um_blue_tableEx[256];  
  11. int  Um_green_tableEx[256];  
  12. int  Vm_green_tableEx[256];  
  13. int  Vm_red_tableEx[256];  
  14. //采用查找表进行计算时,必须运行的初始化函数   
  15. void YUV422P_To_RGB24_init()  
  16. {  
  17.     int i;  
  18.     for (i = 0; i < 256; ++i)  
  19.     {  
  20.         Ym_tableEx[i]=(csY_coeff_16 * (i - 16) )>>16;  
  21.             Um_blue_tableEx[i]=(csU_blue_16 * (i - 128) )>>16;  
  22.         Um_green_tableEx[i]=(csU_green_16 * (i - 128) )>>16;                    
  23.         Vm_green_tableEx[i]=(csV_green_16 * (i - 128) )>>16;  
  24.             Vm_red_tableEx[i]=(csV_red_16 * (i - 128) )>>16;  
  25.     }  
  26. }  
  27. int YUV420P_To_RGB24(BYTE* pY, BYTE* pU, BYTE* pV, BYTE* DstPic, int width, int height)  
  28. {  
  29.     int y;  
  30.     BYTE* pDstLine = DstPic;  
  31.     BYTE* yuv[3];  
  32.       
  33.     if ((width % 8)!=0)  
  34.         return(-1);  
  35.     yuv[0] = pY;  
  36.     yuv[1] = pU;  
  37.     yuv[2] = pV;  
  38.     for (y = height; y > 0; --y)  
  39.     {  
  40.         YUVToRGB24_Assemble(pDstLine, yuv, width); //decoder a line with asm function in YUVToRGB24_Assemble.s   
  41.         pDstLine += width * 3;      //RGB888   
  42.         yuv[0] += width;        //YUV422   
  43.         if(y % 2 == 1) {  
  44.             yuv[1] += width >> 1;  
  45.             yuv[2] += width >> 1;  
  46.         }  
  47.     }  
  48.     return 0;  


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值