
『TIFF圖檔』『Tagged Image File Format』『標記圖檔格式』.擴展名『.tif』或『.tiff』.
首先去『官網』下載tiff圖檔格式指南『tiff6.pdf』.
| https://www.itu.int/itudoc/itu-t/com16/tiff-fx/docs/tiff6.pdf |
| https://download.osgeo.org/libtiff/doc/TIFF6.pdf |
話明係『標記』. 所有數據由『標記』組成. 數據類型多, 長度可變. 支持多種壓縮, 包括『有損壓縮』仝『冇損壓縮』.
『TIFF圖檔』由三個結构體組成
| TIFF圖檔結构體 | 簡述 |
| Image File Header(IFH) | 圖檔頭 |
| Image File Directory(IFD) | 目錄, 保存Directory Entry |
| Directory Entry(DE) | 目錄項-愛蒞保存數據 |
『TIFF圖檔』必定以『Image File Header(IFH)』開始,與眾吾仝係可以保存成『little-endian』或者『big-endian』. 仲可記錄其它格式圖像.
| Image File Header(IFH) | 圖檔頭結构體 |
| WORD ByteOrder; | 字節順序 ‘II’ / ‘MM’ |
| WORD version; | TIFF版本0x002A號, BIGTIFF版本0x002B號 |
| DWORD offset; | 首個IFD偏移量 |
頭兩字節『ByteOrder』字節順序,
| ByteOrder; | 字節順序 |
| ‘II’ | 0x4949 little-endian 細端順序 主機字節 |
| ‘MM’ | 0x4D4D big-endian 大端順序 網路字節 |
『type』圖檔版本0x002A號,
『offset』 首個IFD偏移量,邊界對齊2, 即係2倍數.
壹個TIFF圖檔可能含有多個IFD, 每個IFD都是一個子圖檔.
| Image File Directory(IFD) | 目錄, 保存Directory Entry |
| WORD count; | 數據量 |
| Directory Entry [0]; | 數據0 |
| Directory Entry [1]; | 數據1 |
| Directory Entry [2]; | 數據2 |
| … | |
| DWORD offset; | 下壹IFD偏移, 冇為0. |
| Directory Entry(DE) | 目錄項, 即係數據 |
| WORD tag; | 標簽, 即係name, 下面詳解. |
| WORD type; | 數據類型1~12, 下面詳解. |
| DWORD count; | 數據量 |
| DWORD Value or Offset; | 數據或偏移 |
頭兩字節『tag』標簽.
『type』數據類型, 有12種數據類型,下面介紹.
『count』數據量.
『Value or Offset』數據小於等於4BYTE, 直接擺放數據. 超過4BYTE係偏移
TIFF有12種數據類型.
| 數據類型 | 簡述 |
| 1 | BYTE 8bit冇符號整數 |
| 2 | ASCII字符串, 以NULL結尾 |
| 3 | SHORT-16bit 冇符號短整型 |
| 4 | LONG-32bit 冇符號長整型 |
| 5 | RATIONAL-64bit冇符號分数型,兩個LONG,首LONG係分子,次LONG係分母. |
| 6 | SBYTE-8BIT 有符號整數 |
| 7 | UNDEFINED-8BIT未定義數據 |
| 8 | SSHORT-16BIT 有符號整數 |
| 9 | SLONG-32BIT 有符號整數 |
| 10 | SRATIONAL-64BIT有符號分数型,兩個SLONG,首LONG係分子,次LONG係分母. |
| 11 | FLOAT-4BIT 單精度IEEE格式 |
| 12 | DOUBLE-8BIT 雙精度IEEE格式 |
唯一要講『RATIONAL』64bit冇符號分数型,兩個LONG,首LONG係分子,次LONG係分母.
| typedef struct TIFF_SRATIONAL_TYP { | |
| DWORD molecule; | 首LONG係分子 |
| DWORD denominator; | 次LONG係分母. |
| }TIFF_SRATIONAL, * TIFF_SRATIONAL_PTR; |
『SRATIONAL』64BIT有符號分数型,兩個SLONG,首LONG係分子,次LONG係分母.
| typedef struct TIFF_SRATIONAL_TYP { | |
| int molecule; | 首LONG係分子 |
| int denominator; | 次LONG係分母. |
| }TIFF_SRATIONAL, * TIFF_SRATIONAL_PTR; |
『tag』標簽, 即係數據名.
| tag | type | 簡述 |
| PhotometricInterpretation:
262(0x0106) |
SHORT | 反色顯示.
1=WhiteIsZero白色RGB(0,0,0),黑色RGB(255,255,255). 2=BlackIsZero黑色RGB(0,0,0),白色RGB(255,255,255). 3=RGB 4=RGBPalette 5=TransparencyMask 6=CMYK 7=YCbCr 8=CIELab |
| Compression: 259(0x0103) | SHORT | 1=吾壓縮.
2=霍夫曼壓縮 3=Group 3 Fax 4=Group 4 Fax 5=LZW 6=JPEG 32773=PackBits壓縮 |
| ImageHeight: 257(0x0101) | SHORT or LONG | 圖像高 |
| ImageWidth:256(0x0100) | SHORT or LONG | 圖像寬 |
| ResolutionUnit:296 (0x0128) | SHORT | 解析度單位,計算圖像物理尺碼
1: ratio縱橫比 2: Inch.英寸(默認) 3: Centimeter.釐米 |
| XResolution: 282 (0x011A) | RATIONAL | ImageWidth解析度,X像素解析度,例航拍300m/1000m |
| YResolution:283 (0x011B) | RATIONAL | ImageHeight解析度,Y像素解析度,例航拍300m/1000m |
| RowsPerStrip: 278 (0x0116) | SHORT or LONG | 圖像掃描線長度,等於圖像高度. |
| StripOffsets: 273 (0x0111) | SHORT or LONG | 圖像掃描線(數據)偏移. |
| StripByteCounts: 279 (0x0117) | SHORT or LONG | 圖像數據字節總量 |
| BitsPerSample: 258 (0x0102) | SHORT | 每粒像素位Bit
1=1bit(單色); 4=4bit(16色); 8=8bit(256色) |
| ColorMap: 320 (0x0140) | SHORT | 調色板偏移, 256色和16色圖像先有調色板
3 * (2**BitsPerSample) |
| SamplesPerPixel: 277 (0x0115) | SHORT | 每粒像素字節BYTE
3=(24bit)RGB色 |
| Artist: 315 (0x013B) | ASCII | 創建圖像軟體 |
| CellLength: 265 (0x0109) | SHORT | Threshholding=2 |
| CellWidth: 264 (0x0108) | SHORT | Threshholding=2 |
| Copyright: 33432 (0x8298) | ASCII | 版權聲明: |
| DateTime: 306 (0x0132) | ASCII | 創建日期:
YYYY:MM:DD HH:MM:SS |
| ExtraSamplesa: 338 (0x0152) | SHORT | 說明:
0=未指定數據 1= alpha值(帶預乘顏色) 2=未關聯alpha值 |
| FillOrder: 266 (0x010A) | SHORT |
1= 2= |
| FreeByteCounts: 289 (0x0121) | LONG | free字節量 |
| FreeOffsets: 288 (0x0120) | LONG | free偏移 |
| GrayResponseCurve: 291 (0x0123) | SHORT | 灰度數據-光密度 |
| GrayResponseUnit: 290 (0x0122) | SHORT | 灰度數據-單元
1 |
| HostComputer: 316 (0x013C) | ASCII | 創建圖像操作系統 |
| ImageDescription: 270 (0x010E) | ASCII | 影像描述 |
| Make:271 (0x010F) | ASCII | 掃描儀厰商 |
| MaxSampleValue: 281 (0x0119) | SHORT | |
| MinSampleValue: 280 (0x0118) | SHORT | |
| Model: 272 (0x0110) | ASCII | 掃描儀型號 |
| NewSubfileType: 254 (0x00FE) | LONG | 子檔案中資料類型
ReducedResolution 0x00000001低分辯率; MultiPageImage 0x00000002 多頁影像; TransparencyMask 0x00000004 透明遮罩; |
| Orientation: 274 (0x0112) | SHORT | 影像相對於行和列方向
1:TopLeft 2:TopRight 3:BottomRight 4:BottomLeft 5:LeftTop 6:RightTop 7:RightBottom 8:LeftBottom |
| PhotometricInterpretation: 262 (0x0106) | SHORT | 光度解釋 |
| PlanarConfiguration: 284 (0x011C) | SHORT | 平面配置,祗适用於RGB圖像
1:Chunky塊狀-順序連續存儲RGBRGBRGB(默認) 2: Planar平面-色域獨立存儲RRR..GGG..BBB |
| Software: 305 (0x0131) | ASCII | 創建圖像軟體名稱仝版本 |
| SubfileType:255 (0x00FF) | SHORT | 子檔案中資料類型 |
| Threshholding: 263 (0x0107) | SHORT | 灰色轉黑白 |
| T4Options: 292 (0x0124) | LONG | |
| T6Options: 293 (0x0125) | LONG | |
| DocumentName: 269 (0x0010) | ASCII | 檔案名 |
| PageName:285 (0x011D) | ASCII | 掃描圖頁面名 |
| PageNumber: 297 (0x0129) | SHORT | 掃描圖頁面碼 |
| XPosition: 286 (0x011E) | RATIONAL | 影像X位置 |
| YPosition: 287 (0x011F) | RATIONAL | 影像Y位置 |
| Predictor: 317 (0x013D) | SHORT | 預測器一種數學運算-僅用於LZW壓縮
1:編碼前未使用預測方案(默認) 2:水平差分 |
| TileWidth: 322 (0x0142) | SHORT or LONG | 平鋪寬度 |
| TileLength: 323 (0x0143) | SHORT or LONG | 平鋪高度 |
| TileOffsets: 324 (0x0144) | LONG | 平鋪偏移 |
| TileByteCounts: 325 (0x0145) | SHORT or LONG |
| Compression | #259(0x0103) SHORT 壓縮類型 |
| Uncompressed | 1:未壓縮 |
| CCITT1D | 2 |
| Group3Fax | 3 |
| Group4Fax | 4 |
| LZW | 5: LZW冇損壓縮, 默認 |
| JPEG | 6: JPEG有損壓縮, |
| PackBits | 32773: |
| PhotometricInterpretation | 反色顯示 |
| WhiteIsZero | 1 |
| BlackIsZero | 2 |
| RGB | 3 |
| RGBPalette | 4 |
| TransparencyMask | 5 |
| CMYK | 6 |
| YCbCr | 7 |
| CIELab | 8 |
| ResolutionUnit | 解析度單位,計算圖像物理尺碼 |
| Ratio | 1 :縱橫比 |
| Inch | 2:英寸(默認) |
| Centimeter | 3:釐米 |
| NewSubfileType | 子檔案資料類型 |
| ReducedResolution | 0x00000001低解像 |
| MultiPageImage | 0x00000002:多頁影像 |
| TransparencyMask | 0x00000004:透明遮罩 |
| Orientation | 影像相對於行列方向 |
| TopLeft | 1 |
| TopRight | 2 |
| BottomRight | 3 |
| BottomLeft | 4 |
| LeftTop | 5 |
| RightTop | 6 |
| RightBottom | 7 |
| LeftBottom | 8 |
| BitsPerSample | 每粒像素位Bit |
| 4 | 灰階圖像4bit(16色)/調色板圖像4bit(16色) |
| 8 | 灰階圖像8bit(256色)彩色./調色板圖像8bit(256色)彩色. |
| R=8,G=8,B=8 | TIFF-(RGB Images)RGB影像 |
| R=8,G=8,B=8,A=8 | TIFF-(RGBA Images)RGBA影像 |
| PlanarConfiguration | 平面配置,祗适用於RGB圖像 |
| Chunky | 1:塊狀-順序連續存儲RGBRGBRGB(默認) |
| Planar | 2:平面-色域獨立存儲RRR..GGG..BBB |
| Predictor | 預測器一種數學運算-僅用於LZW壓縮 |
| NO | 1:壓縮前未使用預測方案(默認) |
| Horizontaldifferencing | 2:水平差分 |
如果『ByteOrder』係 ‘MM’-0x4D4D『網路字節』, 要轉為『主機字節』. 定義宏指令.
| #define TIFF_NET2HOST_WORD(_VALUE) ( ((_VALUE & 0x00FF) << 8) | ((_VALUE & 0xFF00) >> 8) ) |
| #define TIFF_NET2HOST_DWORD(_VALUE) ( ((_VALUE & 0x000000FF) << 24) | ((_VALUE & 0x0000FF00) << 8) | ((_VALUE & 0x00FF0000) >> 8) | ((_VALUE & 0xFF000000) >> 24) ) |
| #define TIFF_NET2HOST_DWORD64(_VALUE) ( ((_VALUE & 0x00000000000000FF) << 56) | ((_VALUE & 0x000000000000FF00) << 48) | ((_VALUE & 0x0000000000FF0000) << 40) | ((_VALUE & 0x0000000000FF0000) << 32) | ((_VALUE & 0x00000000FF000000) >> 8) | ((_VALUE & 0x000000FF00000000) >> 16) | ((_VALUE & 0x0000FF0000000000) >> 24) | ((_VALUE & 0x00FF000000000000) >> 32) | ((_VALUE & 0xFF00000000000000) >> 40) ) |
定義TIFF結构, 愛蒞保存分析數據.
| typedef struct TIFF_TYP { | |
| WORD ByteOrder; | 字節順序 ‘II’ / ‘MM’ |
| WORD version; | TIFF圖檔版本 |
| DWORD NewSubfileType; | 子檔案中資料類型 |
| DWORD PhotometricInterpretation; | 反色顯示. |
| DWORD Compression; | 1=吾壓縮. |
| DWORD bitCount; | 像素bits:8位,16位,24位,32位 |
| WORD BitsPerSample[4]; | 每粒像素位BitCount,1=1bit(單色);4=4bit(16色);8=8bit(256色); |
| DWORD SamplesPerPixel; | 位圖像素Bytes:2byte,3byte,4byte; |
| DWORD ImageHeight; | 圖像高 |
| DWORD ImageWidth; | 圖像寬 |
| DWORD Orientation; | 影像方向 |
| DWORD ResolutionUnit; | 解析度單位,計算圖像物理尺碼. 1:縱橫比,2英寸(默認),3釐米 |
| TIFF_RATIONAL XResolution; | ImageWidth解析度,X像素解析度,例航拍300m/1000m = molecule/denominator; |
| TIFF_RATIONAL YResolution; | ImageHeight解析度,Y像素解析度,例航拍300m/1000m = molecule/denominator;
|
| DWORD RowsPerStrip; | 圖像條帶(數據)行數(高度),可能最後一條帶除外. |
| PDWORD64 StripOffsets; | 圖像條帶(數據)偏移. |
| PDWORD64 StripByteCounts; | 圖像數據字節量 |
| DWORD64 StripCount; | 條帶數量 |
| DWORD PlanarConfiguration; | 平面配置 |
| char * ExtraSamplesa; | 說明: |
| char * Software; | 創建圖像軟體名稱仝版本 |
| char * DateTime; | 創建日期: |
| DWORD Predictor; | 預測器一種數學運算-僅用於LZW壓縮 |
| TIFF_PALETTEENTRY palette[256]; | 調色板,用於4bit/8bit模式. |
| PBYTE data; | 原始數據 |
| PBYTE buffer; | 圖像 |
| }TIFF, * TIFF_PTR; |
载入TIFF分析標簽
| bool Load_TIFF(TIFF_PTR tiff, PBYTE data, int size){ |
| TIFF_HEAD_PTR head;// 圖檔頭Image File Header(IFH) |
| tiff->data = data;// 原始數據 |
| head = (TIFF_HEAD_PTR)data;// TIFF圖檔頭 |
| if (tiff->ByteOrder != TIFF_LITTLE_ENDIAN && tiff->ByteOrder != TIFF_BIG_ENDIAN)
return false; |
| if (tiff->ByteOrder == TIFF_BIG_ENDIAN)// ‘MM’ 大端字節 網路字節 net
{ // 網路字節 轉 主機字節 head->version = TIFF_NET2HOST_WORD(head->version); head->offset = TIFF_NET2HOST_DWORD(head->offset); } |
| tiff->version = head->version;// TIFF圖檔版本
if (tiff->version == TIFF_VERSION)// TIFF圖檔版本 { TIFF_DIRECTORY_PTR directory; // 目錄 directory = (TIFF_DIRECTORY_PTR)((PBYTE)data + head->offset); Parse_Directory_TIFF(tiff, directory);// 分析數據 } |
|
// 載入8或16,32Bit圖像 if (tiff->bitCount == 16 || tiff->SamplesPerPixel == 2) Load_Grayscale_TIFF(tiff);// 載入數據 else if (tiff->bitCount == 8 || tiff->SamplesPerPixel == 1) Load_Palette_TIFF(tiff);// 載入數據 else if (tiff->bitCount == 24 || tiff->SamplesPerPixel == 3) Load_RGB_TIFF(tiff);// 載入數據 else if (tiff->bitCount == 32 || tiff->SamplesPerPixel == 4) Load_RGBA_TIFF(tiff);// 載入數據 |
| return true;
} |
分析數據
| bool Parse_Directory_TIFF(TIFF_PTR tiff, TIFF_DIRECTORY_PTR directory) { |
| if (tiff->ByteOrder == TIFF_ENDIAN_BIG)// ‘MM’ 大端字節 網路字節 net
directory->count = TIFF_NET2HOST_WORD(directory->count);// 網路字節 轉 主機字節 |
| for (int index = 0; index < directory->count; ++index)
Parse_Enter_TIFF(tiff, &directory->enter_array[index]);// 分析數據 |
| return true;
} |
分析數據
| bool Parse_Enter_TIFF(TIFF_PTR tiff, TIFF_ENTER_PTR enter)
{ |
| if (tiff->ByteOrder == TIFF_ENDIAN_BIG)// ‘MM’ 大端字節 網路字節 net
{// 網路字節 轉 主機字節 enter->tag = TIFF_NET2HOST_WORD(enter->tag);// 標識 enter->type = TIFF_NET2HOST_WORD(enter->type);// 數據類型 1~12 enter->count = TIFF_NET2HOST_DWORD(enter->count);// 數量 enter->data = TIFF_NET2HOST_DWORD(enter->data);// 數據 } |
| if (enter->tag == TIFF_TAG_NewSubfileType)//子檔案中資料類型
tiff->NewSubfileType = enter->data; else |
| if (enter->tag == TIFF_TAG_PhotometricInterpretation)// 反色顯示.
tiff->PhotometricInterpretation = enter->data; else |
| if (enter->tag == TIFF_TAG_Compression)// 壓縮.
tiff->Compression = enter->data; else |
| if (enter->tag == TIFF_TAG_ImageHeight)// 圖像高
tiff->ImageHeight = enter->data; else |
| if (enter->tag == TIFF_TAG_ImageWidth)// 圖像寬
tiff->ImageWidth = enter->data; else |
| if (enter->tag == TIFF_TAG_ResolutionUnit) // 解析度單位,計算圖像物理尺碼 . 1:縱橫比,2英寸(默認),3釐米
tiff->ResolutionUnit = enter->data; else |
| if (enter->tag == TIFF_TAG_XResolution)// ImageWidth解析度,X像素解析度,例航拍300m/1000m
Parse_XResolution_TIFF(tiff, enter); else |
| if (enter->tag == TIFF_TAG_YResolution) // ImageHeight解析度,Y像素解析度,例航拍300m/1000m
Parse_YResolution_TIFF(tiff, enter); else |
| if (enter->tag == TIFF_TAG_Orientation)// 影像相對於行和列方向
tiff->Orientation = enter->data; else |
| if (enter->tag == TIFF_TAG_ColorMap)//調色板偏移, 256色和16色圖像先有調色板
Parse_ColorMap_TIFF(tiff, enter); else |
| if (enter->tag == TIFF_TAG_BitsPerSample)// 每粒像素位BitCount,1=1bit(單色);4=4bit(16色);8=8bit(256色);
Parse_BitsPerSample_TIFF(tiff, enter); else |
| if (enter->tag == TIFF_TAG_SamplesPerPixel)// RGB圖像,每粒像素字節BYTE
tiff->SamplesPerPixel = enter->data; else |
| if (enter->tag == TIFF_TAG_StripOffsets)// 圖像掃描線(數據)偏移.
Parse_StripOffsets_TIFF(tiff, enter); else |
| if (enter->tag == TIFF_TAG_StripByteCounts) //圖像數據字節總量
Parse_StripByteCounts_TIFF(tiff, enter); else |
| if (enter->tag == TIFF_TAG_RowsPerStrip)// 圖像條帶(數據)行數(高度),可能最後一條帶除外.
tiff->RowsPerStrip = enter->data; else |
| if(enter->tag == TIFF_TAG_PlanarConfiguration)// 平面配置,祗适用於RGB圖像
tiff->PlanarConfiguration = enter->data; else |
| if(enter->tag == TIFF_TAG_ExtraSamplesa)// 說明
tiff->ExtraSamplesa = Malloc_ASCII_TIFF((const char*)(tiff->data + enter->offset)); else |
| if (enter->tag == TIFF_TAG_Software) // 創建圖像軟體名稱仝版本
tiff->Software = Malloc_ASCII_TIFF((const char*)(tiff->data + enter->offset)); else |
| if (enter->tag == TIFF_TAG_DateTime)// 創建日期:
tiff->DateTime = Malloc_ASCII_TIFF((const char*)(tiff->data + enter->offset)); else |
| if(enter->tag == TIFF_TAG_Predictor)// 僅用於LZW編碼
tiff->Predictor = enter->data; |
| return true;
} |
