¿Cómo puedo almacenar los metadatos del juego en un archivo .png?


208

Spore permite compartir criaturas creadas por el jugador al exportar un .pngarchivo. Esa .pnges una foto de la criatura, pero si se importa al juego, la información de la criatura (como texturas, tamaño y forma) también viene con ella.

¿Cómo puedo implementar tal característica?


55
Debería tener una puntuación mucho más alta, esa es una pregunta muy interesante.
Pierre Arlaud

3
El canal alfa podría ser parcialmente abusado por esto ...
Tobias Kienzler


1
Creo que es mejor almacenar estos datos en otro archivo. En este archivo, debe haber el nombre del archivo de textura que está relacionado con una entidad que desea tener datos almacenados. Primero por razones de explicidad (el formato png es para gráficos - "Gráficos de red portátiles"), segundo: considere una situación en la que desea almacenar más imágenes con una entidad, simplemente puede agregarle referencias desde ese archivo personalizado. Probablemente tendrá problemas para almacenar diferentes imágenes (de diferentes tamaños, diferentes profundidades, etc.) en un PNG.
luke1985

3
El canal alfa se ha mencionado mucho y, por supuesto, los PNG admiten metadatos de todos modos, pero solo pensé en compartir una técnica que he utilizado: pasar de izquierda a derecha, de arriba a abajo y a través de los canales en un orden fijo y redondear los valores a probabilidades o pares , no importa si está arriba o abajo. Un cambio de 1 en CUALQUIERA de los canales no hace una diferencia notable, y en una imagen de 256x256 (a 4 bits por píxel, por supuesto), puede almacenar una impresionante cantidad de 32 KB de datos. Si necesita aún más, puede redondear a% 4 en su lugar, demasiado y comienza a parecerse a una vieja mente GIF ...
Octopoid

Respuestas:


56

Si todo lo que realmente necesitaba era el archivo PNG, es probable que simplemente agreguen la información al archivo. Esto es en realidad una práctica de esteganografía . Muchas veces, esto se usa para ocultar cargas útiles o mensajes secretos en cosas que aparentemente son públicas. Sin embargo, es probable en este caso que este método sea el utilizado. La Stegongraphy típica se saldrá del camino para ocultar el contenido, pero no hay ninguna razón por la que uno no pueda simplemente agregar los datos de la imagen al final del archivo y recuperarlos.

Varias herramientas codifican estos datos por usted, una búsqueda en Google trae al menos esto y esto .

Un PNG tiene la firma de bytes $89al comienzo, por lo que es posible que la información se haya insertado después de la estructura PNG y simplemente haya sido analizada por el juego SPORE.

Sin embargo, una investigación adicional dada por las otras respuestas y una búsqueda en Google revela que Spore estaba usando solo una versión de Stegongraphy para ocultar la información en los bits alfa. Con esto en mente, podemos descartar la posibilidad de agregar datos o metadatos.

Cabe señalar que los metadatos siguen siendo una opción muy viable, si los datos se analizan localmente. Si esa información se comparte en la web o se vuelve a codificar, no se garantiza que la exportación conserve toda su información. Cuando se utilizan datos de píxeles, puede sobrevivir a las conversiones sin pérdida sin problemas.


3
Hasta donde sé, las esporas almacenaron metadatos dentro del canal alfa de PNG.
Tara

28
¿Por qué usar el canal alfa o la esteganografía cuando PNG admite fragmentos de metadatos arbitrarios?
Russell Borogove

8
"Un PNG tiene la firma de byte" 89 "al principio, por lo que es muy probable que la información se haya insertado antes o después de la estructura PNG y simplemente haya sido analizada por el juego SPORE". Si ese fuera el caso, entonces no sería Ya no es un archivo PNG. Es decir, los espectadores de imágenes comunes no podrían mostrarlo.
svick

3
@RussellBoro obtuvo una razón bastante buena: si el PNG está decodificado / codificado por algo además de Spore, es más probable que los fragmentos de metadatos arbitrarios sean ignorados o perdidos que los datos de imagen reales. Codificar los datos en la imagen mejora la probabilidad de que si puede verlos, puede cargarlos .
Tim S.

@svick En realidad, jugué con un archivo que era tanto PNG como RAR válido. El encabezado RAR comenzó después del PNG, y los extractores RAR estaban bien. Puede funcionar bien a la inversa también.
cortezas

153

El formato PNG es compatible con metadatos más o menos arbitrarios. El estándar PNG define un archivo PNG, esencialmente una serie de fragmentos, algunos de los cuales son necesarios (y contienen los datos de la imagen). Otros, sin embargo, son opcionales. Por ejemplo, hay un fragmento para almacenar información gamma o datos de histograma.

En particular, hay un tEXtfragmento que se puede utilizar para almacenar pares de texto de clave / valor arbitrarios. Esto se puede usar para enviar cualquier tipo de datos arbitrarios que desee, siempre que pueda representar esos datos como texto (lo cual es bastante probable).

