使用十六进制编辑器学习地理域文件格式(2018)

2021-05-06 01:12:41

自从我开始在行星工作以来,我一直听到云优化的地理灯(COG)。我的同事克里斯福尔摩斯甚至写了一篇文章,解释了他们是什么以及它们是有用的。我决定实施一个去图书馆,能够与COG一起使用。星球的卫星图像大部分都是在地理灯的格式,包括来自2018年2月全球底图的洛杉矶的这个很好的形象:

作为编写图书馆的第一步,我需要学习大约1)云优化的地理灯,2)一般的地球仪,以及3)甚至比:TIFF。我始终发现恐吓的二进制文件格式 - 当您将它们转储到控制台时,它们只需看起来像gibberish!但那里有逻辑。这就是我探索这30岁的文件格式的探索。

我与TIFF的第一个经历来自我作为一个孩子的扫描仪。我扫描了我的漫画风格的图纸,它产生了TIFFS,Windows'95中的扫描仪软件告诉我表示“标记的图像文件格式”。这到底是什么意思呢?让我们来看看标签图像文件格式常见问题解答。

tiff header - 文件的前几个字节 - 给我们很多有用的信息:

+ ------- + ------------- + ----------------- +字节偏移:| 0 | 2 | 4 | + ---------------------------------- +尺寸:|字|字|长| + ---------------------------------- +内容:|字节|版本(42)|偏移到第一个| |订购| | IFD | + ------- + ----------------------------- +

让我们忽略IFD,现在开始一些更容易理解的东西。我们可以看到这个词是两个字节,长是四个字节。字节订单告诉我们文件是否是大端(mm)或小endian(ii)。 TIFF版本是42,TIFF规范是“任意但精心挑选的数字”。

我们如何查看一个TIFF,以确认到目前为止对文件标题的理解?我推荐非常好的XXD工具,以可读方式打印出二进制文件。我喜欢xxd,因为简洁的名字让我感觉像黑客。让我们下载我上面展示的洛杉矶的TIFF,并转储TIFF的前几个字节:

$ curl -o https://oldpatricka.com/planet/la.tif $ xxd la.tif | HEAD-N 1 00000000:4949 2A00 0800 0000 1200 0001 0300 0100 II * .............

此文件的前两个字节为4949,XXD有助于告诉我们这是ASCII的II。请记住,II是小endian,这意味着字节以最重要的顺序存储。 (这也是我喜欢我喜欢写日期的明年加拿大人的方式。)接下来,我们可以确认它实际上是一个tiff。接下来的两个字节是2a00。我们可以将其视为十六进制数字0x002a,这是基数十的42次!欢呼 - 我们只读一个没有任何特殊工具的TIFF的文件类型和字节顺序!

TIFFS分为“页面”,是TIFF中的单个图像。 TIFF实际上并不是一个图像,而是一个图像的容器!图像文件目录(IFD)描述了其中一个页面,并包括一组来实现此目的。标签包括关于文件的元数据以及在文件中找到图像位的位置。在感知系统网站上标签有很好的参考,而TIFF规范是一个非常好的参考资料和易于阅读!

+ --------- + ----------------- + ----------------- + byte偏移:| 0 | 2 | 2 + n标签* 12 | + ---------------------------------------- +大小:|字| 12字节* n标签|无符号长| + --------------------------------------- +内容:|号码|标签数据|偏移到下一个| |标签| | IFD(或0)| + --------- + -------------------------------- +

整体结构包括标签的数量,标签数据本身,然后指向下一个IFD或0的指针(字节偏移),如果没有更多的IFD。

+ -------- + ------------- + ----------------------- --------- + byte | 0 | 2 | 4 | 8 |偏移:| | | | | + ------------------------------------------ --------- +尺寸:|字|字|无符号长|变量| + ------------------------------------------ --------- +内容:|标签ID | tag datatype |数量标签数据或| | | |价值|指向数据| + -------- + ------------- + ----------------------- --------- +

所以我们可以看到一个单独的标签具有标签的ID,标签数据的数据类型,值数和标签数据本身。现在让我们试着读一个标签。

$ xxd la.tif | HEAD-N1 00000000:4949 2A00 0800 0000 1200 0001 0300 0100 II * .............

我们有字节顺序,tiff版本和字节偏移到IFD。让我们直接向TIFF标题中的IFD偏移线,只显示偏移,所以它不是压倒性的:

这些字节(0800 0000)在十六进制中为0x8,这也是十进制的8个。这意味着第一个IFD在偏移8处,其在标题之后。因此,让我们寻求偏移并通过显示前两个字节来读取IFD中的标签数:

这些字节(1200)在十六进制中平均0x12或IFD中的16个标签。很棒,现在让我们阅读其中一个标签!为此,我们可以将2添加到偏移量并尝试读取第一个标记。请记住,标签是12个字节,因此让我们读取12个字节:

