代码改变世界

图像的一般格式

2016-04-17 19:29  GarfieldEr007  阅读(637)  评论(0编辑  收藏  举报

摘要:描述了各种图像文件结构,尤其着重讲述了PPM文件格式以及PPM文件的读写。因为最近在使用PPM文件做图像处理,以前并未接触到,所以会特别关注。 

 

   一般的图像文件结构主要都包含有文件头、文件体和文件尾等三部分:

    文件头:软件ID、软件版本号、图像分辨率、图像尺寸、图像深度、彩色类型、编码方式、压缩算法

   文件体:图像数据、彩色变换表

   文件尾:用户名、注释、开发日期、工作时间
   以上是一个大概的图像文件结构说明,实际的结构根据不同的格式其中的条目要细得多,结构也复杂得多,各个条目所占空间及条目间的排列顺序也大不相同。目前还没有非常统一的图像文件格式。但大多数图像处理软件都与数种图像文件格式相兼容,也即可读取多种不同格式的图像文件。这样,不同的图像格式间可相互转换。当然,还有专门的图像格式转换软件,用于各种图像格式间的转换。

BMP格式
BMP是一种与硬件设备无关的图像文件格式,使用非常广。它采用位映射存贮格式,除了图像深度可选以外,不采用其它任何压缩,因此,BMP文件所占用的空间很大。BMP文件的图像深度可选1bit、4 bit、8 bit及24bit。BMP文件存储数据时,图像的扫描方式是按从左到右、从下到上的顺序。
PCX格式
是PC 画笔的图像文件格式。PCX的图像深度可选为1、4、8bit。由于这种文件格式出现较早,它不支持真彩色。PCX文件采用RLE行程编码,文件体中存放的是压缩后的图像数据。因此,将采集到的图像数据写成PCX文件格式时,要对其进行RLE编码;而读取一个PCX文件时首先要对其进行RLE解码,才能进一步显示和处理。
TIFF格式
TIFF(Tag Image FileFormat)文件是由Aldus和Microsoft公司为扫描仪和桌上出版系统研制开发的一种较为通用的图像文件格式。TIFF格式灵活易变,它又定义了四类不同的格式:TIFF-B适用于二值图像;TIFF-G适用于黑白灰度图像;TIFF-P适用于带调色板的彩色图像;TIFF-R适用于RGB真彩图像。TIFF支持多种编码方法,其中包括RGB无压缩、RLE压缩及JPEG压缩等。
GIF格式
GIF(Graphics Interchange Format)是CompuServe公司在1987年开发的图像文件格式,1989年在1987年版本基础上进行了扩充,扩充后的版本号定义为GIF89a,而1987年版本则为GIF87a。GIF采用LZW压缩算法来存储图象数据,并采用了可变长度等压缩算法。GIF的图像深度从1bit到8bit,也即GIF最多支持256种颜色的图像。GIF格式的另一个特点是其在一个GIF文件中可以存多幅彩色图像,如果把存于一个文件中的多幅图像数据逐幅读出并显示到屏幕上,就可构成一种最简单的动画。

SWF格式
SWF(Shock WaveFlash)是Macromedia公司软件Flash生成的一种动画文件格式。这是一种网络矢量图形标准,压缩率高,但需要Flash软件或插件才能播放

JPEG格式
JPEG(Joint Photographic ExpertsGroup)是由CCITT(国际电报电话咨询委员会)和ISO(国际标准化组织)联合组成的一个图像专家组。该专家组制定的第一个压缩静态数字图像的国际标准,其标准名称为“连续色调静态图像的数字压缩和编码(DigitalCompression and Coding of Continuous - tone StillImage)”,简称为JPEG算法。这是一个适用范围很广的通用标准,其目标如下:

   1.开发的算法在图像压缩率方面是 /或接近当前的科学水平,图像的保真度在较宽的压缩范围里的评价是“很好”、“优秀”到与原图像“不能区别”。

   2.开发的算法可实际应用于任何一类数字图像源,如对图像的大小、颜色空间、像素的长宽比、图像的内容、复杂程度、颜色数及统计特性等都不加限制。

   3.对开发的算法,在计算的复杂程度方面可以调整,因而可根据性能和成本要求来选择用软件执行还是用硬件执行。

    4.开发的算法包括四种编码方式:如顺序编码、累进编码、无损压缩编码和分层编码等。

   JPEG采用对称的压缩算法,也即在同一系统环境下压缩和解压缩所用的时间相同。采用JPEG压缩编码算法压缩的图像,其压缩比约为1:5至1:50,甚至更高。

PNG格式
PNG(Portable Network Graphic Format,便携式网络图象格式)是W3C组织在20世纪90年代中期开始开发的一种无损位图文件存储格式,1996年10月1日正式公布,是一种轻便、无法律障碍、压缩性能好且规范好的一个标准,其目的是企图替代GIF和TIFF,同时增加一些它们文件格式所不具备的特性。PNG名称来源于非官方的“PNG'sNot GIF”,是一种位图文件(bitmapfile)存储格式,读成“ping”。PNG支持索引彩色、灰度和真彩色,并提供可选的α通道。用来存储灰度图象时,灰度图象的深度可多达16位(bit),存储彩色图象时,彩色图象的深度可多达48位(bit),并且还可存储多达16位的α通道数据。PNG图象格式文件(或者称为数据流)由一个8字节的PNG文件署名(PNG filesignature)域和按照特定结构组织的3个以上的数据块(chunk)组成。PNG定义了两种类型的数据块,一种是称为关键数据块(criticalchunk),这是标准的数据块;另一种叫做辅助数据块(ancillarychunks),这是可选的数据块。关键数据块定义了4个标准数据块,每个PNG文件都必须包含它们,PNG读写软件也都必须要支持这些数据块。虽然PNG文件规范没有要求PNG编解码器对可选数据块进行编码和解码,但规范提倡支持可选数据块。

 

特别关注PPM

PPM灰度文件:

文件头由3行文本组成,可由fgets读出

1)第一行为“P2",表示文件类型

