来自个人百度空间的文章---2011.2.13
一、位图文件结构
位图文件由三部分组成:文件头 + 位图信息 + 位图像素数据
1、位图文件头。位图文件头主要用于识别位图文件。以下是位图文件头结构的定义:
typedef struct tagBITMAPFILEHEADER {
// bmfh WORD bfType;
DWORD bfSize;
WORD bfReserved1;
WORD bfReserved2;
DWORD bfOffBits; } BITMAPFILEHEADER;其中的bfType值应该是“BM”(0x4d42),标志该文件是位图文件。bfSize的值是位图文件的大小。
2、位图信息中所记录的值用于分配内存,设置调色板信息,读取像素值等。以下是位图信息结构的定义:
typedef struct tagBITMAPINFO {
BITMAPINFOHEADER bmiHeader;
RGBQUAD bmiColors[1];} BITMAPINFO;可见位图信息也是由两部分组成的:位图信息头 + 颜色表
3.BITMAPINFOHEADER 位头信息头。(此信息在压缩,解压时有用)
位图信息头包含了单个像素所用字节数以及描述颜色的格式,此外还包括位图的宽度、高度、目标设备的位平面数、图像的压缩格式。以下是位图信息头结构的定义:typedef struct tagBITMAPINFOHEADER{ // bmih DWORD biSize; LONG biWidth; LONG biHeight; WORD biPlanes; WORD biBitCount DWORD biCompression; DWORD biSizeImage; LONG biXPelsPerMeter; LONG biYPelsPerMeter; DWORD biClrUsed; DWORD biClrImportant; } BITMAPINFOHEADER; 下表是对结构体当中各个成员的说明:
结构成员
说 明biSize结构BITMAPINFOHEADER的字节数,即sizeof(BITMAPINFOHEADER)*biWidth
以像素为单位的图像宽度*biHeight
以像素为单位的图像长度*biplanes
目标设备的位平面数--区分2D 3D?NO This value must be set to 1biBitCount
每个像素的位数*--像素的比特数 有自己的范围 1 2 4 8 16 24 32biCompression
图像的压缩格式 有自己的范围biSizeImage
以字节为单位的图像数据的大小(对BI_RGB压缩方式而言)biXPelsPermeter
水平方向上的每米的像素个数biYpelsPerMeter
垂直方向上的每米的像素个数biClrused
调色板中实际使用的颜色数--图像实际颜色和数字图像的颜色有差距需要调整?biClrImportant
现实位图时必须的颜色数 If this value is zero, all colors are required.
二、COMPVARS(压缩器)
//设置COMPVARS结构
//手工设置COMPVARS结构
m_CV.dwFlags=ICMF_COMPVARS_VALID;
//COMPVARS结构大小
m_CV.cbSize=sizeof(m_CV);
//使用divx编码器
m_CV.fccHandler=mmioFOURCC('d','i','v','x');
//编码器类型
m_CV.fccType=ICTYPE_VIDEO;
//打开编码器,hic为编码器句柄
m_CV.hic=ICOpen(ICTYPE_VIDEO,mmioFOURCC('d','i','v','x'),ICMODE_COMPRESS);
//数据速率(kb/s)
m_CV.lDataRate=780;
//关键帧率
m_CV.lKey=15;
//默认质量设置
m_CV.lQ=ICQUALITY_DEFAULT;
//保留字段
m_CV.lKeyCount=0;
m_CV.lpbiIn=NULL;
m_CV.lpBitsOut=NULL;
m_CV.lpBitsPrev=NULL;
m_CV.lpState=NULL;
m_CV.cbState=0;
m_CV.lFrame=0;
远程视频压缩与解压缩的全过程详解(压缩-传输-解压)
发送端
1.BITMAPINFO m_InInfo;//初始化编码器输入格式
capSetVideoFormat(ghWndCap,&m_InInfo,sizeof(BITMAPINFO));//设置格式
2.COMPVARS m_CV;//编码器设置
m_CV.hic=ICOpen(ICTYPE_VIDEO,mmioFOURCC('d','i','v','x'),ICMODE_COMPRESS);//打开编码器,hic为编码器句柄
3.BITMAPINFO *m_pOutInfo;//设置编码器输出格式
m_OutFormatSize=ICCompressGetFormatSize(m_CV.hic,&m_InInfo);//编码器输出格式大小
m_pOutInfo=(BITMAPINFO *)new BYTE[m_OutFormatSize];//编码器输出格式
ICCompressGetFormat(m_CV.hic,&m_InInfo,m_pOutInfo);//设置编码器格式
4.ICSeqCompressFrameStart(&m_CV,&m_InInfo);//初始化资源,为编码帧序列做好准备
5.BYTE* Buf=(BYTE*)ICSeqCompressFrame(&m_CV,0,lpVHdr->lpData,&bKeyFrame,(long*)&m_OutActSize);//编码压缩
socket发送流-------------(得先发送m_InInfo和m_CV通知接受端使用什么样的格式和压缩器,然后发送数据lpVHdr->lpData)
接收端
1.COMPVARS m_CV;//解码器
m_CV.hic=ICOpen(m_CV.fccType,m_CV.fccHandler,ICMODE_DECOMPRESS);
2.BITMAPINFO *m_spOutInfo;//设置解码器输出格式
m_sOutFormatSize=ICDecompressGetFormatSize(m_CV.hic,&m_InInfo.bmiHeader); //设置解码数据输出格式的大小
m_spOutInfo=(BITMAPINFO*)new BYTE[m_sOutFormatSize];
ICDecompressGetFormat(m_CV.hic,&m_InInfo,m_spOutInfo); //设置编码器输出格式
3.DWORD m_spOutBuf;//设置输出缓存
m_sOutBufSize=m_spOutInfo->bmiHeader.biSizeImage;//输出缓存大小
m_spOutBuf=new BYTE[m_sOutBufSize];//输出缓存
memset(m_spOutBuf,0,m_sOutBufSize);//初始化输出缓存
4.ICDecompressBegin(m_CV.hic,&m_InInfo,m_spOutInfo);//开始解压
5.ICDecompress(m_CV.hic,0,&m_InInfo.bmiHeader,VideoData.Buf,&m_spOutInfo->bmiHeader,m_pOutBuf)
//解压
6.SetDIBitsToDevice//直接在显示器上显示位图