用 LibTIFF
繪製 TIFF 圖形

Last Update : 04 / 16 / 2008 By DarkRanger .


前言

在 Dev-C++ 中使用 LibTIFF

建立 TIFF 圖形

讀取 TIFF 圖形

製作 TIFF 方格排列圖形

提醒與建議

參考網站


前言


TIFF(*.tif 或 *.tiff)是 一種高度標準化且被許多軟體與平台廣泛支援的圖檔格式,雖然它對一般的使用者而言並不常見,但在許多高階的應用領域(桌面出版與圖像分析等)都可見到它的 蹤跡。之所以會有這篇文章是因為 DR 接了個跟 TIFF 圖檔分析有關的工作,DR 在當中有嘗試使用 LibTIFF 來協助開發,LibTIFF 是一套跨平台且發展成熟的 TIFF 開發函式庫,本文所談的就是如何在程式中利用 LibTIFF 來製作 TIFF 圖檔。

附 註:為方便使用瀏覽器觀看,本文的範例圖片皆使用 GIMP 轉成 JPG 格式。

在 Dev-C++ 中使用 LibTIFF

先至 Tiff for Windows 下載 DependenciesDeveloper files 的檔案包,檔名分別是 tiff-3.8.2-1-dep.ziptiff-3.8.2-1-lib.zip。 先解開 tiff-3.8.2-1-lib.zip,將裡頭 includelib 目錄裡的檔案分別丟到 Dev-C++ 下的 include 和 lib 目錄裡。然後將 tiff-3.8.2-1-dep.zip 解開來,將 bin 目錄下的所有 *.dll 檔:glut32.dlljpeg62.dll、libimage.dlllibpng13.dllzlib1.dll 丟到預定存放自製程式的目錄,使用 LibTIFF 開發的程式必須搭配這些函式庫才能執行。

在 Dev-C++ 中建立一個 C 專案,然後在 Project→Project Options→Parameters→Linker 中加入 -llibtiff。接下來,在 程式中 include:

#include <tiffio.h>

上述步驟完成後就可以進行 TIFF 程式的開發了。

建立 TIFF 圖形

TIFF 圖檔的宣告與建立範例:

//宣告:

 TIFF *tif;

//建立 TIFF 檔:

 tif = TIFFOpen("test.tif", "w");

//最後別忘了將之關閉:

 TIFFClose(tif);

以上程式碼執行後就會產生一個名為「test.tif」的圖檔,但它沒有寫入任何資料,也無法被圖片瀏覽器打開。而以下是一個建立圖檔的完整程式碼範例:

  uint32 imageWidth, imageLength ;
  TIFF *tif;  
  unsigned char *buf;
  tstrip_t strip ;
 
  tif = TIFFOpen("test.tif", "w");
 
  imageWidth = 80 ;
  imageLength = 40 ;
 
  if ( tif )
    {
      TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, imageWidth);
      TIFFSetField(tif, TIFFTAG_IMAGELENGTH, imageLength);
         
      TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8);
      TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
      TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
         
      TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 3);
      TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP,  imageLength);
         
      TIFFSetField(tif, TIFFTAG_XRESOLUTION, 0);
      TIFFSetField(tif, TIFFTAG_YRESOLUTION, 0);  
      TIFFSetField(tif, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH);   
         
      TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
      TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
     
      buf = (char *) malloc(sizeof(uint32) * imageWidth * imageLength ) ;
     
      for (strip = 0; strip < TIFFNumberOfStrips(tif); strip++)
        { 
          unsigned char *buf_copy = buf ;
          TIFFWriteEncodedStrip(tif, strip, buf, imageWidth * imageLength * 3 ) ;
        }

       TIFFClose(tif);
        free(buf);
       printf("Done!\n");
    }
 


以上程式碼會產生一個長度 40、寬度 80、RGB 色彩的圖檔,它也可以正常的被圖片瀏覽器開啟,但是因為沒有寫入任何色彩資料,所以是完全黑色的(RedGreenBlue 值皆為 0),不過只要在原先迴圈的部份修改一下就可以繪出全白的圖形:

 uint32 Pointer ;

      for (strip = 0; strip < TIFFNumberOfStrips(tif); strip++)
        { 
          unsigned char *buf_copy = buf ;

          for ( Pointer = 0 ; Pointer <= ( imageWidth * imageLength * 3 ) ; Pointer ++ )
            {
              buf[Pointer] = 255 ;
            }

          TIFFWriteEncodedStrip(tif, strip, buf, imageWidth * imageLength * 3 ) ;
        }


以上程式碼將所有的 RGB 值皆設為 255,以此類推,再稍加修改就可以繪出完全紅色的圖形:

  uint32 Pointer ;
  int RGB_Color ;

      for (strip = 0; strip < TIFFNumberOfStrips(tif); strip++)
        { 
          unsigned char *buf_copy = buf ;
          RGB_Color = 0 ;

          for ( Pointer = 0 ; Pointer <= ( imageWidth * imageLength * 3 ) ; Pointer ++ )
            {
              RGB_Color ++ ;

              if ( RGB_Color == 1 )
                {
                  buf[Pointer] = 255 ;
                }
              else
                {
                  buf[Pointer] = 0 ;
                }
               
              if ( RGB_Color == 3 )
                {
                  RGB_Color = 0 ;
                }
            }

          TIFFWriteEncodedStrip(tif, strip, buf, imageWidth * imageLength * 3 ) ;
        }

