出处:http://hi.baidu.com/kuku_liu/blo ... 57a613b31bbae8.html
1
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
(34736), 偏移为0所以值为1.5
key2049的值为(GeogCitationGeoKey) is "My Geographic"。
3 GeoTIFF中坐标系
Geotiff设计使得标准的地图坐标系定义可以以一个单一的注册的标签的形式随意存储。也支持非标准坐标系的描述,为了在不同的坐标系间转换,可以通过使用三四个另设的TIFF标签来实现。
然而,为了在各种不同的客户端和GeoTIFF提供者间正确交换,最好要建立一个通能的系统来描述地图投影。
在TIFF/GeoTIFF框架下,主要有3种不同的空间可供坐标系定义,这3种空间是:
1.
a)
2.
3.
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"); -
- }