一、TIFF文件结构:
如下图所示为TIFF图像文件基本结构:
文件结构主要分为三个小的描述结构Header+IFD+DE,下面就三个方面对文件基本组成进行讨论。
1.文件头基本组成
第1,2两个字节确定了文件数据的存储格式为大端存储或者小端存储,分为以下两种情况:
- 第一字节和第二字节的内容组成是0x4949则为Little-endian模式。
- 第一字节和第二字节的内容组成是0x4D4D则为Big-endian模式。
第2,3字节存储了TIFF的Magic Number,所有的TIFF文件都是42。
第4~7四个字节用来存储第一个IFD结构的起始位置(所有文件相关参数都要从这里开始查询)。
2.IFD结构的基本组成
第一个IFD的开头保存了当前IFD保存的DE的数量,在图中为B个,每个DE的大小是12Bytes。
如果文件的参数非常多时,就需要使用类似链表的方式扩充IFD结构,在IFD结构的末尾添加下一个IFD结构的Offset。
对于一般的真彩色图像而言,一般包括的DE的数量为:11个,这11个IFD文件结构中主要包括了图像的尺寸,图像色彩深度,图像方向等信息。
实际上IFD的功能是作为DE结构体入口的数据结构,提供了进入DE结构的门,真正的图像参数数据保存在DE结构体当中。
3.DE结构基本组成
DE结构当中是真正存储图像文件相关参数的主体,结构中的每一部分代表的内容如下:
- Tag:用来表示不同的数据域,例:图像宽度(101.H)、图像高度(100.H)、图像色彩类型(106.H),要获取DE中的内容,首先要检查当前DE中Tag代表的数据类型,然后依次读取数据即可。
- Types:用来确定当前DE域当中保存数据的格式,1=BYTE、2=ASCII、3=SHORT、4=LONG、5=RATIONAL,通过确定不同的数据格式,在读取后续数据的过程中就可以准确地将数据保存下来。
- Count:用来记录当前DE的图像参数信息有多少个Types类型的数据保存,在读取文件的过程中读取即可。
- Value:用来保存小于4Bytes的参数数据(当Count*Sizeof(Types)>4Bytes,就需要将Value当做Offset处理,从而跳转到新的起始地址,完成参数的读取)。
DE是用来保存整个图像文件参数的地方,通过从Header到IFD入口,再到每一个DE结构的入口,最后将整个图像参数提取出来,最后根据参数获取图像Data数据。
如下所示为使用AsTiffTagViewer.exe读取某一图像的结果:
二、相关TIFF文件读写代码实现:
TIFF文件C语言读取(github地址)
有志同道合的朋友可以一起迭代一下这个TIFF的库,可以私聊我!一起进步!
Header结构体展示:
IFD结构体展示:
DE结构体展示:
main.c
#include <stdio.h> #include <stdlib.h> #include <stdfix.h> #include <string.h> #include <math.h> #include "tiff.h" #include "image_alg.h" int main(void) { unsigned char *PATH = "C:/Users/Administrator/Desktop/mamiao/Alg_Cpp/image/A.tiff"; unsigned char *PATH_1 = "C:/Users/Administrator/Desktop/mamiao/Alg_Cpp/image/A1.bin"; unsigned char *PATH_2 = "C:/Users/Administrator/Desktop/mamiao/Alg_Cpp/image/A1.tiff"; unsigned char *Img=(unsigned char *)malloc(sizeof(unsigned char)*3000000); // printf("%d\n",mashine_endian()); Tiff_read(Img,PATH); FILE *fd; int i,j,k; fd = fopen(PATH_1,"wb+"); fseek(fd,0,SEEK_SET); // Insert the image data for(i=0;i<1000;i++){ for(j=0;j<1000;j++){ for(k=0;k<3;k++){ fwrite(Img+i*3000+j*3+k,sizeof(unsigned char),1,fd); } } } Tiff_write(Img,1000,1000,3,PATH_2); // printf("%d-%d-%d-%d\n",sizeof(long),sizeof(int),sizeof(char),sizeof(short)); // 4-4-1-2 printf("Finished!\n"); while(1); return 0; }