#define RGB2YUV_SHIFT 16
#define BY ((int)( 0.098*(1<<RGB2YUV_SHIFT)+0.5))
#define BV ((int)(-0.071*(1<<RGB2YUV_SHIFT)+0.5))
#define BU ((int)( 0.439*(1<<RGB2YUV_SHIFT)+0.5))
#define GY ((int)( 0.504*(1<<RGB2YUV_SHIFT)+0.5))
#define GV ((int)(-0.368*(1<<RGB2YUV_SHIFT)+0.5))
#define GU ((int)(-0.291*(1<<RGB2YUV_SHIFT)+0.5))
#define RY ((int)( 0.257*(1<<RGB2YUV_SHIFT)+0.5))
#define RV ((int)( 0.439*(1<<RGB2YUV_SHIFT)+0.5))
#define RU ((int)(-0.148*(1<<RGB2YUV_SHIFT)+0.5))
void rgb24toyuv400(const unsigned char *src, unsigned char *ydst, unsigned char *udst,
unsigned char *vdst,unsigned int width, unsigned int height,unsigned int lumStride,
unsigned int chromStride, unsigned int srcStride)
{
unsigned int y;
for(y=0; y<height; y++)
{
unsigned int i;
for(i=0; i<height; i++)
{
unsigned int b= src[3*i+0];
unsigned int g= src[3*i+1];
unsigned int r= src[3*i+2];
unsigned int Y = ((RY*r + GY*g + BY*b)>>RGB2YUV_SHIFT) + 16;
ydst[i] = Y;
}
ydst += lumStride;
src += srcStride;
}
}
void rgb24toyuv411(const unsigned char *src, unsigned char *ydst, unsigned char *udst,
unsigned char *vdst,unsigned int width, unsigned int height,unsigned int lumStride,
unsigned int chromStride, unsigned int srcStride)
{
unsigned int y;
const unsigned int chromWidth = width>>1;
y=0;
for(; y<height; y+=2)
{
unsigned int i;
for(i=0; i<chromWidth; i++)
{
unsigned int b= src[6*i+0];
unsigned int g= src[6*i+1];
unsigned int r= src[6*i+2];
unsigned int Y = ((RY*r + GY*g + BY*b)>>RGB2YUV_SHIFT) + 16;
unsigned int V = ((RV*r + GV*g + BV*b)>>RGB2YUV_SHIFT) + 128;
unsigned int U = ((RU*r + GU*g + BU*b)>>RGB2YUV_SHIFT) + 128;
udst[i] = U;
vdst[i] = V;
ydst[2*i] = Y;
b= src[6*i+3];
g= src[6*i+4];
r= src[6*i+5];
Y = ((RY*r + GY*g + BY*b)>>RGB2YUV_SHIFT) + 16;
ydst[2*i+1] = Y;
}
ydst += lumStride;
src += srcStride;
for(i=0; i<chromWidth; i++)
{
unsigned int b= src[6*i+0];
unsigned int g= src[6*i+1];
unsigned int r= src[6*i+2];
unsigned int Y = ((RY*r + GY*g + BY*b)>>RGB2YUV_SHIFT) + 16;
ydst[2*i] = Y;
b= src[6*i+3];
g= src[6*i+4];
r= src[6*i+5];
Y = ((RY*r + GY*g + BY*b)>>RGB2YUV_SHIFT) + 16;
ydst[2*i+1] = Y;
}
udst += chromStride;
vdst += chromStride;
ydst += lumStride;
src += srcStride;
}
}
void rgb24toyuv420(const unsigned char *src, unsigned char *ydst, unsigned char *udst,
unsigned char *vdst,unsigned int width, unsigned int height,unsigned int lumStride,
unsigned int chromStride, unsigned int srcStride)
{
unsigned int y;
const unsigned int chromWidth = width>>1;
y=0;
for(; y<height; y+=2)
{
unsigned int i;
for(i=0; i<chromWidth; i++)
{
unsigned int b= src[6*i+0];
unsigned int g= src[6*i+1];
unsigned int r= src[6*i+2];
unsigned int Y = ((RY*r + GY*g + BY*b)>>RGB2YUV_SHIFT) + 16;
unsigned int U = ((RU*r + GU*g + BU*b)>>RGB2YUV_SHIFT) + 128;
udst[i] = U;
ydst[2*i] = Y;
b= src[6*i+3];
g= src[6*i+4];
r= src[6*i+5];
Y = ((RY*r + GY*g + BY*b)>>RGB2YUV_SHIFT) + 16;
ydst[2*i+1] = Y;
}
ydst += lumStride;
src += srcStride;
for(i=0; i<chromWidth; i++)
{
unsigned int b= src[6*i+0];
unsigned int g= src[6*i+1];
unsigned int r= src[6*i+2];
unsigned int Y = ((RY*r + GY*g + BY*b)>>RGB2YUV_SHIFT) + 16;
unsigned int V = ((RV*r + GV*g + BV*b)>>RGB2YUV_SHIFT) + 128;
vdst[i] = V;
ydst[2*i] = Y;
b= src[6*i+3];
g= src[6*i+4];
r= src[6*i+5];
Y = ((RY*r + GY*g + BY*b)>>RGB2YUV_SHIFT) + 16;
ydst[2*i+1] = Y;
}
udst += chromStride;
vdst += chromStride;
ydst += lumStride;
src += srcStride;
}
}
void rgb24toyuv422(const unsigned char *src, unsigned char *ydst, unsigned char *udst,
unsigned char *vdst,unsigned int width, unsigned int height,unsigned int lumStride,
unsigned int chromStride, unsigned int srcStride)
{
unsigned int y;
const unsigned int chromWidth = width>>1;
for(y=0; y<height; y++)
{
unsigned int i;
for(i=0; i<chromWidth; i++)
{
unsigned int b= src[6*i+0];
unsigned int g= src[6*i+1];
unsigned int r= src[6*i+2];
unsigned int Y = ((RY*r + GY*g + BY*b)>>RGB2YUV_SHIFT) + 16;
unsigned int V = ((RV*r + GV*g + BV*b)>>RGB2YUV_SHIFT) + 128;
unsigned int U = ((RU*r + GU*g + BU*b)>>RGB2YUV_SHIFT) + 128;
udst[i] = U;
vdst[i] = V;
ydst[2*i] = Y;
b= src[6*i+3];
g= src[6*i+4];
r= src[6*i+5];
Y = ((RY*r + GY*g + BY*b)>>RGB2YUV_SHIFT) + 16;
ydst[2*i+1] = Y;
}
udst += chromStride;
vdst += chromStride;
ydst += lumStride;
src += srcStride;
}
}
void rgb24toyuv444(const unsigned char *src, unsigned char *ydst, unsigned char *udst,
unsigned char *vdst,unsigned int width, unsigned int height,unsigned int lumStride,
unsigned int chromStride, unsigned int srcStride)
{
unsigned int y;
const unsigned int chromWidth = width;
for(y=0; y<height; y++)
{
unsigned int i;
for(i=0; i<chromWidth; i++)
{
unsigned int b= src[3*i+0];
unsigned int g= src[3*i+1];
unsigned int r= src[3*i+2];
unsigned int Y = ((RY*r + GY*g + BY*b)>>RGB2YUV_SHIFT) + 16;
unsigned int V = ((RV*r + GV*g + BV*b)>>RGB2YUV_SHIFT) + 128;
unsigned int U = ((RU*r + GU*g + BU*b)>>RGB2YUV_SHIFT) + 128;
udst[i] = U;
vdst[i] = V;
ydst[i] = Y;
}
udst += chromStride;
vdst += chromStride;
ydst += lumStride;
src += srcStride;
}
}
int HeadStand(unsigned char *pBuf,int pWidth,int pHeight)
{
unsigned char *tBuf;
int i;
if ((tBuf = (unsigned char *)malloc(pWidth*pHeight*3)) == NULL)
return -1;
for (i=0;i<pHeight/2;i++)
{
memcpy(tBuf,pBuf+i*pWidth*3,pWidth*3);
memcpy(pBuf+i*pWidth*3,pBuf+(pHeight-i-1)*pWidth*3,pWidth*3);
memcpy(pBuf+(pHeight-i-1)*pWidth*3,tBuf,pWidth*3);
}
free(tBuf);
return 0;
}
void CBmp2yuvDlg::OnConvert()
{
// TODO: Add your control notification handler code here
CString tPathName;
CString tDesDir;
char tDesPathName[100];
FILE *fp;
unsigned char *rgbBuf,*ty,*tu,*tv;
int with=0,height=0,iSizeImage = 0;
BITMAPFILEHEADER bitmap;
BITMAPINFOHEADER bitmapHeader;
char tStr1[100],tStr2[100];
int i,StrLen,SelYUVFormat;
CString FileName;
CComboBox *pComboBox;
int ySize,uSize,vSize;
//检测输入是不是合法
GetDlgItemText(IDC_SOURCEDIR,tPathName);
if(tPathName.IsEmpty() != 0)
return;
GetDlgItemText(IDC_DESDIR,tDesDir);
if(tDesDir.IsEmpty() != 0)
return;
GetDlgItemText(IDC_DESFILENAME,FileName);
if(FileName.IsEmpty() != 0)
return;
fp = fopen(tPathName,"r");
if(fp == NULL)
return;
//得到要转化的yuv格式
pComboBox = (CComboBox *)GetDlgItem(IDC_YUVFORMAT);
SelYUVFormat = pComboBox->GetCurSel();
//得到bitmap头部信息,包括文件头和bitmap头
memset(&(bitmap),0,sizeof(bitmap));
memset(&(bitmapHeader),0,sizeof(bitmapHeader));
fread(&bitmap,sizeof(char),sizeof(bitmap),fp);
fread(&bitmapHeader,sizeof(char),sizeof(bitmapHeader),fp);
//分配空间
with = bitmapHeader.biWidth;
height = bitmapHeader.biHeight;
if((with%2 != 0) || (height%2 != 0))
{
AfxMessageBox("图像的分辨率必须是偶数!",MB_OK,-1);
return;
}
// iSizeImage = bitmapHeader.biSizeImage;
iSizeImage = with*height*3;
switch(SelYUVFormat)
{
case YUV400:
rgbBuf = (unsigned char *)malloc(iSizeImage);
if(rgbBuf == NULL)
return;
ySize = iSizeImage/3;
ty = (unsigned char *)malloc(ySize);
if(ty == NULL)
return;
uSize = 0;
tu = (unsigned char *)malloc(uSize);
if(tu == NULL)
return;
vSize = 0;
tv = (unsigned char *)malloc(vSize);
if(tv == NULL)
return;
fseek(fp,bitmap.bfOffBits,SEEK_SET);
fread(rgbBuf,sizeof(char),iSizeImage,fp);
HeadStand(rgbBuf,with,height);
rgb24toyuv400(rgbBuf,ty,tu,tv,with,height,with,0,with*3);
break;
case YUV411:
rgbBuf = (unsigned char *)malloc(iSizeImage);
if(rgbBuf == NULL)
return;
ySize = iSizeImage/3;
ty = (unsigned char *)malloc(ySize);
if(ty == NULL)
return;
uSize = iSizeImage/12;
tu = (unsigned char *)malloc(uSize);
if(tu == NULL)
return;
vSize = iSizeImage/12;
tv = (unsigned char *)malloc(vSize);
if(tv == NULL)
return;
fseek(fp,bitmap.bfOffBits,SEEK_SET);
fread(rgbBuf,sizeof(char),iSizeImage,fp);
HeadStand(rgbBuf,with,height);
rgb24toyuv411(rgbBuf,ty,tu,tv,with,height,with,with/4,with*3);
break;
case YUV420:
rgbBuf = (unsigned char *)malloc(iSizeImage);
if(rgbBuf == NULL)
return;
ySize = iSizeImage/3;
ty = (unsigned char *)malloc(ySize);
if(ty == NULL)
return;
uSize = iSizeImage/12;
tu = (unsigned char *)malloc(uSize);
if(tu == NULL)
return;
vSize = iSizeImage/12;
tv = (unsigned char *)malloc(vSize);
if(tv == NULL)
return;
fseek(fp,bitmap.bfOffBits,SEEK_SET);
fread(rgbBuf,sizeof(char),iSizeImage,fp);
HeadStand(rgbBuf,with,height);
rgb24toyuv420(rgbBuf,ty,tu,tv,with,height,with,with/4,with*3);
break;
case YUV422:
rgbBuf = (unsigned char *)malloc(iSizeImage);
if(rgbBuf == NULL)
return;
ySize = iSizeImage/3;
ty = (unsigned char *)malloc(ySize);
if(ty == NULL)
return;
uSize = iSizeImage/6;
tu = (unsigned char *)malloc(uSize);
if(tu == NULL)
return;
vSize = iSizeImage/6;
tv = (unsigned char *)malloc(vSize);
if(tv == NULL)
return;
fseek(fp,bitmap.bfOffBits,SEEK_SET);
fread(rgbBuf,sizeof(char),iSizeImage,fp);
HeadStand(rgbBuf,with,height);
rgb24toyuv422(rgbBuf,ty,tu,tv,with,height,with,with/2,with*3);
break;
case YUV444:
rgbBuf = (unsigned char *)malloc(iSizeImage);
if(rgbBuf == NULL)
return;
ySize = iSizeImage/3;
ty = (unsigned char *)malloc(ySize);
if(ty == NULL)
return;
uSize = iSizeImage/3;
tu = (unsigned char *)malloc(uSize);
if(tu == NULL)
return;
vSize = iSizeImage/3;
tv = (unsigned char *)malloc(vSize);
if(tv == NULL)
return;
fseek(fp,bitmap.bfOffBits,SEEK_SET);
fread(rgbBuf,sizeof(char),iSizeImage,fp);
HeadStand(rgbBuf,with,height);
rgb24toyuv444(rgbBuf,ty,tu,tv,with,height,with,with,with*3);
break;
default:
break;
}
fclose(fp);
StrLen = tDesDir.GetLength();
for(i = 0; i < StrLen;i++)
tStr1[i] = tDesDir.GetAt(i);
tStr1[i] = 0;
StrLen = FileName.GetLength();
for(i = 0; i < StrLen;i++)
tStr2[i] = FileName.GetAt(i);
tStr2[i] = 0;
sprintf(tDesPathName,"%s\\%s.yuv",tStr1,tStr2);
fp = fopen(tDesPathName,"w");
if(fp == NULL)
return;
fwrite(ty,sizeof(char),ySize,fp);
fwrite(tu,sizeof(char),uSize,fp);
fwrite(tv,sizeof(char),vSize,fp);
fclose(fp);
free(rgbBuf);
free(ty);
free(tu);
free(tv);
AfxMessageBox("转化完成!",MB_OK,-1);
}
RGB2YUV
最新推荐文章于 2022-03-25 19:09:51 发布