YUV420 和RGB之间的转换的程序,YUV采样频率采用cif

YUV420 和RGB之间的转换的程序。

测试使用的cif文件:http://trace.eas.asu.edu/yuv/tempete.zip


【C/C++ code】 #include < stdio.h > #include < stdlib.h >
#define WIDTH 352
#define HEIGHT 288
// 转换矩阵
double YuvToRgb[ 3 ][ 3 ] = { 1 ,       0 1.4022 ,
                        
1 ,    - 0.3456 , - 0.7145 ,
                        
1 ,   1.771 ,       0 };

// 根据RGB三分量写BMP
int WriteBmp( int width, int height, unsigned char * R,unsigned char * G,unsigned char * B, char * BmpFileName);

// 转换函数
int Convert( char * file, int width, int height, int n)
{
   
// 变量声明
    int i = 0 ;
   
int temp = 0 ;
   
int x = 0 ;
   
int y = 0 ;
   
int fReadSize = 0 ;
   
int ImgSize = width * height;
    FILE
* fp = NULL;
    unsigned
char * yuv = NULL;
    unsigned
char * rgb = NULL;
    unsigned
char * cTemp[ 6 ];
   
char BmpFileName[ 256 ];

   
// 申请空间
    int FrameSize = ImgSize + (ImgSize >> 1 );
    yuv
= (unsigned char * )malloc(FrameSize); rgb = (unsigned char * )malloc(ImgSize * 3 );
   
// 读取指定文件中的指定帧
    if ((fp = fopen(file, " rb " )) == NULL)
       
return 0 ;
    fseek(fp, FrameSize
* (n - 1 ), SEEK_CUR);
    fReadSize
= fread(yuv, 1 , FrameSize, fp);
    fclose(fp);
   
if (fReadSize < FrameSize)
       
return 0 ;
   
// 转换指定帧       cTemp[ 0 ] = yuv;                        // y分量地址
    cTemp[ 1 ] = yuv + ImgSize;            // u分量地址
    cTemp[ 2 ] = cTemp[ 1 ] + (ImgSize >> 2 );    // v分量地址
    cTemp[ 3 ] = rgb;                        // r分量地址
    cTemp[ 4 ] = rgb + ImgSize;            // g分量地址
    cTemp[ 5 ] = cTemp[ 4 ] + ImgSize;        // b分量地址
    for (y = 0 ; y < height; y ++ )
       
for (x = 0 ; x < width; x ++ )
        {
           
// r分量
            temp = cTemp[ 0 ][y * width + x] + (cTemp[ 2 ][(y / 2 ) * (width / 2 ) + x / 2 ] - 128 ) * YuvToRgb[ 0 ][ 2 ];
            cTemp[
3 ][y * width + x] = temp < 0 ? 0 : (temp > 255 ? 255 : temp);
           
// g分量
            temp = cTemp[ 0 ][y * width + x] + (cTemp[ 1 ][(y / 2 ) * (width / 2 ) + x / 2 ] - 128 ) * YuvToRgb[ 1 ][ 1 ]
                                      
+ (cTemp[ 2 ][(y / 2 ) * (width / 2 ) + x / 2 ] - 128 ) * YuvToRgb[ 1 ][ 2 ];
            cTemp[
4 ][y * width + x] = temp < 0 ? 0 : (temp > 255 ? 255 : temp);
           
// b分量
            temp = cTemp[ 0 ][y * width + x] + (cTemp[ 1 ][(y / 2 ) * (width / 2 ) + x / 2 ] - 128 ) * YuvToRgb[ 2 ][ 1 ];
            cTemp[
5 ][y * width + x] = temp < 0 ? 0 : (temp > 255 ? 255 : temp);
        }

   
// 写到BMP文件中
    sprintf(BmpFileName, " %s%05d.bmp " , file, n);
    WriteBmp(width, height, cTemp[
3 ], cTemp[ 4 ], cTemp[ 5 ], BmpFileName);

    free(yuv);
    free(rgb);
   
return n;
}
// 入口 void main()
{
   
int i = 1 ;
//     for( i=0; i<260; i++)
        Convert( " tempete.cif " , WIDTH, HEIGHT, i); // 获取文件的第i帧
}

