如何将游戏元数据存储在.png文件中?


208

孢子允许通过导出.png文件共享玩家创建的生物。那.png是生物的照片,但是如果将其导入到游戏中,则生物的信息(例如纹理,大小和形状)也会随之出现。

如何实现这种功能?


5
应该有更高的分数,这是一个非常有趣的问题。
皮埃尔·阿洛德

3
Alpha通道可能会因此而被滥用……
Tobias Kienzler 2014年


1
我认为最好将此数据存储在另一个文件中。在此文件中,应该有与要存储数据的实体相关的纹理文件的名称。首先,为了明确起见(png格式用于图形-“便携式网络图形”),其次:考虑一种情况,如果您想使用实体存储更多图像,则可以简单地从该自定义文件中添加对它的引用。您可能会在一个PNG中存储不同的图像(大小不同,深度不同等)时遇到问题。
luke1985

3
Alpha通道已被大量提及,当然PNG仍然支持元数据,但我只是想分享自己使用的一种技术-从左到右,从上到下,以固定顺序遍历通道,然后将值四舍五入为奇数或偶数 -不管是升还是降。任何一个通道的1改变都没有明显的区别,在256x256图像(当然每个像素为4位)中,您可以存储令人印象深刻的32KB数据。如果您需要更多,则可以舍入到%4来代替-太多了,它开始看起来像是旧的GIF思维
。。– Octopoid 2015年

Answers:


56

如果您真正需要的只是PNG文件,那么他们很可能只是将信息添加到文件中。这实际上是隐写术的一种做法。很多时候,这用于隐藏有效载荷或秘密消息,这些东西似乎是面向公众的。但是,在这种情况下,很可能使用了这种方法。典型的文字描写法不会隐藏内容,但是没有理由不能简单地将数据追加到文件末尾的图像中并进行检索。

有几种工具可以为您编码这些数据,谷歌搜索至少会显示thisthis

PNG $89在开始时具有字节签名,因此有可能将信息插入到PNG结构本身之后,并通过SPORE游戏简单地进行了解析。

但是,其他答案和在Google上进行的搜索给出的进一步研究表明,Spore实际上仅使用了一种文字术来将信息隐藏在alpha位中。考虑到这一点,我们可以排除附加数据或元数据的可能性。

应该注意的是,如果要在本地解析元数据,那么元数据仍然是一个非常可行的选择。如果该信息可能在网络上共享或重新编码,则不能保证导出会保留您的所有信息。使用像素数据时,它可以毫无损失地幸免于难。


3
据我所知,孢子将元数据存储在PNG的alpha通道内。
塔拉2014年

28
当PNG支持任意元数据块时,为什么要使用Alpha通道或隐写术?
Russell Borogove 2014年

8
“ PNG开头具有字节签名“ 89”,因此很有可能在PNG结构本身之前或之后插入该信息,并仅通过SPORE游戏对其进行分析。”如果是这种情况,那么就不会”不再是PNG文件。也就是说,普通的图像查看器将无法显示它。
svick

3
@RussellBorogove有一个很好的理由:如果PNG除了通过Spore进行解码/编码,与实际的图像数据相比,任意元数据块更有可能被忽略或丢失。对图像中的数据进行编码可以提高如果可以看到它就可以加载它的可能性。
Tim S.

@svick实际上,我使用的文件既是有效的PNG,又是RAR。RNG标头在PNG之后开始,并且RAR提取程序很好。它也可以以其他方式正常工作。
皮质2014年

153

PNG格式有更多或更少的任意元数据支持。的PNG标准定义了一个PNG文件,本质上是一系列的块,其中的一些是必需的(和包含的图像数据)的。但是,其他是可选的。例如,有一个块用于存储伽马信息或直方图数据。

特别是,有一个tEXt可用于存储任意键/值文本对。只要您可以将数据表示为文本(很有可能),就可以使用它来运送所需的任何种类的任意数据。

您将需要一个PNG库,该库允许您访问和操作这些其他块(例如参考库),或者您需要自己编写一个。然后,只需选择如何将所需数据编码为键/值对即可。我建议以下内容:

  • 选择以项目名称或代码名称为前缀的键名称,以创建粗略的“命名空间”系统,并避免与其他应用程序使用数据的潜在冲突
  • 不要尝试以这种方式存储实际纹理,而是存储指向您游戏自己的资产数据库中的那些纹理的引用
  • 诸如生物或物体的大小,重量等的数据-基本上是简单的标量-可以轻松存储

为了做出更完整的答案,我还将指出,还有另一种方法(以前由@Vaughn和@Alexis的答案记录):直接在图像像素中编码所需的其他数据,然后将数据分布到整个图像像素中。颜色通道的低位。这种方法不需要使用额外的元数据,这意味着您可以完全实现它而无需依赖它,也不必担心外部程序会错误地处理该元数据。它还具有很高的“酷”因数,并且由于仅使用低阶位,因此图像在人眼看来仍将是正确的。但是,这确实意味着图像大小是可存储数据量的主要控制因素。如果需要更多存储空间,则需要为图像分配更多像素。

正如其他人指出的那样,此过程称为隐写术


3
可以简单地通过Base64发送数据并将其存储为单个值
CodesInChaos 2014年

11
@ da4c30ff像元数据一样实用,隐写术具有一定的间谍幻想效果,这是我们的人群难以抗拒的。如果我自己进行此操作,则将使用Josh Petrie提出的可伸缩性方法,但我非常想使用隐写术在图像本身中隐藏校验和,以验证图像和文本是否彼此对应-不是因为这是有用或安全的,但仅仅是因为它很酷。;)
DMGregory

