zoukankan      html  css  js  c++  java
  • 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.瓦片格式

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

  • 相关阅读:
    Java设计模式之装饰模式
    学习Emacs系列教程(二):导航
    Android ProgressDialog 延时消失
    java设计模式装饰模式
    Java 字节流和字符流的相互转换
    emacs配置颜色主题
    Android ProgressDialog的使用
    个人管理 时间管理GTD流程图
    jQuery - 列表控件推荐
    WPF - 模板查看工具:Show Me The Template及如何查看第三方主题
  • 原文地址:https://www.cnblogs.com/ybqjymy/p/13704518.html
Copyright © 2011-2022 走看看