2)第二行为图像的宽度和高度

3)第三行为最大的象素值255
接下来是图像数据块。按行顺序存储。每个象素占4个字节,灰度通道为4字节ASCII码表示的整数,高字节在前。左上角为坐标原点。


16位PPM文件:(至少适用于读取由DCRAW生成的PPM文件)

文件头由3行文本组成,可由fgets读出

1)第一行为“P6",表示文件类型

2)第二行为图像的宽度和高度

3)第三行为最大的象素值

接下来是图像数据块。按行顺序存储。每个象素占6个字节,依次为红绿蓝通道,每个通道为2字节整数,高字节在前。

 

PPM彩色文件:

文件头由3行文本组成,可由fgets读出

1)第一行为“P3",表示文件类型

2)第二行为图像的宽度和高度

3)第三行为最大的象素值255

接下来是图像数据块。按行顺序存储。每个象素占12个字节,依次为红绿蓝通道,每个通道为4字节ASCII码表示的整数,高字节在前。左上角为坐标原点。

 

PPM文件的读写

  #ifndef   PNM_FILE_H 
  #define  PNM_FILE_H     
  #include   <cstdlib> 
  #include   <climits> 
  #include   <cstring> 
  #include   <fstream> 
  #include   "image.h" 
  #include   "misc.h" 
  #include  <iostream.h>//for  debug,qiansen      
  #define   BUF_SIZE 256   
   
  class pnm_error  {   };

 static image<rgb> *loadPPM(const char *name)  {  
      char  buf[BUF_SIZE], doc[BUF_SIZE]; 
      
      
     std::ifstream file(name, std::ios::in |std::ios::binary);  
     pnm_read(file,   buf);  
     if (strncmp(buf, "P5", 2)){ 
         //throw pnm_error();  
         cout<<"pnmversion  is P6,may be not supported."<<endl; 
      } 
     pnm_read(file, buf);  
      intwidth = atoi(buf); 
     pnm_read(file, buf);  
     int height = atoi(buf); 
   
     pnm_read(file, buf);  
     if(atoi(buf)>UCHAR_MAX)  
        throw pnm_error();  
   
      
     image<rgb> *im = new image<rgb>(width,  height);  
     file.read((char*)imPtr(im,0,0), width * height *sizeof(rgb));   
     return im;  
  }  
   
 static void savePPM(image<rgb>*im, constchar *name)   {  
      intwidth = im->width();  
      int height= im->height();  
     std::ofstream file(name, std::ios::out | std::ios::binary); 
   
     file<<"P6\n"<<width<<" "<<height<<"\n"<<UCHAR_MAX<<"\n"; 
     file.write((char*)imPtr(im,0,0),width * height *sizeof(rgb));  
  }  

参考文献:

[1]http://topic.csdn.net/t/20050912/10/4263160.html
[2]http://www.kylinx.net/node/55
[3]http://blog.csdn.net/begtostudy/archive/2006/10/13/1332750.aspx

转自:http://blog.163.com/jianweicheng@126/blog/static/3567320220071122112155300/

 

from: http://blog.csdn.net/yangtrees/article/details/7731762