文件在计算机中是以二进制存放的,文本、图像、音频、视频对于计算机来说都是一段二进制数字。那计算机怎么来区分这些不同类型的文件呢?
首先是通过文件的扩展名,但文件可以没有扩展名,而且扩展名也不一定与文件类型匹配,例如把一个txt文件扩展名改为bmp后,它还是一个文本文件而不是图片。其实大多文件的类型信息都存储在文件开头的一段二进制数字中,计算机程序通过这些信息判断出文件的类型,再根据各种类型约定的协议进行后续操作。
具体到图像部分,又可分为多种类型,如.bmp .jpg .gif .tiff等。这些不同的类型就是通过文件开头的二进制信息来区分的。下面举例来看一下:lena.bmp
用二进制文件查看器打开,左侧为16进制形式,两位对应一个字节,右侧为每个字节对应的字符:
我们看到.bmp格式的图像开头的二进制对应的内容是BM,这是位图格式文件的统一规定。其实每一种文件都有自己的标识,用于区别于其它文件类型,当开发一种新的文件类型时,就要设计一套之前没有过的标识。
在文件类型确定后,BM后面的一部分文件头信息用于描述这种类型的文件。其中前几位的用处如下:
typedef struct tagBITMAPFILEHEADER
{
WORD bfType;//位图文件的类型,必须为BM(1-2字节)
DWORD bfSize;//位图文件的大小,以字节为单位(3-6字节,低位在前)
WORD bfReserved1;//位图文件保留字,必须为0(7-8字节)
WORD bfReserved2;//位图文件保留字,必须为0(9-10字节)
DWORD bfOffBits;//位图数据的起始位置,以相对于位图(11-14字节,低位在前)
//文件头的偏移量表示,以字节为单位
}BITMAPFILEHEADER;
具体.bmp文件头部还包含什么信息,可以参考百度。
下面我们再来看一下.jpg格式的文件:lena.jpg
我们看到.jpg与.bmp格式的图像文件头信息差别很大,表示的信息也不同,所以读取时也要区别对待。其实很多图像类库都提供了统一的读取函数,不同类型的图像读进内存后是统一的格式,在此基础上进行处理,不用我们再去分类读取。
常见的图像类库有:
MFC中的CBitmap 、CImage
opencv中的IplImage 、Mat
CxImage
FreeImage
Cimg
等,具体都有什么样的特点,可以参考百度。
如果自己也想开发一套图像类库的话,就要区分不同的类型,解析不同的压缩方式,这个工作量是很大的。但是如果只是想了解一下图像内部结构的话,可以用CFile读取位图,因为位图一般没有经过压缩,易于理解。