// 写BMP  int WriteBmp( int width, int height, unsigned char * R,unsigned char * G,unsigned char * B, char * BmpFileName)
{
   
int x = 0 ;
   
int y = 0 ;
   
int i = 0 ;
   
int j = 0 ;
    FILE
* fp;
    unsigned
char * WRGB;
    unsigned
char * WRGB_Start;
   
int yu = width * 3 % 4 ;
   
int BytePerLine = 0 ;

    yu
= yu != 0 ? 4 - yu : yu;
    BytePerLine
= width * 3 + yu;

   
if ((fp = fopen(BmpFileName, " wb " )) == NULL)
       
return 0 ;
    WRGB
= (unsigned char * )malloc(BytePerLine * height + 54 );
    memset(WRGB,
0 , BytePerLine * height + 54 );
   
   
// BMP头
    WRGB[ 0 ] = ' B ' ;
    WRGB[
1 ] = ' M ' ;
   
* ((unsigned int * )(WRGB + 2 )) = BytePerLine * height + 54 ;
   
* ((unsigned int * )(WRGB + 10 )) = 54 ;
   
* ((unsigned int * )(WRGB + 14 )) = 40 ;
   
* ((unsigned int * )(WRGB + 18 )) = width;
   
* ((unsigned int * )(WRGB + 22 )) = height;
   
* ((unsigned short * )(WRGB + 26 )) = 1 ;
   
* ((unsigned short * )(WRGB + 28 )) = 24 ;
   
* ((unsigned short * )(WRGB + 34 )) = BytePerLine * height;

    WRGB_Start
= WRGB + 54 ;

   
for (y = height - 1 ,j = 0 ; y >= 0 ; y -- ,j ++ )
    {
       
for (x = 0 ,i = 0 ; x < width; x ++ )
        {
            WRGB_Start[y
* BytePerLine + i ++ ] = B[j * width + x];
            WRGB_Start[y
* BytePerLine + i ++ ] = G[j * width + x];
            WRGB_Start[y
* BytePerLine + i ++ ] = R[j * width + x];
        }
    }

    fwrite(WRGB,
1 , BytePerLine * height + 54 , fp);
    free(WRGB);
    fclose(fp);
   
return 1 ;
}
 
 
  
  【C/C++ code:RGB2YUV420 ,存储格式为cif】 
 
 
 
 
  
  #include 
  
  <
  
  stdio.h
  
  >
  
  
#include 
  
  <
  
  stdlib.h
  
  >
  
  
