多媒体编程
实验一 报告
2008212519_王俊华



多媒体编程实验一报告


实验过程



  1. 分析bmp文件格式
    ,格式见附录一


  2. 以最精简最实用的结构定义CBmp类,将作业中所需的操作封装到该类


  3. 实现文档/视图结构


  4. 在实验中记录遇到的问题






程序框架


文档/视图结构


CBmp类封装了对Bmp文件的读操作和显示,以及将当前取得的RGB值转化为亮度值


详细结构如图一



图一


CBmpViewerDoc 中添加
CBmp *bmp 成员,作为载入的位图对象存储,实现如下两个成员函数:



  1. 菜单
    作业
    ->信息头分析
    OnToText(); //解析bmp文件头信息,并写入文本


  2. 菜单
    作业
    ->RGB转成YUV
    OnToYUV(); //bmp图片像素阵列输出亮度值到文本






CBmpViewerview
中修改OnDraw()
函数,以显示bmp图片;


CBmpViewerview
中修改OnInitialUpdate()
函数,以实现滚屏视图;





软件操作方法



  1. 显示
    通过文件
    ->打开
    bmp图片即可


  2. 读取头文件
    菜单 作业
    ->信息头分析
    然后在打开的文件夹里
    选择合适的
    txt文本
    或者直接新建


  3. bmp图片像素阵列输出亮度值到文本
    菜单 作业
    ->RGB转成YUV






实验中遇到的问题及相关解决方法



  1. CString的格式化输出



%c 单个字符


%d 十进制整数


%f 十进制浮点数


%o 八进制数


%s 字符串


%u 无符号十进制数


%x 十六进制数


%% 输出百分号%





一个格式说明可以带有几个修饰符,用来指定显示宽度,小数尾数及左对齐等:


- 左对齐


+ 在一个带符号数前加'+''-'



  1. 域宽用前导零来填充,而不是用空白符






域宽是一个整数,设置了打印一个格式化字符串的最小域。精度使用小数点后加数字表示的,给出每个转换说明符所要输出的字符个数。


注意:带修饰符的显示可能不正常。


数据格式说明由“%”开头,形式为
%<数据输出宽度说明><格式符>,数据格式说明用在需要输出变量或运算数值结果的时候,它的个数与输出表列的个数一一对应。


数据宽度说明中如果实际数据小于宽度,则根据宽度是否大于零而左补空格或右补空格。如果实际数据大于宽度,按实际位数输出。如果缺省宽度说明,则按实际宽度输出。


CString.format('%10f',
a);


10表示把a10个字符宽度格式化


%f形式输出,则小数部分为6位;






%10f


a的整数部分位数+小数点(1)+小数部分位数大于等于10,则按实际a的形式格式化;


a的整数部分位数+小数点(1)+小数部分位数小于10,则在前面补空格,补足10位;






%.7f


a的小数部分位数若大于7,则截取7位小数,整数部分不变;


a的小数部分位数若小于等于7,则不满7位的部分后面以0补足;





