⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 debugycbcr.cpp

📁 将 AD芯片(ADV7183) 采集到的一帧数据 进行处理的程序。 处理源为 ITU656格式 entire field 模式下的整帧数据。 程序输出 每一行的EAV SAV信号坐标、 图像数据字节数
💻 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 + -