前言 在 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 下載 Dependencies 和 Developer files 的檔案包,檔名分別是 tiff-3.8.2-1-dep.zip 和 tiff-3.8.2-1-lib.zip。 先解開 tiff-3.8.2-1-lib.zip,將裡頭 include 和 lib 目錄裡的檔案分別丟到 Dev-C++ 下的 include 和 lib 目錄裡。然後將 tiff-3.8.2-1-dep.zip 解開來,將 bin 目錄下的所有 *.dll 檔:glut32.dll、jpeg62.dll、libimage.dll、libpng13.dll、zlib1.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 色彩的圖檔,它也可以正常的被圖片瀏覽器開啟,但是因為沒有寫入任何色彩資料,所以是完全黑色的(Red、Green、Blue 值皆為 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 |