str.Format(_T('Left-justified
integer: %.6d\n'), b);


%.6d


若整数b不满6位则在最高为前面补0


若整数b大于等于6位则形式不变;





%6d


若整数b不满6,则在最高位前面补上空格,是之格式化为6个字符宽度;


若整数b大于等于6位则形式不变。






  1. CFile 遇到的文件读写错误和指针定位



CFile定义的文件,在读写操作结束的时候一定要close(),否则会造成文件共享错误;


文件读写是从类型或者结构的末端开始的。


CFile->Read()
读取文件结束后,指针就停留在结构末端,下一次读取的时候不用调用seek
重新定位文件指针。






  1. 指针转换的学习




ptrHeader
= (BITMAPFILEHEADER*) bmPtr;



ptrInfo
= (BITMAPINFO*) &bmPtr[sizeof(BITMAPFILEHEADER)];



ptrBits
= &bmPtr[ptrHeader->bfOffBits];



指针可以根据结构的长度
自动截断原指针所指向结构的长度



可以方便的把某个指针的一部分快速的赋给另一个指针







  1. Dib位图显示




int
StretchDIBits(



HDC
hdc, // handle to DC



int
XDest, // x-coord of destination upper-left corner



int
YDest, // y-coord of destination upper-left corner



int
nDestWidth, // width of destination rectangle



int
nDestHeight, // height of destination rectangle



int
XSrc, // x-coord of source upper-left corner



int
YSrc, // y-coord of source upper-left corner



int
nSrcWidth, // width of source rectangle



int
nSrcHeight, // height of source rectangle



CONST
VOID *lpBits, // bitmap bits



CONST
BITMAPINFO *lpBitsInfo, // bitmap data



UINT
iUsage, // usage options



DWORD
dwRop // raster operation code



);







int
SetDIBitsToDevice(



HDC
hdc, // handle to DC



int
XDest, // x-coord of destination upper-left corner



int
YDest, // y-coord of destination upper-left corner



DWORD
dwWidth, // source rectangle width



DWORD
dwHeight, // source rectangle height



int
XSrc, // x-coord of source lower-left corner



int
YSrc, // y-coord of source lower-left corner



UINT
uStartScan, // first scan line in array



UINT
cScanLines, // number of scan lines



CONST
VOID *lpvBits, // array of DIB bits



CONST
BITMAPINFO *lpbmi, // bitmap information



UINT
fuColorUse // RGB or palette indexes



);



  1. 调色板的创建



调色板的存在到底有什么用处,还不是很清楚,只是猜测可能每次在dc上画图,用逻辑调色板修改系统调色板,可以将系统调色板缺少的颜色都补上,使得图片显色的时候保真。


调色板是通过logPalette创建的。把代码贴在这里,以防遗忘……






附录一


位图文件分为四部分:


1)位图文件头BITMAPFILEHEADER


  位图文件头BITMAPFILEHEADER是一个结构体,长度为14字节,定义为:


typedef struct
tagBITMAPFILEHEADER


{


 WORD
bfType; //文件类型,必须是0x424D,即字符串"BM"


 DWORD
bfSize; //文件大小,包括BITMAPFILEHEADER14个字节


 WORD
bfReserved1; //保留字


 WORD
bfReserved2; //保留字


 DWORD
bfOffBits; //从文件头到实际的位图数据的偏移字节数


} BITMAPFILEHEADER;





2)位图信息头BITMAPINFOHEADER


  位图信息头BITMAPINFOHEADER也是一个结构体,长度为40字节,定义为:


typedef struct
tagBITMAPINFOHEADER


{


 DWORD
biSize; //本结构的长度,为40


 LONG
biWidth; //图象的宽度,单位是象素


 LONG
biHeight; //图象的高度,单位是象素


 WORD
biPlanes; //必须是1


 WORD
biBitCount;


 //表示颜色时要用到的位数,1(单色),
4(16),
8(256),
24(真彩色)


 DWORD
biCompression;


 //指定位图是否压缩,有效的值为BI_RGBBI_RLE8BI_RLE4BI_BITFIELDS等,BI_RGB表示不压缩


 DWORD
biSizeImage;


 //实际的位图数据占用的字节数,即
biSizeImage=biWidth’ ×
biHeightbiWidth’biWidth
按照4的整倍数调整后的结果


 LONG
biXPelsPerMeter; //目标设备的水平分辨率,单位是每米的象素个数


 LONG
biYPelsPerMeter; //目标设备的垂直分辨率,单位是每米的象素个数


 DWORD
biClrUsed; //位图实际用到的颜色数,0表示颜色数为2biBitCount


 DWORD
biClrImportant; //位图中重要的颜色数,0表示所有颜色都重要


} BITMAPINFOHEADER;





3)调色板Palette


  调色板Palette针对的是需要调色板的位图,即单色、16色和256色位图。对于不以调色板方式存储的位图,则无此项信息。调色板是一个数组,共有biClrUsed个元素(如果该值为0,则有2biBitCount个元素)。数组中每个元素是一个RGBQUAD结构体,长度为4个字节,定义为:


typedef struct
tagRGBQUAD


{


 BYTE
rgbBlue; //蓝色分量


 BYTE
rgbGreen; //绿色分量


 BYTE
rgbRed; //红色分量


 BYTE
rgbReserved; //保留值


} RGBQUAD;