Necesitará una biblioteca PNG que le permita acceder y manipular estos fragmentos adicionales (como la biblioteca de referencia ), o deberá escribir uno usted mismo. Entonces es solo cuestión de elegir cómo codificar los datos que desea como pares clave / valor. Sugeriría lo siguiente:

  • elija nombres clave que tengan como prefijo el nombre de su proyecto o el nombre de código como una forma de crear un sistema de "espacio de nombres" crudo y evite posibles conflictos con los usos de los datos por parte de otras aplicaciones
  • no intente almacenar texturas reales de esta manera, almacene referencias a esas texturas que apuntan dentro de la base de datos de activos de su propio juego
  • datos como el tamaño de la criatura u objeto, el peso, etc., escalares simples, básicamente, pueden almacenarse trivialmente

En aras de dar una respuesta más completa, también señalaré que hay otro enfoque (previamente documentado por las respuestas de @Vaughn y @ Alexis): codifique los datos adicionales que desee directamente en los píxeles de su imagen, distribuyendo sus datos a través de los bits de bajo orden de los canales de color. Este enfoque no requiere el uso de metadatos adicionales, lo que significa que puede implementarlo por completo sin depender de él o preocuparse por los programas externos que manejan incorrectamente esos metadatos. También tiene un factor "genial" muy alto, y debido a que solo usa bits de bajo orden, la imagen seguirá siendo correcta para el ojo humano. Sin embargo, significa que el tamaño de su imagen es un factor de control primario para la cantidad de datos que puede almacenar; Si necesita más almacenamiento, deberá asignar más píxeles a la imagen.

Como otros han señalado, este proceso se conoce como esteganografía .


3
Uno podría simplemente enviar los datos a través de Base64 y almacenarlos como un valor único
CodesInChaos

11
@ da4c30ff A pesar de lo prácticos que son los metadatos, la esteganografía tiene un cierto factor genial de espía-fantasía que es difícil de resistir para nuestra multitud. Si lo hiciera yo mismo, usaría el método propuesto de Josh Petrie para la escalabilidad, pero me sentiría muy tentado a usar la esteganografía para ocultar una suma de verificación en la imagen en sí misma para verificar que la imagen y el texto se pertenecen entre sí, no porque Esto es útil o seguro, pero solo porque es genial. ;)
DMGregory

¿Qué significa exactamente "texto" aquí? ¿Solo ASCII (carácter <= 127)? Cualquier byte excepto 0? ¿Algún byte? ¿O algo mas? (Esto afectará la codificación que necesita usar para escribir datos binarios. Por ejemplo, si necesita base64 o no.)
svick

1
Actualicé la respuesta con un enlace al estándar para el fragmento de texto; pero, básicamente, el texto se interpreta según ISO 8859-1 (caracteres de 8 bits, un byte, Latin-1).
Josh

51

El desarrollador de Mónaco en realidad hizo un excelente artículo sobre cómo tanto ellos como Spore lograron esto.

El resumen básico de lo que hacen es bastante simple:

  • Convierte tus datos en binario
  • Convierta su imagen de destino en un mapa de bits sin procesar
  • Camine a lo largo de los píxeles de la imagen en un patrón predecible (simplemente lo hacen de izquierda a derecha desde la esquina superior izquierda).
  • Escriba un bit en el bit de orden más bajo de cada canal de color de cada píxel
  • Exporte el mapa de bits modificado a png nuevamente

Simplemente haga esto a la inversa para recuperar sus datos.

La idea básica detrás del proceso es que hay muchos píxeles en una imagen, y los bits de orden más bajo de cada canal de color no hacen una gran diferencia. Además, aproximadamente la mitad de los bits que escriba serán lo que ya era en la imagen. Lo que obtienes es esencialmente la imagen correcta, pero con artefactos extraños. Se toma el tiempo para notar que estos artefactos solo son realmente notables si realmente aumenta el contraste / saturación y se acerca. Sin embargo, tiene imágenes de origen con mucho ruido inicial.

Del artículo:

Observe en la última imagen cómo hay una línea horizontal apenas perceptible en el ruido. Ese es el final de los datos de nivel. Lo que esto significa es que realmente puedo ajustar todos los datos de nivel en una imagen de 265x120 píxeles, solo usando el bit menos significativo.

Un truco adicional:

Algo que podría hacer, y creo que la gente de Spore también lo hizo, es usar TODOS los bits de color en píxeles que son 100% transparentes. Dado que esos píxeles son transparentes, no importa en qué color los configure.

Sin embargo, no puedo hacer esto, ya que estoy usando toda la imagen, lo que significa que no tengo píxeles transparentes para trabajar.

