
高解像度『TIFF』圖片, 加入『BIGTIFF』規范,使用64bit支緩4GB以上圖片. 支緩『ZIP』壓縮.擴展名『.tf8』『.btf』『.tiff』.
『BIGTIFF』圖檔頭Image File Header(IFH)
| typedef struct BIGTIFF_HEAD_TYP { | BIGTIFF圖檔頭 |
| WORD ByteOrder; | 字節順序 ‘II’ / ‘MM’ |
| WORD version; | BIGTIFF圖檔版本 0x002B |
| WORD ReservedOffset; | 保留 |
| WORD Reserved; | 保留 |
| DWORD64 offset; | 首個IFD偏移量64BIT,邊界對齊4 |
| }BIGTIFF_HEAD, * BIGTIFF_HEAD_PTR; |
區分『BIGTIFF』仝『TIFF』
| #define TIFF_VERSION 0x002A | TIFF圖檔版本 |
| #define BIGTIFF_VERSION 0x002B | BIGTIFF圖檔版本 |
『BIGTIFF』新增三個數據類型
| #define BIGTIFF_TYPE_LONG8 16 | 冇符號8字節(64位)整数 |
| #define BIGTIFF_TYPE_SLONG8 17 | 有符號8字節(64 位)整数 |
| #define BIGTIFF_TYPE_IFD8 18 | 无符号8字節(64位)IFD偏移。 |
『BIGTIFF』新增ZIP壓縮類型 8
| #define TIFF_Compression_ZIP 8 | ZIP壓縮, MAX_WBITS帶 zlib 頭和尾 |
『BIGTIFF』目錄入口 Directory Entry(DE)
| typedef struct BIGTIFF_ENTER_TYP { | 即係數值 |
| WORD tag; | 標識 |
| WORD type; | 數據類型 1~12 16~17 |
| DWORD64 count; | 數量64BIT |
| union {
DWORD64 data; |
數值64BIT |
| DWORD64 offset;
}; |
偏移64BIT |
| }BIGTIFF_ENTER, * BIGTIFF_ENTER_PTR; |
『BIGTIFF』目錄 Image File Directory(IFD)
| typedef struct BIGTIFF_DIRECTORY_TYP { | |
| DWORD64 count; | 目錄數量64BIT |
| BIGTIFF_ENTER enter_array[1]; | 目錄,即係數值 |
| // DWORD64 offset; | 64BIT下壹個偏移-BIGIFD |
| }BIGTIFF_DIRECTORY, * BIGTIFF_DIRECTORY_PTR; |
『高解像圖片』組織成『Tiled瓦片』而非『條帶Strip』, 低中解像圖像用標準『TIFF』『條帶Strip』.『高解像圖片』切割成大致方正塊狀,而非長條『條帶Strip』.壓縮效果更佳.
『Tiled瓦片』取代『StripOffsets』、『StripByteCounts』『RowsPerStrip』. 切忽仝時用『Tiled瓦片』仝『條帶Strip』.
『TileWidth』仝『TileLength』『瓦片』定義寬高. 所有『瓦片』『寬高』相同, 『瓦片』邊界填充.
當『ImageWidth』=129, 『TileWidth』= 64.則分割3個『Tiled瓦片』, 最後一個填充63個像素.
平鋪邊界代價需要浪費一定空間,但係壓縮可以將填充區壓縮到接近0.
即使數據冇壓縮,『Tiled瓦片』祗适用於『高解像圖片』. 『高解像圖片』分割大量『Tiled瓦片』, 填充區祈浪費百分之幾空間,
『Tiled瓦片』被單獨壓縮, 仝『條帶Strip』壓縮一樣. 即每個『Tiled瓦片』數據被視為單獨『條帶Strip』.
『Tiled瓦片』欄位:
| 『Tiled瓦片』欄位: | ||
| TileWidth | SHORT or LONG | 瓦片寬度, 必須16倍數 |
| TileHeight | SHORT or LONG | 瓦片高度, 必須16倍數 |
| TileOffsets | LONG or LONG8 | 瓦片(數據)偏移, 從左到右從上到下的順序排列. |
| TileByteCounts | SHORT or LONG or LONG8 | 瓦片數據字節量, 從左到右從上到下的順序排列. |
載入瓦片數據
| bool Load_Tile_TIFF(TIFF_PTR tiff){ |
| PBYTE tile_buffer; // 瓦片圖像
DWORD64 tile_size; // 瓦片數據字節量 DWORD64 tile_offset;// 瓦片数据偏移 DWORD64 tiles_countX;// 瓦片橫跨 DWORD64 tiles_countY; // 瓦片縱跨 DWORD64 line_size; DWORD64 index, i, j; // 索引 DWORD64 offset;// (數據)偏移. DWORD64 count;// 數據字節量 DWORD64 size;// 寫入量 DWORD64 buffer_offset;// 圖像数据偏移 DWORD64 buffer_size;// 圖像数据字節 |
| tiles_countX = (tiff->ImageWidth + tiff->TileWidth – 1) / tiff->TileWidth;// 瓦片橫跨 |
| tiles_countY = (tiff->ImageHeight + tiff->TileHeight – 1) / tiff->TileHeight;// 瓦片縱跨 |
| tile_size = tiff->TileWidth * tiff->TileHeight * tiff->SamplesPerPixel; // 瓦片數據字節量 |
| tile_buffer = (PBYTE)malloc(tile_size);// 分配記憶體 |
| size = 0;// 寫入量 |
| // 計算圖像所占長度
buffer_size = (tiff->ImageWidth * tiff->ImageHeight) * tiff->SamplesPerPixel; |
| // 定位平鋪/瓦片图像数据
for (j = 0; j < tiles_countY; ++j){ |
| for (i = 0; i < tiles_countX; ++i){ |
| index = j * tiles_countX + i; |
| offset = tiff->TileOffsets[index]; // (數據)偏移.
count = tiff->TileByteCounts[index]; // 數據字節量 |
| // 讀瓦片數據
if (tiff->Compression == TIFF_Uncompressed) {// 未壓縮 memcpy(tile_buffer, tiff->data + offset, count);// 复制图像数据 size = size + count;// 累積寫入量 }else |
| if (tiff->Compression == TIFF_Compression_LZW)
{// LZW 解壓縮 tile_size = ((tiff->TileWidth * tiff->TileHeight) * tiff->SamplesPerPixel); UnCompress_Data_LZW(&_lzw, tile_buffer, &tile_size, tiff->data + offset, count); size = size + tile_size;// 累積寫入量 } else |
| if (tiff->Compression == TIFF_Compression_ZIP)
{// ZIP 解壓縮 DWORD _tile_size = ((tiff->TileWidth * tiff->TileHeight) * tiff->SamplesPerPixel); Uncompress_Data_ZIP(tile_buffer, &_tile_size, tiff->data + offset, (DWORD)count, MAX_WBITS); size = size + _tile_size;// 累積寫入量 } |
| // 寫入瓦片數據
for (DWORD tindex = 0; tindex < tiff->TileHeight; ++tindex) { |
| if ( (j * tiff->TileHeight + tindex) >= tiff->ImageHeight )
break;// 超出 |
| buffer_offset = ( ((j * tiff->TileHeight + tindex) * tiff->ImageWidth) + (i * tiff->TileWidth)) * tiff->SamplesPerPixel;// 圖像数据偏移 |
| tile_offset = tindex * tiff->TileWidth * tiff->SamplesPerPixel;// 瓦片数据偏移 |
| if ((tiff->TileWidth * i) > tiff->ImageWidth)
line_size = (tiff->ImageWidth – (tiff->TileWidth * (i – 1))) * tiff->SamplesPerPixel; else line_size = tiff->TileWidth * tiff->SamplesPerPixel; |
| if (buffer_offset >= buffer_size)
break;// 截斷填充區 |
| memcpy(tiff->buffer + buffer_offset, tile_buffer + tile_offset, line_size);
} } } |
| free(tile_buffer);// 释放
return true; } |
