IMG格式详解

时间:2024-02-23 13:32:03

Img to Tif API下载:

Please Read detail info document with imagine file format at:http://home.gdal.org/projects/imagine/hfa_index.html

基本结构和基本对象

IMG文件的存储格式是HFA树,全称是Hierarchal File Format(层级文件结构),貌似是Erdas自己搞出来的东西…… 
总体来说,IMG文件是由头文件、节点存储结构和一系列节点组成,其中每个节点都有自己的头文件和存储的信息。
基本结构图:

Header 是整个文件的头文件,包括两部分内容,一个是Ehfa_HeaderTag,存储在文件最开头的地方,结构如下:

Ehfa_HeaderTag {
      char [16] label;  //对象名,就是EHFA_HEADER_TAG
      long headerPtr;  //对象Ehfa_File的位置
    }

另一个是Ehfa_File,开始位置可从上边的headerPtr 里读取,不过一般都是跟在Ehfa_HeaderTag 的后边,结构如下:

Ehfa_File {
      long version;  //版本号,通常是1
      long freelist;  //不知道是神马
      long rootEntryPtr;  //根节点的位置
      short entryHeaderLength;  //每一个节点头文件的长度
      long dictionaryPtr;  //节点存储结构列表的位置
    }

通过这个对象里的信息,可以取得根节点和节点存储结构列表的位置。

节点

从根节点开始的各个节点存放了图像的内容,而各个节点之间的联系是通过Ehfa_Entry 对象来实现的,结构如下:

Ehfa_Entry {
      long next;  //下一个节点的位置
      long prev;  //前一个节点的位置
      long parent;  //父节点的位置
      long child;  //第一个子节点的位置
      long data;  //数据的存放位置
      long datasize;  //数据大小
      char [64] name;  //节点的名字
      char [32] type;  //节点数据的存储结构
      TIME modTime;  //节点的修改时间
    }

通过next, prev, parent 和child 四个属性可以将节点联系成一棵树,而节点所存储的数据,可以通过data 属性来找到其位置。而数据的存储结构,需要在节点存储结构列表中去查找。

节点存储结构列表

Dictionary 是文件的节点存储结构列表,包括每个节点所存储的数据的结构,以及上边所说的头文件及节点本身的存储结构。比如Ehfa_Entry 对象,在列表中表述为

{1:Lnext,1:Lprev,1:Lparent,1:Lchild,1:Ldata,1:ldataSize,64:cname,32:ctype,1:tmodTime,}Ehfa_Entry

每个存储结构之间用逗号隔开,存储结构中的变量也用逗号隔开。
在每个变量的表述中,比如1:Lnext,1代表一个变量,L表示是Long型的,next是变量名。
变量类型有很多种,可以确定的有L代表Long,C代表Char,T代表Time,S代表Short,E代表Enum,D代表Double,还有一些我也不确定的,比如B可能是指Bool, pc可能代表String,po和o可能都代表Object,表示嵌入另一个存储结构。
因为变量类型有的是一个字符有的是两个,并且Enum和Object等类型的存储格式和其他类型不太一样,如下

{1:e2:no compression,RLC compression,compressionType,0:poEdms_VirtualBlockInfo,blockinfo}

除此之外还有这种我完全没能理解的存储格式

1:x{0:pcstring,}Emif_String,title

由于不方便解析,而且每个文件的存储结构基本相同,因此我把要用到的一些节点直接写为了JSON 对象,没有直接解析文件来生成节点存储结构列表。在读取节点存储数据的时候,必须从列表中查找其存储结构,才能够读取所存储的信息。

节点存储数据

IMG 格式中一个重要的节点是Eimg_Layer,一般是根节点的子节点,每个节点对应图像的一个波段。数据存储结构如下:

Eimg_Layer {
      long width;  //图层的宽度
      Long height;  //图层的长度
      enum layerType;  //图层的类型
      enum pixelType;  //图层像素的存储类型
      long blockWidth;  //图层块的宽度
      long blockHeight;  //图层块的长度
    }

IMG图像是二进制文件,并且采用的是Little-Endian模式存储。在各变量类型里,Char占一个字节,Short和Enum占两个字节,Long和Time占四个字节,Double占八个字节,String和Object的占用不固定。除了 ​​这些变量之外,一个像素占的字节数就需要通过pixelType类型来确定。另外IMG图像的一个重要特点是分块存储,一幅图像按照行列数被分成N块,然后再分块存储,blockWidth和blockHeight就是存储了每块的大小。
由于一般各图层的宽高度等属性都是相同的,我在读取的时候只读取第一波段的Eimg_Layer信息。
在Eimg_Layer节点下,包括Edms_State(像素数据),Eprj_ProParameters(投影信息),Eprj_MapInfo(地理信息)等子节点。Edms_State节点保存的是图像像素的数据,也是非常重要的节点。结构如下:

Edms_State {
      long numvirtualblocks;  //块的个数
      long numobjectsperblock;  //块的大小
      long nextobjectnum;  //不知道是神马
      enum compressiontype;  //是否压缩,0是不压缩,1是RLC压缩
      edms_VirtualBlockInfo blockinfo;  //块的信息
      edms_FreelDList freelist;  //仍然不知道是神马
      TIME modTime;  //修改时间
    }

其内嵌的两个子结构如下:

Edms_VirtualBlockInfo {
      short filecode;  //一般是0
      long offset;  //块数据的存储地址
      long size;  //块的大小
      enum logvalid;  //代表什么不了解,但一般是1
      enum compression;  //是否压缩,0是不压缩,1是ESRI GRID压缩
    }
    Edms_FreelDList {
      long min;  //大概是最小值?
      long max;  //大概是最大值?
    }

在读取内嵌子结构的时候,需要先读取两个Long型的变量,一个是子结构的重复个数,另一个是子结构的地址。之后以重复个数为循环读取子结构内部的变量,如果子结构重复个数为0,则不读取。与其类似的是String型,其预读取的第一个变量不是重复个数而是字段的长度。
在读取完Edms_State节点之后,就可以通过其子结构Edms_VirtualBlockInfo的offset和size两个属性读取每个分块的图像数据。由于IMG文件是分块存储,还必须对所有读取出来的数据进行整理,才可以形成可以显示的数据流。