¿Por qué favorecer esta técnica en lugar de almacenarla en los metadatos?

  • ¡Es más divertido! :)
  • Los servicios pueden alterar los metadatos (posiblemente como una característica de privacidad / seguridad), pero no deben alterar los píxeles de sus png a menos que tengan requisitos de alojamiento de imágenes agresivos (mirándolo, Facebook). Pero si están reexportando completamente su imagen, no hay nada que pueda hacer de manera confiable .

Crédito adicional: para reducir la notoriedad del ruido, puede usar un PRNG con una semilla fija para seleccionar los píxeles para modificar. También puede modificar solo algunos de los canales de color de manera similar.


66
Hay algoritmos esteganográficos que son más robustos contra el ajuste de escala / color de la imagen que el método de Mónaco. (Aunque generalmente almacenan datos a una densidad sustancialmente menor) Un ejemplo es la marca de agua utilizada en las capturas de pantalla de World of Warcraft: owncore.com/forums/world-of-warcraft/…
DMGregory

@DMGregory ¡Buen hallazgo! Por supuesto, el algoritmo preciso que elija debe decidirlo su caso de uso específico (espacio, durabilidad, secreto, etc.).
Alexis Beingessner 01 de

1
Por muy bueno que parezca, es una mala idea. Las imágenes PNG utilizan compresión de imagen sin pérdida; juguetear con los bits bajos de la imagen probablemente hará que el archivo sea más grande al mismo tiempo que reduce (ligeramente) la calidad de la imagen. Absolutamente cualquier información puede codificarse como "texto", por lo que usar un fragmento de metadatos es la forma obviamente correcta de hacer esto; alguien tocando fragmentos de imagen sin necesitar realmente la esteganografía es simplemente caballitos.
dfeuer

1
@dfeuer: Aparentemente, tanto Spore como Mónaco estaban usando marcos de juego que tienen una canalización de carga de activos que elimina el .PNG en un mapa de bits desnudo, por lo que los fragmentos de metadatos no se lograron.
Russell Borogove

1
@dfeuer Hice algunas pruebas ingenuas. El enfoque de metadatos parece agregar aproximadamente el 80% del tamaño agregado por el enfoque estenográfico al escribir 100kB de bits aleatorios en una imagen de 1920x1080px. Probado en una imagen en blanco y captura de pantalla de escritorio. No es exactamente una diferencia catastrófica, pero los metadatos son ciertamente mejores (y más consistentes) si realmente le preocupan más de 40kB. Tenga en cuenta que los metadatos todavía eran bastante ineficientes. ¡Gané 181kB por escribir 100kB de datos! Podría haber espacio para optimizar cómo se codifica la cadena o algo así.
Alexis Beingessner

7

Descargué y examiné algunas criaturas Spore de Sporepedia. De aquellos aprendí que:

  • Las imágenes no contienen información además de los datos de imagen estándar.
  • Los datos estenográficos se han almacenado sin tener en cuenta la imagen, uno podría imaginar que las partes transparentes se usaron exclusivamente, pero no lo son.
  • El uso del almacenamiento depende de la cantidad de información que necesita ser almacenada, algunas de las imágenes usan solo el bit menos significativo para el almacenamiento de datos, algunas usan los dos bits menos significativos, algunas pueden usar más.
  • El formato Spore evita el uso de un bit en solo una parte de la imagen, el bit menos significativo cambia en toda la imagen, si se usa el segundo bit menos significativo, se usa en toda la imagen. Esto se hace presumiblemente usando relleno aleatorio. Esto evita un cambio en la calidad que podría ser más molesto para el espectador que el ruido en sí.
  • Los cuatro canales se usan por igual, el canal de opacidad no recibe un tratamiento especial, por lo que algunos de los píxeles transparentes son ligeramente opacos, mientras que algunos de los píxeles opacos son ligeramente transparentes.

Vale la pena señalar que esto es justo lo que hace Spore, es un método que pone la simplicidad antes que la mayoría de las otras preocupaciones.

La elección de usar estenografía en lugar de un bloque de datos adicional significa que los datos sobrevivirán si la imagen se vuelve a codificar, por ejemplo, por un sitio web, aunque no sobrevivirá a la escala o la compresión Jpeg.

Creo que la alternativa más destacada es en realidad codificar solo una identificación en la imagen y dejar que los datos reales se almacenen en un servidor central donde esta identificación se pueda intercambiar por los datos exactos de la criatura. Tal identificación sería lo suficientemente corta como para poder codificarse en un formato de estenografía tolerante a la compresión y al escalado.

Las posibles mejoras simples al formato Spore incluyen:

  • Use solo o prefiera usar los valores de color de píxeles transparentes, no hacen una diferencia visual.
  • Use el canal azul más y el canal verde menos, el color azul tiene un menor impacto percibido en la imagen.
  • Manteniendo la luminancia de cada píxel casi sin cambios y codificando los datos en croma, un poco de ruido en este parámetro es prácticamente indetectable para los humanos.
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.