LIBTIFF读写黑白TIFF

一 介绍

TIFF(标记图像文件格式(Tag Image File Format))是一种最初由 Adobe 提出的光栅图像格式。 光栅图像格式将图片存储为描述像素状态的位图,而不是记录图元(譬如,线和曲线)的长度和位置。Libtiff 是 TIFF 规范的标准实现之一,目前它因其速度、强大的功能和源代码的易于获取而被广泛使用。


二. TIFF 挑战

大多数文件格式规范定义文件表示的一些基本规则。 例如,PNG 文档(TIFF 的一个竞争者)始终使用大尾数法。然而,TIFF 没有这种规定。下面的示例列出了某些看起来很基本而 TIFF 并未定义的内容:

  • 字节次序:大尾数法还是小尾数法
  • 图像字节内的位填充次序:最高位首先填充还是最低位首先填充
  • 给定的黑白象素值的含义:0 代表黑还是白?

创建 TIFF 文件很容易,因为几乎不需要对您已有的数据进行任何转换。 另一方面,它也意味着读入其它应用程序创建的随机 TIFF 会很困难 ― 所以您必须编码所有可能的组合,以确信得到可靠的产品。

那么,如何编写一个应用程序来读入 TIFF 格式的所有可能的不同排列呢? 最重要的是要记住 决不要假设正在读入的图像数据的格式。


三.写TIFF文件

