📄 debugycbcr.cpp
字号:
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// AUTHOR: Ren MingWu (任明武)
// 13952033136
// renmingwu@mail.njust.edu.cn
// 该软件Free,请保留作者信息.
// 2008.7.30
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <math.h>
#include <stdio.h>
#include <time.h>
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Global Definations
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#define PAL_IMG_WIDTH 720
#define PAL_IMG_HEIGHT 576
BYTE gCbYCrData[864*625*2+1024*3]; //1728*625*2,再多出3K防止错误时溢出
BYTE gRGBImg[PAL_IMG_WIDTH*PAL_IMG_HEIGHT*3+1024*3]; //转换后的结果,再多出3K防止错误时溢出
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// YCbCr: CbYCr => RGB
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int RmwLoadCbYCrData(char *fileName,BYTE *pCbYCrData)
{
int N=0;
FILE *fp=fopen(fileName,"rb");
if (!fp) return 0;
fseek(fp,0L,SEEK_END);
N=ftell(fp);
fseek(fp,0L,SEEK_SET);
fread(pCbYCrData,1,N,fp);
fclose(fp);
return N;
}
void RmwDebugPalCbYCr2RGB(BYTE *pCbYCrData,int N,BYTE *pRGBImg)
{
int i,j;
char buff[100];
int curPos,prePos=0;
FILE *fp=fopen("DebugCbYCr.txt","w+t");
//-------------CbYCr=>RGB--------------------------//
BYTE Y1,Y2;
char tmpCb,tmpCr;
int Cb,Cr;
int B1,B2,G1,G2,R1,R2;
//-------------控制参数----------------------------//
bool isNewRow;
BYTE controlByte;
int F; //0-odd field, 1--even field.
bool isOddField; //是否是奇数场
int V; //1- blanking, 0-not blanking
bool isVerticalBlanking;//是否在消隐.
int H; //0 at SAV; 1 at EAV
bool isSAV; //SAV: Start of Active Video.
//-------------RGB图像----------------------------//
int tranferLines=0;
BYTE *pRes;
BYTE *pOddBegin=pRGBImg; //奇数行指针
BYTE *pEvenBegin=pRGBImg+PAL_IMG_WIDTH*3; //偶数行指针
// step.1--------------------检测最末最首的各10个字节,看数据是否回绕了-------------------//
fprintf(fp,"The First 10 Byte is : ");
printf("The First 10 Byte is : ");
for(i=0;i<10;i++)
{
fprintf(fp,"%02X ",pCbYCrData[i]);
printf("%02X ",pCbYCrData[i]);
}
fprintf(fp,"\n");
printf("\n");
fprintf(fp,"The Last 10 Byte is : ");
printf("The Last 10 Byte is : ");
for(i=N-10;i<N;i++)
{
fprintf(fp,"%02X ",pCbYCrData[i]);
printf("%02X ",pCbYCrData[i]);
}
fprintf(fp,"\n\n");
printf("\n");
getchar();
getchar();
// step.2--------------------图像内容分析-------------------------------------------------//
prePos=0;
for(i=prePos=0;i<N-4;i++)
{
// step.1------新的1行数据---------------------------------------------//
isNewRow = (pCbYCrData[i+0]==0xFF)&& (pCbYCrData[i+1]==0)&& (pCbYCrData[i+2]==0);
if (!isNewRow) continue;
// step.2------填写有效控制信息---------------------------------------//
//0.记录控制字
curPos=i;
controlByte=pCbYCrData[i+3];
//1.是否是奇数场数据
F = (controlByte & 0x40); //0x40: 01(F)00,0000.
isOddField = (F==0);
//2.是否是消隐期
V = (controlByte & 0x20); //0x20: 010(V)0,0000.
isVerticalBlanking = (V!=0);
//3.是否是视频有效数据开始
H = (controlByte & 0x10); //0x10: 0001(H),0000.
isSAV= (H==0);
//step.3 ---写调试信息------------------------------------------------//
if (isSAV) //是有效数据开始SAV.其应该距离EAV的尾部仅相隔了Horizontal Blanking 280个字节,+EAV的4个字节,故284
{
sprintf(buff,"%08d__%04d %X is start",curPos,curPos-prePos,controlByte);
if (curPos-prePos!=284)
{
strcat(buff,"*****Err *****!");
printf("%s\n",buff);
getchar();
}
else printf("%s\n",buff);
fprintf(fp,"%s\n",buff);
}
else //是有效数据结束EAV,其应该距离SAV的尾部仅相隔了720个像素,即1440个字节,+SAV的4个字节,故1444
{
sprintf(buff,"%08d__%04d %X is End",curPos,curPos-prePos,controlByte);
if (curPos-prePos!=1444)
{
strcat(buff,"*****Err *****!");
printf("%s\n",buff);
getchar();
}
else printf("%s\n",buff);
fprintf(fp,"%s\n",buff);
}
prePos=curPos;
//step.4 ---图像转换--------------------------------------------------//
if (isVerticalBlanking) continue; //不是有效图像数据.
if (!isSAV) continue; //不是有效数据开始
//对于奇数场而言,其SAV/EAV应该是80/9D;对偶数场而言,其SAV/EAV应该是C7/DA.
if (isOddField)
{
pRes=pOddBegin;
pOddBegin += PAL_IMG_WIDTH*3*2;
}
else
{
pRes=pEvenBegin;
pEvenBegin += PAL_IMG_WIDTH*3*2;
}
tranferLines++; //被总转换的行数.
for(j=curPos+4;j<curPos+4+PAL_IMG_WIDTH*2;j+=4) //一次处理4个字节,即CbY1CrY2,得到2个像素
{
tmpCb=pCbYCrData[j+0]-128;
Y1=pCbYCrData[j+1];
tmpCr=pCbYCrData[j+2]-128;
Y2=pCbYCrData[j+3];
Cb=tmpCb;
Cr=tmpCr;
// ==>B: B = Y + 1.772 Cb
B1 = Y1 + 1.772*Cb;
B2 = Y2 + 1.772*Cb;
// ==>G: G = Y - 0.34414 Cb - 0.71414 Cr
G1=Y1 - 0.34414*Cb - 0.71414*Cr;
G2=Y2 - 0.34414*Cb - 0.71414*Cr;
// ==>R: R = Y + 1.402 Cr
R1 = Y1 + 1.402 * Cr;
R2 = Y2 + 1.402 * Cr;
// 饱和运算
B1=min(max(0,B1),255);
B2=min(max(0,B2),255);
G1=min(max(0,G1),255);
G2=min(max(0,G2),255);
R1=min(max(0,R1),255);
R2=min(max(0,R2),255);
// 赋值
#ifdef USE_GRY
*(pRes++) = Y1;
*(pRes++) = Y1;
*(pRes++) = Y1;
*(pRes++) = Y2;
*(pRes++) = Y2;
*(pRes++) = Y2;
#else
*(pRes++) = B1;
*(pRes++) = G1;
*(pRes++) = R1;
*(pRes++) = B2;
*(pRes++) = G2;
*(pRes++) = R2;
#endif
}
}
// step.3--------------------返回---------------------------------------------------------//
fprintf(fp,"共转换图像 %d 行\n",tranferLines);
printf("共转换图像 %d 行\n",tranferLines);
fclose(fp);
return;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// 读写文件
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
BYTE *RmwRead24BitBmpFile2Img(const char * filename,int *width,int *height)
{ FILE * BinFile;
BITMAPFILEHEADER FileHeader;
BITMAPINFOHEADER BmpHeader;
BYTE *img;
unsigned int size;
int Suc=1,w,h;
// Open File
*width=*height=0;
if((BinFile=fopen(filename,"rb"))==NULL) return NULL;
// Read Struct Info
if (fread((void *)&FileHeader,1,sizeof(FileHeader),BinFile)!=sizeof(FileHeader)) Suc=-1;
if (fread((void *)&BmpHeader,1,sizeof(BmpHeader),BinFile)!=sizeof(BmpHeader)) Suc=-1;
if ( (Suc==-1) ||
(FileHeader.bfOffBits<sizeof(FileHeader)+sizeof(BmpHeader) )
)
{
fclose(BinFile);
return NULL;
}
// Read Image Data
*width=w=(BmpHeader.biWidth+3)/4*4;
*height=h=BmpHeader.biHeight;
size=(*width)*(*height)*3;
fseek(BinFile,FileHeader.bfOffBits,SEEK_SET);
if ( (img=new BYTE[size])!=NULL)
{
for(int i=0;i<h;i++)
{
if(fread(img+(h-1-i)*w*3,sizeof(BYTE),w*3,BinFile)!=w*3)
{
fclose(BinFile);
delete img;
img=NULL;
return NULL;
}
}
}
fclose(BinFile);
return img;
}
bool RmwWrite24BitImg2BmpFile(BYTE *pImg,int width,int height,const char * filename)
// 当宽度不是4的倍数时自动添加成4的倍数
{ FILE *BinFile;
BITMAPFILEHEADER FileHeader;
BITMAPINFOHEADER BmpHeader;
bool Suc=true;
int i,extend;
BYTE *pCur;
// Open File
if((BinFile=fopen(filename,"w+b"))==NULL) { return false; }
// Fill the FileHeader
FileHeader.bfType= ((WORD) ('M' << 8) | 'B');
FileHeader.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);
FileHeader.bfSize=FileHeader.bfOffBits+width*height*3L ;
FileHeader.bfReserved1=0;
FileHeader.bfReserved2=0;
if (fwrite((void *)&FileHeader,1,sizeof(BITMAPFILEHEADER),BinFile)!=sizeof(BITMAPFILEHEADER)) Suc=false;
// Fill the ImgHeader
BmpHeader.biSize = 40;
BmpHeader.biWidth = width;
BmpHeader.biHeight = height;
BmpHeader.biPlanes = 1 ;
BmpHeader.biBitCount = 24 ;
BmpHeader.biCompression = 0 ;
BmpHeader.biSizeImage = 0 ;
BmpHeader.biXPelsPerMeter = 0;
BmpHeader.biYPelsPerMeter = 0;
BmpHeader.biClrUsed = 0;
BmpHeader.biClrImportant = 0;
if (fwrite((void *)&BmpHeader,1,sizeof(BITMAPINFOHEADER),BinFile)!=sizeof(BITMAPINFOHEADER)) Suc=false;
// write image data
extend=(width+3)/4*4-width;
if (extend==0)
{
for(pCur=pImg+(height-1)*3*width;pCur>=pImg;pCur-=3*width)
{
if (fwrite((void *)pCur,1,width*3,BinFile)!=(unsigned int)(3*width)) Suc=false; // 真实的数据
}
}
else
{
for(pCur=pImg+(height-1)*3*width;pCur>=pImg;pCur-=3*width)
{
if (fwrite((void *)pCur,1,width*3,BinFile)!=(unsigned int)(3*width)) Suc=false; // 真实的数据
for(i=0;i<extend;i++) // 扩充的数据
{
if (fwrite((void *)(pCur+3*(width-1)+0),1,1,BinFile)!=1) Suc=false;
if (fwrite((void *)(pCur+3*(width-1)+1),1,1,BinFile)!=1) Suc=false;
if (fwrite((void *)(pCur+3*(width-1)+2),1,1,BinFile)!=1) Suc=false;
}
}
}
// return;
fclose(BinFile);
return Suc;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// 主函数
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void main()
{
int N,i;
char fileName[100];
for(i=1;i<10;i++)
{
i = 10;
sprintf(fileName,"c:\\frames\\frame%02d.dat",i);
N= RmwLoadCbYCrData(fileName,gCbYCrData);
if (N<100) continue;
RmwDebugPalCbYCr2RGB(gCbYCrData,N,gRGBImg);
sprintf(fileName,"frame%02d.bmp",i);
RmwWrite24BitImg2BmpFile(gRGBImg,PAL_IMG_WIDTH,PAL_IMG_HEIGHT,fileName);
break;
}
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -