bmp提取rgb888转换成yuv格式中的yv12再从yv12转换为rgb888写成bmp格式文件的工程,测试通过

bmp中提取rgb888格式的数据 ,转换成yv12格式,
再从yv12格式转换成rgb888格式的数据
然后以bmp格式写入文件的测试工程。

///-------------rgb.cpp-----------内容是rgb与yv12格式转换函数
#include "convert.h"


// Conversion from RGB to YUV420
int RGB2YUV_YR[256], RGB2YUV_YG[256], RGB2YUV_YB[256];
int RGB2YUV_UR[256], RGB2YUV_UG[256], RGB2YUV_UBVR[256];
int RGB2YUV_VG[256], RGB2YUV_VB[256];
// Conversion from YUV420 to RGB24
static long int crv_tab[256];
static long int cbu_tab[256];
static long int cgu_tab[256];
static long int cgv_tab[256];
static long int tab_76309[256];
static unsigned char clp[1024]; //for clip in CCIR601

// Table used for RGB to YUV420 conversion
void InitLookupTable()
{
 int i;
 for (i = 0; i < 256; i++) RGB2YUV_YR[i] = (float)65.481 * (i<<8);
 for (i = 0; i < 256; i++) RGB2YUV_YG[i] = (float)128.553 * (i<<8);
 for (i = 0; i < 256; i++) RGB2YUV_YB[i] = (float)24.966 * (i<<8);
 for (i = 0; i < 256; i++) RGB2YUV_UR[i] = (float)37.797 * (i<<8);
 for (i = 0; i < 256; i++) RGB2YUV_UG[i] = (float)74.203 * (i<<8);
 for (i = 0; i < 256; i++) RGB2YUV_VG[i] = (float)93.786 * (i<<8);
 for (i = 0; i < 256; i++) RGB2YUV_VB[i] = (float)18.214 * (i<<8);
 for (i = 0; i < 256; i++) RGB2YUV_UBVR[i] = (float)112 * (i<<8);
}