#include 
  
  <
  
  string
  
  .h
  
  >
  
  


  
  //
  
  转换矩阵
  
  

  
  #define
  
   MY(a,b,c) (( a*  0.2989  + b*  0.5866  + c*  0.1145))
  
  

  
  #define
  
   MU(a,b,c) (( a*(-0.1688) + b*(-0.3312) + c*  0.5000 + 128))
  
  

  
  #define
  
   MV(a,b,c) (( a*  0.5000  + b*(-0.4184) + c*(-0.0816) + 128))
  
  

  
  //
  
  大小判断
  
  

  
  #define
  
   DY(a,b,c) (MY(a,b,c) > 255 ? 255 : (MY(a,b,c) < 0 ? 0 : MY(a,b,c)))
  
  

  
  #define
  
   DU(a,b,c) (MU(a,b,c) > 255 ? 255 : (MU(a,b,c) < 0 ? 0 : MU(a,b,c)))
  
  

  
  #define
  
   DV(a,b,c) (MV(a,b,c) > 255 ? 255 : (MV(a,b,c) < 0 ? 0 : MV(a,b,c)))
  
  

  
  //
  
  只处理352*288文件
  
  

  
  #define
  
   WIDTH 352
  
  

  
  #define
  
   HEIGHT 288
  
  


  
  //
  
  读BMP
  
  

  
  void
  
   ReadBmp(unsigned 
  
  char
  
   
  
  *
  
  RGB,FILE 
  
  *
  
  fp);


  
  //
  
  转换函数
  
  

  
  void
  
   Convert(unsigned 
  
  char
  
   
  
  *
  
  RGB, unsigned 
  
  char
  
   
  
  *
  
  YUV);


  
  //
  
  入口
  
  

  
  int
  
   main()
{
    
  
  int
  
   i
  
  =
  
  1
  
  ;
    
  
  char
  
   file[
  
  255
  
  ];
    FILE 
  
  *
  
  fp;
    FILE 
  
  *
  
  fp2;
    unsigned 
  
  char
  
   
  
  *
  
  YUV 
  
  =
  
   NULL;
    unsigned 
  
  char
  
   
  
  *
  
  RGB 
  
  =
  
   NULL;
    unsigned 
  
  int
  
   imgSize 
  
  =
  
   WIDTH
  
  *
  
  HEIGHT;

    
  
  if
  
  ((fp2 
  
  =
  
   fopen(
  
  "
  
  CIF文件
  
  "
  
  , 
  
  "
  
  wb
  
  "
  
  )) 
  
  ==
  
   NULL)
    {
        
  
  return
  
   
  
  0
  
  ;
    }

    RGB 
  
  =
  
   (unsigned 
  
  char
  
  *
  
  )malloc(imgSize
  
  *
  
  6
  
  );
    YUV 
  
  =
  
   (unsigned 
  
  char
  
  *
  
  )malloc(imgSize 
  
  +
  
   (imgSize
  
  >>
  
  1
  
  ));
   
    
  
  for
  
  (i
  
  =
  
  1
  
  ; i
  
  <=
  
  260
  
  ; i
  
  ++
  
  )
    {
        sprintf(file, 
  
  "
  
  RGB_%05d.bmp
  
  "
  
  , i);
  
  //
  
  生成文件名
  
  

  
          
  
  if
  
  ((fp 
  
  =
  
   fopen(file, 
  
  "
  
  rb
  
  "
  
  )) 
  
  ==
  
   NULL)
            
  
  continue
  
  ;

        printf(
  
  "
  
  打开文件%s/n
  
  "
  
  , file);
        ReadBmp(RGB, fp);
        Convert(RGB, YUV);
        fwrite(YUV, 
  
  1
  
  , imgSize
  
  +
  
  (imgSize
  
  >>
  
  1
  
  ), fp2);
  
  //
  
  写入文件
  
  

  
          fclose(fp);
    }

    fclose(fp2);
    
  
  if
  
  (RGB)
        free(RGB);

    
  
  if
  
  (YUV)
        free(YUV);

    printf(
  
  "
  
  完成/n
  
  "
  
  );
    system(
  
  "
  
  pause
  
  "
  
  );
    
  
  return
  
   
  
  1
  
  ;
}


  
  //
  
  读BMP
  
  

  
  void
  
   ReadBmp(unsigned 
  
  char
  
   
  
  *
  
  RGB,FILE 
  
  *
  
  fp)
{
    
  
  int
  
   i,j;
    unsigned 
  
  char
  
   temp;

    fseek(fp,
  
  54
  
  , SEEK_SET);

    fread(RGB
  
  +
  
  WIDTH
  
  *
  
  HEIGHT
  
  *
  
  3
  
  , 
  
  1
  
  , WIDTH
  
  *
  
  HEIGHT
  
  *
  
  3
  
  , fp);
  
  //
  
  读取
  
  

  
      
  
  for
  
  (i
  
  =
  
  HEIGHT
  
  -
  
  1
  
  ,j
  
  =
  
  0
  
  ; i
  
  >=
  
  0
  
  ; i
  
  --
  
  ,j
  
  ++
  
  )
  
  //
  
  调整顺序
  
  

  
      {
        memcpy(RGB
  
  +
  
  j
  
  *
  
  WIDTH
  
  *
  
  3
  
  ,RGB
  
  +
  
  WIDTH
  
  *
  
  HEIGHT
  
  *
  
  3
  
  +
  
  i
  
  *
  
  WIDTH
  
  *
  
  3
  
  ,WIDTH
  
  *
  
  3
  
  );
    }
    
    
  
  //
  
  顺序调整
  
  

  
      
  
  for
  
  (i
  
  =
  
  0
  
  ; (unsigned 
  
  int
  
  )i 
  
  <
  
   WIDTH
  
  *
  
  HEIGHT
  
  *
  
  3
  
  ; i
  
  +=
  
  3
  
  )
    {
        temp 
  
  =
  
   RGB[i];
        RGB[i] 
  
  =
  
   RGB[i
  
  +
  
  2
  
  ];
        RGB[i
  
  +
  
  2
  
  ] 
  
  =
  
   temp;
    }
}


  
  void
  
   Convert(unsigned 
  
  char
  
   
  
  *
  
  RGB, unsigned 
  
  char
  
   
  
  *
  
  YUV)
{
    
  
  //
  
  变量声明
  
  

  
      unsigned 
  
  int
  
   i,x,y,j;
    unsigned 
  
  char
  
   
  
  *
  
  Y 
  
  =
  
   NULL;
    unsigned 
  
  char
  
   
  
  *
  
  U 
  
  =
  
   NULL;
    unsigned 
  
  char
  
   
  
  *
  
  V 
  
  =
  
   NULL;
    
    Y 
  
  =
  
   YUV;
    U 
  
  =
  
   YUV 
  
  +
  
   WIDTH
  
  *
  
  HEIGHT;
    V 
  
  =
  
   U 
  
  +
  
   ((WIDTH
  
  *
  
  HEIGHT)
  
  >>
  
  2
  
  );

    
  
  for
  
  (y
  
  =
  
  0
  
  ; y 
  
  <
  
   HEIGHT; y
  
  ++
  
  )
        
  
  for
  
  (x
  
  =
  
  0
  
  ; x 
  
  <
  
   WIDTH; x
  
  ++
  
  )
        {
            j 
  
  =
  
   y
  
  *
  
  WIDTH 
  
  +
  
   x;
            i 
  
  =
  
   j
  
  *
  
  3
  
  ;
            Y[j] 
  
  =
  
   (unsigned 
  
  char
  
  )(DY(RGB[i], RGB[i
  
  +
  
  1
  
  ], RGB[i
  
  +
  
  2
  
  ]));

            
  
  if
  
  (x
  
  %
  
  2
  
   
  
  ==
  
   
  
  1
  
   
  
  &&
  
   y
  
  %
  
  2
  
   
  
  ==
  
   
  
  1
  
  )
            {
                j 
  
  =
  
   (WIDTH
  
  >>
  
  1
  
  ) 
  
  *
  
   (y
  
  >>
  
  1
  
  ) 
  
  +
  
   (x
  
  >>
  
  1
  
  );
                
  
  //
  
  上面i仍有效
  
  

  
                  U[j] 
  
  =
  
   (unsigned 
  
  char
  
  )
                       ((DU(RGB[i  ], RGB[i
  
  +
  
  1
  
  ], RGB[i
  
  +
  
  2
  
  ]) 
  
  +
  
   
                         DU(RGB[i
  
  -
  
  3
  
  ], RGB[i
  
  -
  
  2
  
  ], RGB[i
  
  -
  
  1
  
  ]) 
  
  +
  
  
                         DU(RGB[i  
  
  -
  
  WIDTH
  
  *
  
  3
  
  ], RGB[i
  
  +
  
  1
  
  -
  
  WIDTH
  
  *
  
  3
  
  ], RGB[i
  
  +
  
  2
  
  -
  
  WIDTH
  
  *
  
  3
  
  ]) 
  
  +
  
  
                         DU(RGB[i
  
  -
  
  3
  
  -
  
  WIDTH
  
  *
  
  3
  
  ], RGB[i
  
  -
  
  2
  
  -
  
  WIDTH
  
  *
  
  3
  
  ], RGB[i
  
  -
  
  1
  
  -
  
  WIDTH
  
  *
  
  3
  
  ]))
  
  /
  
  4
  
  );

                V[j] 
  
  =
  
   (unsigned 
  
  char
  
  )
                       ((DV(RGB[i  ], RGB[i
  
  +
  
  1
  
  ], RGB[i
  
  +
  
  2
  
  ]) 
  
  +
  
   
                         DV(RGB[i
  
  -
  
  3
  
  ], RGB[i
  
  -
  
  2
  
  ], RGB[i
  
  -
  
  1
  
  ]) 
  
  +
  
  
                         DV(RGB[i  
  
  -
  
  WIDTH
  
  *
  
  3
  
  ], RGB[i
  
  +
  
  1
  
  -
  
  WIDTH
  
  *
  
  3
  
  ], RGB[i
  
  +
  
  2
  
  -
  
  WIDTH
  
  *
  
  3
  
  ]) 
  
  +
  
  
                         DV(RGB[i
  
  -
  
  3
  
  -
  
  WIDTH
  
  *
  
  3
  
  ], RGB[i
  
  -
  
  2
  
  -
  
  WIDTH
  
  *
  
  3
  
  ], RGB[i
  
  -
  
  1
  
  -
  
  WIDTH
  
  *
  
  3
  
  ]))
  
  /
  
  4
  
  );
            }

        }
}
 
 
 
 


 
 
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值