出處:http://hi.baidu.com/kuku_liu/blo ... 57a613b31bbae8.html
1 GeoTiff利用Tiff表達Geo(地理)信息的思想
Tiff對GeoTiff的支持已寫進Tiff6.0,也就是說,GeoTiff是一種Tiff6.0文件,它繼承了在Tiff6.0規範中的相應部分,所有的GeoTiff特有的信息都編碼在Tiff的一些預留Tag(標籤)中,它沒有自己的IFD(圖像文件目錄)、二進制結構以及其它一些對Tiff來說不可見的信息。
用來描述GeoTiff流行的衆多影射參數及類型信息,如果每一個信息都採用一個標籤那將至少需要幾十甚至幾百個標籤,這會耗盡Tiff定義的有限的標籤資源,另一方面,雖然私有的IFD提供了數千個自由的標籤,但也是有限的,因爲標籤值對不理解的讀者來說是不可見的(因爲他們不知道IFD_OFFSET標籤值指向一個私有的IFD)。
爲了避免這些問題,GeoTiff採用一系列的Keys(鍵)來存取這些信息,這些鍵在功能上相當於標籤,但它處在TIFF上抽象更上一層。準確的說它是一種媒介標籤(Meta-Tag)。鍵與格式化的標籤值一起共存,TIFF文件處理其它圖像數據。和標籤一樣,鍵也有的ID號,範圍從0到65535,但不像標籤那樣,所有鍵的ID號都可以用於GeoTiff的參數定義上。
2 結構與定義
這些鍵也稱爲GeoKeys,所有鍵都由GeoKeyDirectoryTag標籤來索引,該標籤就相當於表示Geo信息的鍵的一個目錄。它的結構如下:
GeoKeyDirectoryTag:
Tag = 34735 (87AF.H)
Type = SHORT (2-byte unsigned short)
N = variable, >= 4
Alias: ProjectionInfoTag, CoordSystemInfoTag
Owner: SPOT Image, Inc.
它由頭和鍵實體構成,如下:
Header={KeyDirectoryVersion, KeyRevision, MinorRevision, NumberOfKeys}
KeyEntry = { KeyID, TIFFTagLocation, Count, Value_Offset }
其中,TIFFTagLocation表示哪個tag存放值,如果值爲0則表示值爲SHORT類型且包含在Value_Offset元素中;否則,其值類型由tag含有值的TIFF-Type暗指。
所有Key值不是short類型的都存放在下面兩種Tag下,基於下面的結構:
GeoDoubleParamsTag:
Tag = 34736 (87BO.H)
Type = DOUBLE (IEEE Double precision)
N = variable
Owner: SPOT Image, Inc.
注:該tag用來存放DOUBLE型的GeoKeys,被GeoKeyDirectoryTag引用,這個double數組中任何值的意義由指向它的GeoKeyDirectoryTag引用決定。FLOAT值必須先轉換爲DOUBLE才能存儲。
GeoAsciiParamsTag:
Tag = 34737 (87B1.H)
Type = ASCII
Owner: SPOT Image, Inc.
N = variable
GeoKeyDirectoryTag=( 1, 1, 2, 6,
1024, 0, 1, 2,
1026, 34737,12, 0,
2048, 0, 1, 32767,
2049, 34737,14, 12,
2050, 0, 1, 6,
2051, 34736, 1, 0 )
GeoDoubleParamsTag(34736)=(1.5)
GeoAsciiParamsTag(34737)=("Custom File|My Geographic|")
第一行表明這是一個版本號爲1的GeoTIFF GeoKey目錄,鍵的版本爲Rev. 1.2,在這個標籤中定義了6個鍵。
下一行定義第一個鍵(ID=1024 = GTModelTypeGeoKey),值爲2(Geographic),直接放在元素列表中(因爲TIFFTagLocation=0);
下一行鍵1026(the GTCitationGeoKey),列在GeoAsciiParamsTag(34737)數組中開始於偏移0,數到第12個字節,所以其值爲"Custom File"(”|”被轉換爲結束符了)
再下面一行,鍵2051(GeogLinearUnitSizeGeoKey) 位於GeoDoubleParamsTag
(34736), 偏移爲0所以值爲1.5
key2049的值爲(GeogCitationGeoKey) is "My Geographic"。
3 GeoTIFF中座標系
Geotiff設計使得標準的地圖座標系定義可以以一個單一的註冊的標籤的形式隨意存儲。也支持非標準座標系的描述,爲了在不同的座標系間轉換,可以通過使用三四個另設的TIFF標籤來實現。
然而,爲了在各種不同的客戶端和GeoTIFF提供者間正確交換,最好要建立一個通能的系統來描述地圖投影。
在TIFF/GeoTIFF框架下,主要有3種不同的空間可供座標系定義,這3種空間是:
1. 光柵空間(圖像空間)R,用於在一幅圖像中表示象素值;
a) 在標準TIFF6.0中定義了與光柵空間R與設備空間相關的標籤:如顯示器、掃描儀、或打印機
2. 設備空間D;
3. 模型空間M,用於表示地球上的點。
a) 地理座標系
b) 地心座標系
c) 投影座標系
d) 垂直座標系
下面是從GeoTIFF的觀點上來看,這3種空間的使用以及它們相應的座標系。
4 讀寫程序
講到這兒,我們得開始玩玩真的了,看我們如何來讀寫這類GeoTiff文件的,我們的目標只有一個,我們將規範中要求的鍵值寫入文件並能讀出,所幸的事,這些工作別人已經做了,這就是著名的LibGeoTiff,它是在LibTiff基礎上實現的。
它的主要讀寫函數原型如下:
The cpp code:
- GTIFFree(): Free GeoTIFF access handle.
- GTIFGetDefn(): Read and Normalize GeoTIFF Definition.
- GTIFKeyGet(): Read GeoTIFF GeoKey.
- GTIFKeySet(): Write GeoTIFF GeoKey.
- GTIFNew(): Create GeoTIFF access handle.
- GTIFWriteKeys(): Flush GeoTIFF Keys.
- SetCSVFilenameHook(): Override CSV File Searching.
- XTIFFClose(): Close GeoTIFF file.
- XTIFFOpen(): Open GeoTIFF file.
- 下面是一個例程makegeo.c:
- #include "geotiffio.h"
- #include "xtiffio.h"
- #include <stdlib.h>
- void SetUpTIFFDirectory(TIFF *tif);
- void SetUpGeoKeys(GTIF *gtif);
- void WriteImage(TIFF *tif);
- #define WIDTH 20L
- #define HEIGHT 20L
- void main()
- {
- char *fname = "newgeo.tif";
- TIFF *tif=(TIFF*)0;
- GTIF *gtif=(GTIF*)0;
- tif=XTIFFOpen(fname,"w");
- if (!tif) goto failure;
- gtif = GTIFNew(tif);
- if (!gtif)
- {
- printf("failed in GTIFNew\n");
- goto failure;
- }
- SetUpTIFFDirectory(tif);
- SetUpGeoKeys(gtif);
- WriteImage(tif);
- GTIFWriteKeys(gtif);
- GTIFFree(gtif);
- XTIFFClose(tif);
- exit (0);
- failure:
- printf("failure in makegeo\n");
- if (tif) TIFFClose(tif);
- if (gtif) GTIFFree(gtif);
- exit (-1);
- }
- void SetUpTIFFDirectory(TIFF *tif)
- {
- double tiepoints[6]={0,0,0,130.0,32.0,0.0};
- double pixscale[3]={1,1,0};
- TIFFSetField(tif,TIFFTAG_IMAGEWIDTH, WIDTH);
- TIFFSetField(tif,TIFFTAG_IMAGELENGTH, HEIGHT);
- TIFFSetField(tif,TIFFTAG_COMPRESSION, COMPRESSION_NONE);
- TIFFSetField(tif,TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_MINISBLACK);
- TIFFSetField(tif,TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
- TIFFSetField(tif,TIFFTAG_BITSPERSAMPLE, 8);
- TIFFSetField(tif,TIFFTAG_ROWSPERSTRIP, 20L);
- TIFFSetField(tif,TIFFTAG_GEOTIEPOINTS, 6,tiepoints);
- TIFFSetField(tif,TIFFTAG_GEOPIXELSCALE, 3,pixscale);
- }
- void SetUpGeoKeys(GTIF *gtif)
- {
- GTIFKeySet(gtif, GTModelTypeGeoKey, TYPE_SHORT, 1, ModelGeographic);
- GTIFKeySet(gtif, GTRasterTypeGeoKey, TYPE_SHORT, 1, RasterPixelIsArea);
- GTIFKeySet(gtif, GTCitationGeoKey, TYPE_ASCII, 0, "Just An Example");
- GTIFKeySet(gtif, GeographicTypeGeoKey, TYPE_SHORT, 1, KvUserDefined);
- GTIFKeySet(gtif, GeogCitationGeoKey, TYPE_ASCII, 0, "Everest Ellipsoid Used.");
- GTIFKeySet(gtif, GeogAngularUnitsGeoKey, TYPE_SHORT, 1, Angular_Degree);
- GTIFKeySet(gtif, GeogLinearUnitsGeoKey, TYPE_SHORT, 1, Linear_Meter);
- GTIFKeySet(gtif, GeogGeodeticDatumGeoKey, TYPE_SHORT, 1, KvUserDefined);
- GTIFKeySet(gtif, GeogEllipsoidGeoKey, TYPE_SHORT, 1, Ellipse_Everest_1830_1967_Definition);
- GTIFKeySet(gtif, GeogSemiMajorAxisGeoKey, TYPE_DOUBLE, 1, (double)6377298.556);
- GTIFKeySet(gtif, GeogInvFlatteningGeoKey, TYPE_DOUBLE, 1, (double)300.8017);
- }
- void WriteImage(TIFF *tif)
- {
- int i;
- char buffer[WIDTH];
- memset(buffer,0,(size_t)WIDTH);
- for (i=0;i<HEIGHT;i++)
- if (!TIFFWriteScanline(tif, buffer, i, 0))
- TIFFError("WriteImage","failure in WriteScanline\n");
- }