4)实际的位图数据ImageDate


  对于用到调色板的位图,实际的图象数据ImageDate为该象素的颜色在调色板中的索引值;对于真彩色图,图象数据则为实际的RGB值:


  a.单色位图:用1bit就可以表示象素的颜色索引值;


  b.16色位图:用4bit可以表示象素的颜色索引值;


  c.
256色位图:1个字节表示1个象素的颜色索引值;


  d.真彩色:3个字节表示1个象素的颜色RGB值。


  此外,位图数据每一行的字节数必须为4的整倍数,如果不是,则需要补齐。奇怪的是,位图文件中的数据是从下到上(而不是从上到下)、从左到右方式存储的。


详细位移结构见表01



01
位图文件结构内容摘要








































































































































 



偏移量



域的名称



大小



内容




 



 



 



图象文件





0000h



文件标识



2
bytes




两字节的内容用来识别位图的类型:



BM'
Windows
3.1x, 95, NT, ...



BA'
OS/2
Bitmap Array



CI'
OS/2
Color Icon



CP'
OS/2
Color Pointer



IC'
OS/2
Icon



PT'
OS/2
Pointer



注:因为OS/2系统并没有被普及开,所以在编程时,你只需判断第一个标识"BM"就行。



 



0002h



File
Size



1
dword



用字节表示的整个文件的大小



 



0006h



Reserved



1
dword



保留,必须设置为0



 



000Ah



Bitmap
Data Offset



1
dword



从文件开始到位图数据开始之间的数据(bitmap
data)
之间的偏移量



 



000Eh



Bitmap
Header Size



1
dword




位图信息头(Bitmap
Info Header)
的长度,用来描述位图的颜色、压缩方法等。下面的长度表示:



28h - Windows
3.1x, 95, NT, ...



0Ch - OS/2 1.x



F0h - OS/2 2.x



注:在Windows95982000等操作系统中,位图信息头的长度并不一定是28h,因为微软已经制定出了新的BMP文件格式,其中的信息头结构变化比较大,长度加长。所以最好不要直接使用常数28h,而是应该从具体的文件中读取这个值。这样才能确保程序的兼容性。



 



0012h



Width



1
dword



位图的宽度,以象素为单位



 



0016h



Height



1
dword



位图的高度,以象素为单位



 



001Ah



Planes



1
word



位图的位面数(注:该值将总是1





图象



信息







 



 



001Ch



Bits
Per Pixel



1
word




每个象素的位数



1 -
单色位图(实际上可有两种颜色,缺省情况下是黑色和白色。你可以自己定义这两种颜色)



4 - 16 色位图



8 - 256 色位图



16 - 16bit
高彩色位图



24 - 24bit
真彩色位图



32 - 32bit
增强型真彩色位图



 



001Eh



Compression



1
dword




压缩说明:



0 - 不压缩
(使用BI_RGB表示)



1 - RLE
8-
使用8RLE压缩方式(BI_RLE8表示)



2 - RLE
4-
使用4RLE压缩方式(BI_RLE4表示)



3 -
Bitfields-
位域存放方式(BI_BITFIELDS表示)



 



0022h



Bitmap
Data Size



1
dword



用字节数表示的位图数据的大小。该数必须是4的倍数



 



0026h



HResolution



1
dword



用象素/米表示的水平分辨率



 



002Ah



VResolution



1
dword



用象素/米表示的垂直分辨率



 



002Eh



Colors



1
dword



位图使用的颜色数。如8-比特/象素表示为100h或者
256.



 



0032h



Important
Colors



1
dword



指定重要的颜色数。当该域的值等于颜色数时(或者等于0时),表示所有颜色都一样重要



调色板数据



根据BMP版本的不同而不同



Palette



N
* 4 byte




调色板规范。对于调色板中的每个表项,这4个字节用下述方法来描述RGB的值:


Frame1



图象数据



根据BMP版本及调色板尺寸的不同而不同



Bitmap
Data



xxx
bytes



该域的大小取决于压缩方法及图像的尺寸和图像的位深度,它包含所有的位图数据字节,这些数据可能是彩色调色板的索引号,也可能是实际的RGB值,这将根据图像信息头中的位深度值来决定。








~
1
~




Comments (0)