// Convert from RGB24 to YUV420
//int ConvertRGB2YUV(int w,int h,unsigned char *bmp,unsigned int *yuv)
int ConvertRGB2YUV(int w,int h,unsigned char *bmp,unsigned char*yuv)
{

 //unsigned int *u,*v,*y,*uu,*vv;
 //unsigned int *pu1,*pu2,*pu3,*pu4;
 //unsigned int *pv1,*pv2,*pv3,*pv4;
 //unsigned char *r,*g,*b;
 //int i,j;

 //uu=new unsigned int[w*h];
 //vv=new unsigned int[w*h];

 unsigned char *u,*v,*y,*uu,*vv;
 unsigned char *pu1,*pu2,*pu3,*pu4;
 unsigned char *pv1,*pv2,*pv3,*pv4;
 unsigned char *r,*g,*b;
 int i,j;

 uu=new unsigned char[w*h];
 vv=new unsigned char[w*h];
 if(uu==NULL || vv==NULL)
  return 0;
 y=yuv;
 u=uu;
 v=vv;
 // Get r,g,b pointers from bmp image data....
 r=bmp;
 g=bmp+1;
 b=bmp+2;

 //Get YUV values for rgb values. ..

 for(i=0;i {
  for(j=0;j  {
   *y++=( RGB2YUV_YR[*r] +RGB2YUV_YG[*g]+RGB2YUV_YB[*b]+1048576)>>16;
   *u++=(-RGB2YUV_UR[*r] -RGB2YUV_UG[*g]+RGB2YUV_UBVR[*b]+8388608)>>16;
   *v++=( RGB2YUV_UBVR[*r]-RGB2YUV_VG[*g]-RGB2YUV_VB[*b]+8388608)>>16;
   r+=3;
   g+=3;
   b+=3;
  }
 }

// Now sample the U & V to obtain YUV 4:2:0 format
// Sampling mechanism...
/* @ -> Y
# -> U or V
@ @ @ @
# #
@ @ @ @
@ @ @ @
# #
@ @ @ @
*/
// Get the right pointers...

 u=yuv+w*h;
 v=u+(w*h)/4;
 // For U
 pu1=uu;
 pu2=pu1+1;
 pu3=pu1+w;
 pu4=pu3+1;
 // For V
 pv1=vv;
 pv2=pv1+1;
 pv3=pv1+w;
 pv4=pv3+1;
 // Do sampling....

 for(i=0;i {
  for(j=0;j  {
   *u++=(*pu1+*pu2+*pu3+*pu4)>>2;
   *v++=(*pv1+*pv2+*pv3+*pv4)>>2;
   pu1+=2;
   pu2+=2;
   pu3+=2;
   pu4+=2;
   pv1+=2;
   pv2+=2;
   pv3+=2;
   pv4+=2;
  }

  pu1+=w;
  pu2+=w;
  pu3+=w;
  pu4+=w;
  pv1+=w;
  pv2+=w;
  pv3+=w;
  pv4+=w;

 }

 delete uu;
 delete vv;
 return 1;

}

//
//Initialize conversion table for YUV420 to RGB
//

void InitConvertTable()
{

 long int crv,cbu,cgu,cgv;
 int i,ind;
 crv = 104597; cbu = 132201; /* fra matrise i global.h */
 cgu = 25675; cgv = 53279;
 for (i = 0; i < 256; i++)
 {
  crv_tab[i] = (i-128) * crv;
  cbu_tab[i] = (i-128) * cbu;
  cgu_tab[i] = (i-128) * cgu;
  cgv_tab[i] = (i-128) * cgv;
  tab_76309[i] = 76309*(i-16);
 }

 for (i=0; i<384; i++)
  clp[i] =0;

 ind=384;
 for (i=0;i<256; i++)
  clp[ind++]=i;

 ind=640;
 for (i=0;i<384;i++)
  clp[ind++]=255;

}
// // Convert from YUV420 to RGB24
//
void ConvertYUV2RGB(unsigned char *src0,unsigned char *src1,unsigned char *src2,unsigned char *dst_ori,
int width,int height)
{

 int y1,y2,u,v;
 unsigned char *py1,*py2;
 int i,j, c1, c2, c3, c4;
 unsigned char *d1, *d2;
 py1=src0;
 py2=py1+width;
 d1=dst_ori;
 d2=d1+3*width;

 for (j = 0; j < height; j += 2)
 {

  for (i = 0; i < width; i += 2)
  {

   u = *src1++;
   v = *src2++;
   c1 = crv_tab[v];
   c2 = cgu_tab[u];
   c3 = cgv_tab[v];
   c4 = cbu_tab[u];
   //up-left
   y1 = tab_76309[*py1++];
   *d1++ = clp[384+((y1 + c1)>>16)];
   *d1++ = clp[384+((y1 - c2 - c3)>>16)];
   *d1++ = clp[384+((y1 + c4)>>16)];
   //down-left
   y2 = tab_76309[*py2++];
   *d2++ = clp[384+((y2 + c1)>>16)];
   *d2++ = clp[384+((y2 - c2 - c3)>>16)];
   *d2++ = clp[384+((y2 + c4)>>16)];
   //up-right
   y1 = tab_76309[*py1++];
   *d1++ = clp[384+((y1 + c1)>>16)];
   *d1++ = clp[384+((y1 - c2 - c3)>>16)];
   *d1++ = clp[384+((y1 + c4)>>16)];
   //down-right
   y2 = tab_76309[*py2++];
   *d2++ = clp[384+((y2 + c1)>>16)];
   *d2++ = clp[384+((y2 - c2 - c3)>>16)];
   *d2++ = clp[384+((y2 + c4)>>16)];
     }

  d1 += 3*width;
  d2 += 3*width;
  py1+= width;
  py2+= width;
 }
}
///----------------------convert.h--头文件
#ifndef CONVERT_H
#define CONVERT_H
#include
#include
#include
// Conversion from RGB24 to YUV420
void InitLookupTable();
//int ConvertRGB2YUV(int w,int h,unsigned char *rgbdata,unsigned int *yuv);
int ConvertRGB2YUV(int w,int h,unsigned char *bmp,unsigned char*yuv) ;
// Conversion from YUV420 to RGB24
void InitConvertTable();
void ConvertYUV2RGB(unsigned char *src0,unsigned char *src1,unsigned char *src2,unsigned char *dst_ori,
int width,int height);
typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef unsigned int DWORD;
typedef long LONG;
#pragma pack (1)
typedef struct tagBITMAPFILEHEADER {
  WORD    bfType;
  DWORD   bfSize;
  WORD    bfReserved1;
  WORD    bfReserved2;
  DWORD   bfOffBits;
} BITMAPFILEHEADER, *PBITMAPFILEHEADER;
typedef struct tagBITMAPINFOHEADER{
  DWORD  biSize;
  LONG   biWidth;
  LONG   biHeight;
  WORD   biPlanes;
  WORD   biBitCount;
  DWORD  biCompression;
  DWORD  biSizeImage;
  LONG   biXPelsPerMeter;
  LONG   biYPelsPerMeter;
  DWORD  biClrUsed;
  DWORD  biClrImportant;
} BITMAPINFOHEADER, *PBITMAPINFOHEADER;
typedef struct tagRGBQUAD {
  BYTE    rgbBlue;
  BYTE    rgbGreen;
  BYTE    rgbRed;
  BYTE    rgbReserved;
} RGBQUAD;

#endif ///CONVERT_H
//--------------------------main.cpp ,转换格式的测试文件
#include "convert.h"


int main(void)
{
 int width = 176;
 int height = 144;
 int yuvsize = width*height*2;
 int rgbsize = width*height*3;
 
 BYTE *yuv = new BYTE[yuvsize];
 BYTE *rgbdata = new BYTE[rgbsize];
 memset(yuv, 0, yuvsize);
 memset(rgbdata, 0, rgbsize);

    int sizeofheads = sizeof(BITMAPFILEHEADER);
 sizeofheads = sizeof(BITMAPINFOHEADER);

 BITMAPFILEHEADER filehead, *fileheadp = &filehead;
 BITMAPINFOHEADER infohead, *infoP = &infohead;  
 memset(fileheadp, 0, sizeof(BITMAPFILEHEADER));
 memset(infoP, 0, sizeof(BITMAPINFOHEADER));
 FILE * fp = fopen("D://rgb.bmp", "r");
 int readsize = fread(fileheadp, sizeof(BITMAPFILEHEADER), 1, fp);

 int dataoffset = filehead.bfOffBits;//说明从文件头开始到实际的图象数据之间的字节的偏移量
 int filesizeall = filehead.bfSize;//说明文件的大小,用字节为单位
 int filetype = filehead.bfType;//说明文件的类型.(该值必需是0x4D42,也就是字符'BM'。

 readsize = fread(infoP, sizeof(BITMAPINFOHEADER), 1, fp);
 int infosize = infohead.biSize;//说明BITMAPINFOHEADER结构所需要的字数
 int biW = infohead.biWidth;//说明图象的宽度,以象素为单位
 int biH = infohead.biHeight;//说明图象的高度,以象素为单位。如果该值是一个正数,说明图像是倒向的,如果该值是一个负数,则说明图像是正向的。大多数的BMP文件都是倒向的位图,
 int indexsize = infohead.biBitCount;//其值为1、4、8、16、24、或32
 int isCompress = infohead.biCompression;//说明图象数据压缩的类型。
 int sizeImg = infohead.biSizeImage;//说明图象的大小,以字节为单位。当用BI_RGB格式时,可设置为0
   
 BYTE *rgbP = rgbdata;
 for (int i = biH-1; i>=0; i--)
 {
  rgbP = rgbdata + i*biW*3;
  for (int j = 0; j < biW; j++)
  {
   fread(rgbP+2, sizeof(BYTE) ,1, fp);
   fread(rgbP+1, sizeof(BYTE) , 1,fp);
   fread(rgbP, sizeof(BYTE) ,1, fp);
   rgbP = rgbP + 3;
  }
 }

 InitLookupTable();
 InitConvertTable();
 ConvertRGB2YUV(width, height, rgbdata, yuv);
 FILE * fw_yuv = fopen("D://rgb_1.yuv", "w");
 fwrite(yuv, sizeof(unsigned char), yuvsize, fw_yuv);
 BYTE *rgbdata2 = new BYTE[rgbsize];
 memset(rgbdata2, 0, rgbsize);
 BYTE * yp = yuv;
 BYTE * up = yuv + width*height;
 BYTE * vp = yuv + width*height + width*height/4;
 ConvertYUV2RGB(yp,up,vp,rgbdata2, width, height);
 FILE * fw_rgb = fopen("D://rgb_2.bmp", "w");
 fwrite(fileheadp, sizeof(BITMAPFILEHEADER) ,1, fw_rgb);
 fwrite(infoP, sizeof(BITMAPINFOHEADER) ,1, fw_rgb);
 for (int i = biH-1; i>=0; i--)
 {
  rgbP = rgbdata2 + i*biW*3;
  for (int j = 0; j < biW; j++)
  {
   fwrite(rgbP+2, sizeof(BYTE) ,1, fw_rgb);
   fwrite(rgbP+1, sizeof(BYTE) , 1,fw_rgb);
   fwrite(rgbP, sizeof(BYTE) ,1, fw_rgb);
   rgbP = rgbP + 3;
  }
 }

 delete(yuv);
 delete(rgbdata);
 fclose(fp);
 fclose(fw_yuv);
 fclose(fw_rgb);
 return 0;
}

 

你可能感兴趣的:(bmp提取rgb888转换成yuv格式中的yv12再从yv12转换为rgb888写成bmp格式文件的工程,测试通过)