chl00100的笔记 https://bbs.21ic.com/?432396 [收藏] [复制] [RSS]

日志

函数fopen的参数”w”与”wb”在图像处理中引发的问题(ZT)

已有 1364 次阅读2008-6-17 10:24 |个人分类:学习资料|系统分类:视频音频

 

      函数fopen是一个标准c函数,其功能是打开一个文件,之后便可以进行读或写的操作.其原型是这样的:
FILE *fopen( const char *filename, const char *mode );

第一个参数是要打开文件的名字(路径),第二个参数是打开文件所用的模式.对于模式参数的”w””wb”,”r””rb”,我起初并不是很理解,按照课本上的说法,”w”是以文本的形式进行写入,”wb”是以二进制模式进行写入.这样的解释令人感觉有点玄乎,不能准确理解.


 


       最近写了一个小程序用从文本中读取数据,进行一定处理后转换为位图图像.数据格式大概是这样:


0.005      0.083      0.083      0.078      0.078      0.044      0.049      0.049      0.044      0.044      0.044      0.039      0.034       0.039      0.034      0.029      0.029      0.034      0.029      0.029      0.029      0.020      0.015      0.005      0.000      0.005       0.000      0.010…


经过处理后得到的图像大概是这样的:


.


而令我感到很奇怪的是,我同学用几乎和我差不多的代码得出的图像颜色上却有很大不同:



显然,初衷是显示256色的灰度图,而他得出的图形却是偏绿的,有点奇怪.仔细想想,之所以会呈现绿色,应该跟调色板有关系,估计是色调的映射出了点问题.而调色板的初始化我们都是这么写的:


       for( int i=0;i<256;i++ )  


       {  


              m_pRGBQuad.rgbBlue= i;


              m_pRGBQuad.rgbGreen = i;


              m_pRGBQuad.rgbRed = i;


              m_pRGBQuad.rgbReserved = 0;


       }


从其初始化来看,应该是没有问题的,那问题出在哪里呢?


 


于是我用ultraedit打开了两幅图像,发现它们的前五行都是一样的,而第二幅图第六行是这样的:


00000050h: 06 00 07 07 07 00 08 08 08 00 09 09 09 00 0D 0A ; ................


00000060h: 0D 0A 0D 0A 00 0B 0B 0B 00 0C 0C 0C 00 0D 0D 0D ; ................


第一幅图:


00000050h: 06 00 07 07 07 00 08 08 08 00 09 09 09 00 0A 0A ; ................


00000060h: 0A 00 0B 0B 0B 00 0C 0C 0C 00 0D 0D 0D 00 0E 0E ; ................


可以很清楚的看到,第一幅图的30A都被替换成了0D0A,而除此之外的数据都是一样的.于是图像呈绿色的原因就明了了:由于0A变成了0D0A,造成了数据的整体向后偏移,于是调色板的数据被破坏,所以无法显示正常的灰度图像.


 


       那么,是什么原因造成这样的差异呢?几经调试之后,终于发现是fopen的参数引起的.如果这么写   


fpOut = fopen( strOut, "wb" );


可以得到正常的图像,


       fpOut = fopen( strOut, "w" );


得到的就是绿色的图像.看来是参数”w””wb”造成的差异.为什么呢?让我们看看msdn的描述:


b   Open in binary (untranslated) mode; translations involving carriage-return and linefeed characters are suppressed.


If t or b is not given in mode, the default translation mode is defined by the global variable _fmode. If t or b is prefixed to the argument, the function fails and returns NULL.


原来,如果有参数b,是以二进制方式打开,这种方式不会进行回车符换行符的转换.而如果没有b,即单以”w”为参数的话,系统就把换行符0A转换为0D0A,因为windows是以0D0A为换行符的.


       至此,总算是弄明白了所谓二进制打开和文本打开的区别,真晕.-.-b

 

 


所以,以后进行数据处理时要小心了,当然,如果你已经不用fopen那估计就万事大吉,这篇文章算是白看了,呵呵~


路过

鸡蛋

鲜花

握手

雷人

评论 (0 个评论)