具体见如下代码

 1 #include <stdio.h>
 2 #include <tiffio.h>
 3 int main(int argc, char *argv[]){
 4   // Define an image
 5   char buffer[25 * 144] = { /* 省略了16进制的图像值 */ };
 6   TIFF *image;
 7   // Open the TIFF file
 8   if((image = TIFFOpen("output.tif", "w")) == NULL){
 9     printf("Could not open output.tif for writing
");
10     exit(42);
11   }
12   // We need to set some values for basic tags before we can add any data
13   TIFFSetField(image, TIFFTAG_IMAGEWIDTH, 25 * 8); //图像的宽度
14   TIFFSetField(image, TIFFTAG_IMAGELENGTH, 144);  //图像长度
15   TIFFSetField(image, TIFFTAG_BITSPERSAMPLE, 1);  //每个像素点位数
16   TIFFSetField(image, TIFFTAG_SAMPLESPERPIXEL, 1);//每像素样本数
17   TIFFSetField(image, TIFFTAG_ROWSPERSTRIP, 144); //每个条的行数
18   TIFFSetField(image, TIFFTAG_COMPRESSION, COMPRESSION_CCITTFAX4); //压缩算法
19   TIFFSetField(image, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISWHITE); //
20   TIFFSetField(image, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB); //图像排列方式
21   TIFFSetField(image, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
22   TIFFSetField(image, TIFFTAG_XRESOLUTION, 150.0); //X分辨率
23   TIFFSetField(image, TIFFTAG_YRESOLUTION, 150.0); //Y分辨率
24   TIFFSetField(image, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH); //分辨率单位 英寸
25    
26   // Write the information to the file
27   TIFFWriteEncodedStrip(image, 0, buffer, 25 * 144); //写文件
28   // Close the file
29   TIFFClose(image); //关闭文件
30 }

 


四 读TIFF文件

  1 void testReadGrayTiff()
  2 {
  3     TIFF* image;
  4     uint16 photo, bps, spp, fillorder;
  5     uint32 width;
  6     tsize_t stripSize;
  7     unsigned long imageOffset, result;
  8     int stripMax, stripCount;
  9     char* buffer, tempbyte;
 10     unsigned long bufferSize, count;
 11  
 12     // Open the TIFF image
 13     if ((image = TIFFOpen("output.tif", "r")) == NULL) {
 14         fprintf(stderr, "Could not open incoming image
");
 15         exit(42);
 16     }
 17  
 18     // Check that it is of a type that we support
 19     if ((TIFFGetField(image, TIFFTAG_BITSPERSAMPLE, &bps) == 0) || (bps != 1)) {
 20         fprintf(stderr, "Either undefined or unsupported number of bits per sample
");
 21         exit(42);
 22     }
 23  
 24     if ((TIFFGetField(image, TIFFTAG_SAMPLESPERPIXEL, &spp) == 0) || (spp != 1)) {
 25         fprintf(stderr, "Either undefined or unsupported number of samples per pixel
");
 26         exit(42);
 27     }
 28  
 29     // Read in the possibly multiple strips
 30     stripSize = TIFFStripSize(image);
 31     stripMax = TIFFNumberOfStrips(image);
 32     imageOffset = 0;
 33  
 34     bufferSize = TIFFNumberOfStrips(image) * stripSize;
 35     if ((buffer = (char*)malloc(bufferSize)) == NULL) {
 36         fprintf(stderr, "Could not allocate enough memory for the uncompressed image
");
 37         exit(42);
 38     }
 39  
 40     for (stripCount = 0; stripCount < stripMax; stripCount++) {
 41         if ((result = TIFFReadEncodedStrip(image, stripCount,
 42             buffer + imageOffset,
 43             stripSize)) == -1) {
 44             fprintf(stderr, "Read error on input strip number %d
", stripCount);
 45             exit(42);
 46         }
 47  
 48         imageOffset += result;
 49     }
 50  
 51     // Deal with photometric interpretations
 52     if (TIFFGetField(image, TIFFTAG_PHOTOMETRIC, &photo) == 0) {
 53         fprintf(stderr, "Image has an undefined photometric interpretation
");
 54         exit(42);
 55     }
 56  
 57     if (photo != PHOTOMETRIC_MINISWHITE) {
 58         // Flip bits
 59         printf("Fixing the photometric interpretation
");
 60  
 61         for (count = 0; count < bufferSize; count++)
 62             buffer[count] = ~buffer[count];
 63     }
 64  
 65     // Deal with fillorder
 66     if (TIFFGetField(image, TIFFTAG_FILLORDER, &fillorder) == 0) {
 67         fprintf(stderr, "Image has an undefined fillorder
");
 68         exit(42);
 69     }
 70  
 71     if (fillorder != FILLORDER_MSB2LSB) {
 72         // We need to swap bits -- ABCDEFGH becomes HGFEDCBA
 73         printf("Fixing the fillorder
");
 74  
 75         for (count = 0; count < bufferSize; count++) {
 76             tempbyte = 0;
 77             if (buffer[count] & 128) tempbyte += 1;
 78             if (buffer[count] & 64) tempbyte += 2;
 79             if (buffer[count] & 32) tempbyte += 4;
 80             if (buffer[count] & 16) tempbyte += 8;
 81             if (buffer[count] & 8) tempbyte += 16;
 82             if (buffer[count] & 4) tempbyte += 32;
 83             if (buffer[count] & 2) tempbyte += 64;
 84             if (buffer[count] & 1) tempbyte += 128;
 85             buffer[count] = tempbyte;
 86         }
 87     }
 88  
 89     // Do whatever it is we do with the buffer -- we dump it in hex
 90     if (TIFFGetField(image, TIFFTAG_IMAGEWIDTH, &width) == 0) {
 91         fprintf(stderr, "Image does not define its width
");
 92         exit(42);
 93     }
 94  
 95     for (count = 0; count < bufferSize; count++) {
 96         printf("%02x", (unsigned char)buffer[count]);
 97         if ((count + 1) % (width / 8) == 0) printf("
");
 98         else printf(" ");
 99     }
100  
101     TIFFClose(image);
102 }

 


五. TIFF图像的几种类型

1.单条格式

象它的名称表述的那样,这是条纹图像的特例。在这种情况中,所有位图都存储在一个大的块中。 我在 Windows 机器上体验过单条图像的可靠性问题。通常建议一个未压缩的条不要占据 8 K 字节以上, 黑白图像限制为单条中最多为 65536 个像素。
条纹(或多条)图像

图像的水平块存储在一起。多个条垂直地连接以形成完整的位图。

2.瓦片格式

象盥洗室墙壁那样,它是由瓷砖组成的。 下图演示了这种表示法, 它可用于非常大的图像。当您想在任何时候只操纵图像的一小部分时,平铺特别有用。

原文地址:https://www.cnblogs.com/ybqjymy/p/13704518.html