“文本”在这里到底是什么意思?仅ASCII(字符<= 127)?除0以外的任何字节?有没有字节?或者是其他东西?(这将影响您用于写入二进制数据所需的编码。例如是否需要base64。)
svick

1
我用文本块标准的链接更新了答案。但基本上,该文本是按照ISO 8859-1(8位,单字节,拉丁1字符)进行解释的。
乔什

51

摩纳哥的开发人员实际上就他们和Spore如何做到这一点发表了出色的文章

他们所做的工作的基本摘要非常简单:

  • 将您的数据转换成二进制
  • 将目标图像转换为原始位图
  • 以某种可预测的模式沿着图像的像素移动(它们只是从左上角从左到右进行操作)。
  • 向每个像素的每个颜色通道的最低位写入一位
  • 再次将修改后的位图导出为png

只需相反地执行此操作即可检索您的数据。

该过程背后的基本思想是图像中有很多像素,并且每个颜色通道的最低位没有太大区别。另外,您写入的比特中的大约一半将恰好是映像中已经存在的比特。您得到的基本上是正确的图像,但带有怪异的伪影。他花时间注意到,只有在您真正提高对比度/饱和度并放大后,这些伪像才真正引起注意。不过,他的源图像确实带有很多初始噪声。

从文章:

注意在上一张图片中,噪声中几乎没有可分辨的水平线。这是关卡数据的结尾。这意味着我实际上可以仅使用最低有效位将所有级别的数据拟合为265x120像素的图像。

棘手的补遗:

我可以做的事情,我相信孢子人也一样,实际上是使用像素中100%透明的所有颜色位。由于这些像素是透明的,因此将它们设置为什么颜色都没有关系。

但是,由于我正在使用整个图像,因此无法执行此操作,这意味着我没有透明像素可以使用。

为什么不赞成仅将这种技术存储在元数据中呢?

  • 很有趣!:)
  • 服务可能会破坏元数据(可能是一种隐私/安全功能),但除非有强烈的图像托管要求(看着您,facebook),否则不应破坏png的像素。但是,如果他们完全重新导出您的图像,则您无能为力。

额外的功劳:为了降低噪声的可见性,您可以使用带有固定种子的PRNG选择要修改的像素。您也只能以类似方式修改某些颜色通道。


6
有一些隐写算法比Monaco方法在图像缩放/颜色调整方面更强大。(尽管它们通常以低得多的密度存储数据)一个例子是《魔兽世界》屏幕截图中使用的水印:owncore.com/forums/world-of-warcraft/…–
DMGregory

@DMGregory很好找到!您选择的精确算法当然应该由您的特定用例(空间,耐用性,保密性等)决定。
亚历克西斯·贝辛斯纳2014年

1
听起来很酷,但这是个坏主意。PNG图像使用无损图像压缩;摆弄图像的低位可能会同时使文件变大,因为它(略微)降低了图像质量。绝对任何信息都可以编码为“文本”,因此使用元数据块显然是正确的方法。摆弄图像位而实际上不需要隐写术的人只是突然出现。
dfeuer 2014年

1
@dfeuer-显然Spore和Monaco都在使用具有资源加载管道的游戏框架,该资源加载管道将.PNG剥离为裸露的位图,因此元数据块无法通过。
罗素·博罗戈夫

1
@dfeuer我做了一些幼稚的测试。当向1920x1080px图像写入100kB随机位时,元数据方法似乎会增加速记方法所增加的大小的80%。在空白图片和桌面截图上进行了测试。这并不完全是灾难性的差异,但是如果您真的担心40kB以上的数据,meatadata肯定会更好(并且更加一致)。请注意,元数据仍然效率很低。通过写入100kB数据,我获得了181kB!可能是优化字符串编码方式或其他方式的空间。
亚历克西斯·贝辛斯纳2014年

7

我下载并检查了一些来自孢子虫的孢子生物。从那些我了解到:

  • 这些图像除标准图像数据外不包含任何信息。
  • 速记数据的存储没有考虑到图像,可以想象透明部分是专门使用的,但没有使用。
  • 存储的使用取决于需要存储的信息量,有些图像仅使用最低有效位进行数据存储,有些使用两个最低有效位,有些则使用更多。
  • 孢子格式避免只在图像的一部分上使用位,在整个图像中最低有效位会发生变化,如果使用了第二最低有效位,则会在整个图像上使用。大概是使用随机填充完成的。这避免了质量的变化,这种变化可能比噪声本身更给观看者带来不便。
  • 所有四个通道均被平等使用,不透明度通道没有得到特殊处理,因此某些透明像素有些不透明,而某些不透明像素有些透明。

值得注意的是,这正是Spore所做的,它是一种将简单性放在大多数其他问题之前的方法。

选择使用速记技术而不是使用其他数据块意味着如果重新编码图像(例如通过网站),则数据将保留下来,尽管它在缩放或Jpeg压缩后将无法幸存。

我认为最突出的选择实际上是只对图像中的一个id编码,然后将实际数据存储在中央服务器上,在此该ID可以交换为确切的生物数据。这样的id足够短,以致可以以缩放和压缩容忍的速记格式进行编码。

对孢子格式可能的简单改进包括:

  • 仅使用或更喜欢使用透明像素的颜色值,它们不会产生视觉差异。
  • 多使用蓝色通道,少使用绿色通道,蓝色对图像的影响较小。
  • 保持每个像素的亮度接近不变并以色度对数据进行编码,此参数中的一点噪声实际上是人类无法检测到的。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.