讀取 TIFF 圖形

以下是一個複製 TIFF 圖檔的程式碼範例:

  uint32 imageWidth, imageLength, TileWidth, TileLength, imageRowsPerStrip ;
  uint16 imageCompression, imageSamplePerPixel ;
  uint16 imagePlanarConfig, imagePhotoMetric, ResolutUnit, Orientation ;
  uint16 bps ;
  float X_Resolut, Y_Resolut ;
 
  TIFF *tif_r, *tif_w ;  
  unsigned char *buf;
  tstrip_t strip ;
 
  tif_r = TIFFOpen("old.tif", "r");
 
  if ( tif_r )
    {
      tif_w = TIFFOpen("new.tif", "w");
     
      if ( tif_w )
        {
          /* 讀取 TIFF 標籤 */
          TIFFGetField(tif_r, TIFFTAG_IMAGEWIDTH, &imageWidth);
          TIFFGetField(tif_r, TIFFTAG_IMAGELENGTH, &imageLength);
     
          TIFFGetField(tif_r, TIFFTAG_BITSPERSAMPLE, &bps);
          TIFFGetField(tif_r, TIFFTAG_COMPRESSION, &imageCompression);
          TIFFGetField(tif_r, TIFFTAG_PHOTOMETRIC, &imagePhotoMetric);
     
          TIFFGetField(tif_r, TIFFTAG_SAMPLESPERPIXEL, &imageSamplePerPixel);
          TIFFGetField(tif_r, TIFFTAG_ROWSPERSTRIP, &imageRowsPerStrip);

          TIFFGetField(tif_r, TIFFTAG_XRESOLUTION, &X_Resolut);
          TIFFGetField(tif_r, TIFFTAG_YRESOLUTION, &Y_Resolut);
          TIFFGetField(tif_r, TIFFTAG_RESOLUTIONUNIT, &ResolutUnit);

          TIFFGetField(tif_r, TIFFTAG_PLANARCONFIG, &imagePlanarConfig);
          TIFFGetField(tif_r, TIFFTAG_ORIENTATION, &Orientation);
         
          /* 寫入 TIFF 標籤 */
          TIFFSetField(tif_w, TIFFTAG_IMAGEWIDTH, imageWidth);
          TIFFSetField(tif_w, TIFFTAG_IMAGELENGTH, imageLength);
         
          TIFFSetField(tif_w, TIFFTAG_BITSPERSAMPLE, bps);
          TIFFSetField(tif_w, TIFFTAG_COMPRESSION, imageCompression);
          TIFFSetField(tif_w, TIFFTAG_PHOTOMETRIC, imagePhotoMetric);
         
          TIFFSetField(tif_w, TIFFTAG_SAMPLESPERPIXEL, imageSamplePerPixel);
          TIFFSetField(tif_w, TIFFTAG_ROWSPERSTRIP, imageRowsPerStrip);
         
          TIFFSetField(tif_w, TIFFTAG_XRESOLUTION, X_Resolut);
          TIFFSetField(tif_w, TIFFTAG_YRESOLUTION, Y_Resolut);  
          TIFFSetField(tif_w, TIFFTAG_RESOLUTIONUNIT, ResolutUnit);   
         
          TIFFSetField(tif_w, TIFFTAG_PLANARCONFIG, imagePlanarConfig);
          TIFFSetField(tif_w, TIFFTAG_ORIENTATION, Orientation);
         
          buf = (char *) malloc(sizeof(uint32) * imageWidth * imageLength ) ;
         
          for (strip = 0; strip < TIFFNumberOfStrips(tif_r); strip++)
            {
              TIFFReadEncodedStrip(tif_r, strip, buf, (tsize_t) -1);
              unsigned char *buf_copy = buf ;
              TIFFWriteEncodedStrip(tif_w, strip, buf, imageWidth * imageLength * imageSamplePerPixel ) ;
            }
          TIFFClose(tif_w);
          free(buf);
        }
      TIFFClose(tif_r);
    }
 
  printf("Done!\n");

以上程式碼會將「old.tif」圖檔複製出一個新的「new.tif」圖檔。假設要將一張黑白色圖形的色彩顛倒再重新輸出成一張新的圖形,其添加的程式碼如下:

 uint32 Pointer ;

          for (strip = 0; strip < TIFFNumberOfStrips(tif_r); strip++)
            {
              TIFFReadEncodedStrip(tif_r, strip, buf, (tsize_t) -1);
              unsigned char *buf_copy = buf ;
              for ( Pointer = 0 ; Pointer <= ( imageWidth * imageLength * 3 ) ; Pointer ++ )
                {
                  if ( buf[Pointer] == 255 )
                    {
                      buf[Pointer] = 0 ;
                    }
                  else
                   {
                     buf[Pointer] = 255 ;
                   }
                }
              TIFFWriteEncodedStrip(tif_w, strip, buf, imageWidth * imageLength * imageSamplePerPixel ) ;
            }

以上程式碼執行後就會產生如以下兩張圖的轉換效果:


08/03/2016 公告:
事隔多年,今日才發現本文接下來的內容都因未知因素損毀了。而且更不幸的是,連現有最久遠的網頁備份(2013 年)裡,所收藏的也是同樣損毀的版本,真是不好意思!原先本文接著會提及的原始碼在此:main.c,以及輸出的圖檔範例為:dr_tiff_3.jpg
-DR