GeoTiff格式的基本概念

GeoTiff格式的基本概念


发布日期: 2017-11-17 更新日期: 2017-11-17 编辑:xuzhiping 浏览次数: 21206

标签:

摘要: Tag Image File Format(TIFF)图像文件是图形图像处理中常用的格式之一, 它的图像格式很复杂, 但由于它对图像信息的存放灵活多变,它可以支持很多色彩系统,而且独立于操作系统, 因此TIFF得到了广泛的应用。 在各种地理信息系统、摄影测量与...

Tag Image File Format(TIFF)图像文件是图形图像处理中常用的格式之一, 它的图像格式很复杂, 但由于它对图像信息的存放灵活多变,它可以支持很多色彩系统,而且独立于操作系统, 因此TIFF得到了广泛的应用。

在各种地理信息系统、摄影测量与遥感等应用中, 都要求图像具有地理编码信息, 例如图像所在的坐标系、比例尺、图像上点的坐标、经纬度、长度单位及角度单位等等。对于存储和读取这些信息,纯TIFF 格式的图像文件是很难做到的,而是GeoTIFF 作为TIFF 的一种扩展, 在TIFF 的基础上定义了 一些GeoTag (地理标签),从而对各种坐标系统、椭球基准、投影信息等进行定义和存储,使图像数据和地理数据存储在同一图像文件中, 这样就为广大用户制作和使用带有地理信息的图像提供了方便的途径。

GeoTiff只是Tiff的一种特例,但要遵循规范来用好它却不是那么简单。

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,所有键都是由Geo Key Directory Tag标签来索引,这个标签就相当于表示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 }

其中,TIFF Tag Location表示哪个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基础上实现的。

它的主要读写函数原型如下:

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 



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 GTIFNewn");

               goto failure;

        }



        SetUpTIFFDirectory(tif);

        SetUpGeoKeys(gtif);

        WriteImage(tif);



        GTIFWriteKeys(gtif);

        GTIFFree(gtif);

        XTIFFClose(tif);

        exit (0);



failure:

        printf("failure in makegeon");

        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

关注公众号
获取免费资源

随机推荐


Copyright © Since 2014. 开源地理空间基金会中文分会 吉ICP备05002032号

Powered by TorCMS

OSGeo 中国中心 邮件列表

问题讨论 : 要订阅或者退订列表,请点击 订阅

发言 : 请写信给: osgeo-china@lists.osgeo.org