所以标签ID是十六进制中的前两个字节(0001)或0x100,这是十进制的256。标签参考说,ID 256是ImageWidth。现在我们需要知道数据类型能够读取该值。这存储在十六进制中的接下来的两个字节(0300)或0x0003中,这是小数中的3个。 TIFF规范说3是短的,这是一个两个字节的整数。现在我们可以检查其中有多少有接下来的4个字节(0100 0000)的这些值(0100 0000),其在十六进制中为0x1或十进制。所以,一个图像宽度值。那讲得通。现在,让我们读取该价值本身。这是一个简短的,所以我们读取了下一个两个字节(0010),在十进制的十六进制中为0x1000或4096。现在我们了解到,我们的TIFF中的第一张图像的宽度为4096像素。凉爽的!再次,我们甚至不使用关于TIFF的任何软件。

现在,我不想以这种方式或其他IFDS(Ian Hansen和我写了一个转储IFDS的脚本),但现在我们现在对TIFF是如何结构的以及如何阅读它们,只需使用命令行和TIFF引用。

所以所有这个元数据都很有趣,但不是tiffs图像?图像数据本身在哪里?嗯,一些特殊的标签描述了在哪里找到文件中的数据。在齿轮的情况下,您可以使用瓷砖,TileLength,TileOffsets和TileByTecounts来读取图像数据,因为它发生才能铺平。你可能有这样的东西:

瓷砖:256,TileLeght:256,瓷砖:[100,10000,20000,30000],瓷砖纤维(10000,20000,30000],TilebyTecounts:[9900,10000,10000,9000]。这告诉您所有您需要知道读出图像的瓷砖部分的字节。

地理员只是一个有特殊标签的TIFF,让您允许您地造影图像。这告诉您地球上的位置由图像表示。有很多标签,但他们让您了解地球的图像的界限,投影它使用的投影以及许多其他东西。

现在很容易理解,我们对TIFFS有很好的理解。地理码就像我们在上面看的那样,但是使用特定的标签集。

现在我们知道一个TIFF和地理率是什么,齿轮是什么?如果我们查看规范,那么很容易理解,现在我们理解TIFFS。

带有一个或多个IFD的TIFF(描述原始图像和缩小版本)。所描述的图像的数据并不与常规TIFF完全相同?没有实际!我们上面没有覆盖这一点,但除了标题之外,TIFF的不同部分可以是文件中的任何顺序,而TIFF阅读器只需要遵循偏移来读取文件。 TIFF可以像其中任何一个一样结构:

漂亮的齿轮:烦人的tiff:+ ------------- + + ------------- + | TIFF标头| | TIFF标头| + ------------- + + ------------- + | IFD 0 | |图像数据| + ------------- + |对于IFD 1 | | IFD 1 | | | + ------------- + | | | IFD 2 | + ------------- + + ------------- + | IFD 2 | |图像数据| + ------------- + |对于IFD 2 | | IFD 0 | | | + ------------- + | | |图像数据| + ------------- + |对于IFD 0 | |图像数据| | | |对于IFD 1 | | | | | + ------------- + | | | IFD 1 | + ------------- + + ------------- + |图像数据| |图像数据| |对于IFD 0 | |对于IFD 2 | | | | | | | | | + ------------- + + ------------- +

如果它是左边的结构,那么受益于我们可以一次下载较小的块状块,如果我们只想要一点块,我们并不总是需要下载整个文件。我们可以通过使用HTTP范围请求来询问我们对我们感兴趣的TIFF的特定位。例如,我们可以只在带有以下内容的标题和IFDS下载:

我们只是猜测IFDS适合1K,但现在我们已经检索到这一点,我们可以使用IFDS来获取单个瓷砖而不获取整个TIFF。假设我们发现瓷砖OFFSETS是:[2048,52048,102048,152048]和瓷砖地区:[50000,50000,50000,50000],我们可以只获取第一个瓷砖:

那么你为什么要这样做?假设您正在运行一个图形服务器,并希望在运行Tile Server上呈现Tiles在Web上运行,可以跨多个主机拆分工作负载,并仅将TIFF的块拉呈现给渲染。或者说你想对你的图像进行一些分析,可以分成小块,你现在可以抓住小块的文件。

我们现在了解TIFFS,地理癖和齿轮的工作!这里有很多东西,但如果你慢慢地慢慢地建立了你的知识,那就不太难以理解。当然,我没有通过一些细节,就像如何将图像数据存储在条带中或平铺,压缩成不同的格式,或者以不同方式对象本身交错!

如果您想了解更多有关COGS的信息,Cogeo.org有很好的参考文献,您可以使用COG MAP项目查看浏览器中的COG。如果您想要有关Planet API的更多信息以获取像上面的图像,请查看开发人员中心。

更新:我写了一个后续帖子:在没有任何TIFF工具的情况下读取单个TIFF像素,在那里您可以超越元数据,并了解如何阅读像素数据。

要关闭,我要感谢一些我的行星同事:Ian Hansen与我一起工作,了解COGS; Joe Kington填补了很多空白,了解马赛克队如何使用嵌齿轮;克里斯福尔摩斯鼓励我分享这个星球外; Dana Bauer为一大批审查这篇文章;和坦率的暖和人作为资源,专门用于了解地球仪和齿轮。

如果我在这里犯了任何错误,请告诉我在Twitter上或在中等上!我喜欢了解更多关于TIFFS的信息!