Comment puis-je stocker des métadonnées de jeu dans un fichier .png?

208

Spore permet aux créatures créées par le joueur d'être partagées en exportant un .pngfichier. C'est .pngune photo de la créature, mais si elle est importée dans le jeu, les informations de la créature (telles que les textures, la taille et la forme) sont également fournies.

Comment puis-je implémenter une telle fonctionnalité?

ibrabeicker
la source
5
Devrait avoir un score beaucoup plus élevé, c'est une question très intéressante.
Pierre Arlaud
3
Le canal alpha pourrait être partiellement abusé pour cela ...
Tobias Kienzler
3
D'utilisation possible: stackoverflow.com/questions/9542359/…
unité logique
1
Je pense qu'il est préférable de stocker ces données dans un autre fichier. Dans ce fichier, il devrait y avoir le nom du fichier de texture associé à une entité pour laquelle vous souhaitez que les données soient stockées. Tout d’abord par souci d’explicitation (le format png est utilisé pour les graphiques - "Portable Network Graphics"), ensuite: si vous souhaitez stocker davantage d’images avec une entité, vous pouvez simplement y ajouter des références à partir de ce fichier personnalisé. Vous aurez probablement du mal à stocker différentes images (taille différente, profondeur différente, etc.) dans un seul fichier PNG.
luke1985
3
Le canal alpha a été beaucoup mentionné et, bien sûr, les PNG prennent en charge les métadonnées, mais je pensais partager une technique déjà utilisée: défiler de gauche à droite, de haut en bas, et dans un ordre fixe. et arrondir les valeurs à des probabilités faibles ou égales - peu importe que ce soit à la hausse ou à la baisse. Un changement de 1 dans TOUS les canaux ne fait aucune différence notable, et dans une image de 256 x 256 (à 4 bits par pixel bien sûr), vous pouvez stocker une impressionnante quantité de données de 32 Ko. Si vous avez encore besoin de plus, vous pouvez arrondir à 4% à la place - trop et cela commence à ressembler à un vieil esprit GIF ..
Octopoid

Réponses:

56

Si vous n'aviez besoin que du fichier PNG, il est probable qu'ils ont simplement ajouté les informations dans le fichier. C'est en fait une pratique de la stéganographie . Souvent, cela est utilisé pour masquer des charges utiles ou des messages secrets dans des choses apparemment publiques. Cependant, il est probable dans ce cas que cette méthode soit celle qui a été utilisée. Une stégongraphie typique fera tout pour cacher le contenu, mais il n'y a aucune raison pour laquelle on ne pourrait pas simplement ajouter les données de l'image à la fin du fichier et les récupérer.

Plusieurs outils encodent ces données pour vous, une recherche sur Google fait apparaître au moins ceci et cela .

Un fichier PNG ayant la signature octet $89au début, il est donc possible que les informations aient été insérées après la structure PNG elle-même et simplement analysées par le jeu SPORE.

Cependant, une recherche plus poussée donnée par les autres réponses et une recherche sur Google révèle que Spore utilisait en réalité une version de Stegongraphy pour masquer les informations contenues dans les bits alpha. En gardant cela à l'esprit, nous pouvons exclure la possibilité d'ajouter des données ou des méta-données.

Il convient de noter que les métadonnées restent un choix très viable si les données sont analysées localement. Si ces informations peuvent être partagées sur le Web ou réencodées, l’exportation n’est pas garantie pour conserver toutes vos informations. Lorsque des données de pixels sont utilisées, elles peuvent survivre sans conversions sans perte.

Vaughan Hilts
la source
3
Autant que je sache, spore a stocké des métadonnées à l'intérieur du canal alpha du PNG.
Tara
28
Pourquoi utiliser le canal alpha ou la stéganographie lorsque le format PNG prend en charge des fragments de métadonnées arbitraires?
Russell Borogove
8
"Un fichier PNG portant la signature d'octet" 89 "au début, il est donc très probable que les informations aient été insérées avant ou après la structure PNG elle-même et simplement analysées par le jeu SPORE." Si tel était le cas, il ne serait t être un fichier PNG plus. Les visualiseurs d'image courants ne pourraient pas l'afficher.
svick
3
@RussellBorogove est une assez bonne raison: si le fichier PNG est décodé / encodé par quelque chose en plus de Spore, les fragments de métadonnées arbitraires risquent davantage d'être ignorés ou perdus que les données d'image réelles. Le codage des données dans l'image augmente la probabilité que vous puissiez les charger si vous les voyez .
Tim S.
@svick En fait, j'ai joué avec un fichier qui était à la fois un fichier PNG et RAR valide. L'en-tête RAR a commencé après le fichier PNG et les extrames de RAR étaient bons. Cela peut aussi bien fonctionner dans l'autre sens.
cortices
153

Le format PNG prend en charge les métadonnées plus ou moins arbitraires. La norme PNG définit un fichier PNG, essentiellement une série de morceaux, dont certains sont nécessaires (et contiennent les données d'image). D'autres, cependant, sont facultatifs. Par exemple, un morceau permet de stocker des informations gamma ou des données d'histogramme.

En particulier, il existe un tEXtbloc qui peut être utilisé pour stocker des paires de texte clé / valeur arbitraires. Cela peut être utilisé pour envoyer n'importe quel type de données arbitraires, à condition que vous puissiez les représenter sous forme de texte (ce qui est assez probable).

Vous aurez besoin d'une bibliothèque PNG qui vous permettra d'accéder à ces fragments supplémentaires (tels que la bibliothèque de référence ) et de les manipuler , ou vous devrez en écrire un vous-même. Ensuite, il suffit de choisir comment coder les données souhaitées sous forme de paires clé / valeur. Je suggère ce qui suit:

  • choisissez des noms de clés précédés du nom de votre projet ou du nom de code de votre projet afin de créer un système "d'espace de noms" brut et évitez les conflits potentiels avec l'utilisation des données par une autre application
  • n'essayez pas de stocker les textures réelles de cette façon, stockez des références à ces textures qui pointent dans la base de données d'actifs de votre jeu
  • des données telles que la taille de la créature ou de l'objet, son poids, etc. - des scalaires simples, en gros - peuvent être stockées de manière triviale

Dans l’intérêt d’une réponse plus complète, je soulignerai également qu’il existe une autre approche (déjà documentée par les réponses @Vaughn et @ Alexis): coder les données supplémentaires souhaitées directement dans vos pixels d’image, en répartissant vos données sur les bits de poids faible des canaux de couleur. Cette approche ne nécessite pas l’utilisation de métadonnées supplémentaires, ce qui signifie que vous pouvez l’implémenter entièrement sans vous en fier ou sans vous soucier des programmes externes qui gèrent ces métadonnées de manière incorrecte. Son facteur de "fraîcheur" est également très élevé et, du fait que vous n'utilisez que des bits de poids faible, l'image sera toujours correcte à l'œil humain. Toutefois, cela signifie que la taille de votre image est un facteur de contrôle principal pour la quantité de données que vous pouvez stocker. si vous avez besoin de plus de stockage, vous devrez allouer plus de pixels à l’image.

Comme d'autres l'ont souligné, ce processus s'appelle la stéganographie .

Josh
la source
3
On pourrait simplement envoyer les données via Base64 et les stocker en tant que valeur unique
CodesInChaos
11
@ da4c30ff Aussi pratique que soient les métadonnées, la stéganographie a un certain facteur de fantaisie-espionnage-fantaisie auquel notre public a du mal à résister. Si je le faisais moi-même, j'utiliserais la méthode d'évolutivité proposée par Josh Petrie, mais je serais fortement tenté d'utiliser la stéganographie pour masquer une somme de contrôle dans l'image elle-même afin de vérifier que l'image et le texte appartiennent l'un à l'autre - non pas c'est utile ou sécurisé, mais juste parce que c'est cool. ;)
DMGregory
Que veut dire exactement "texte" ici? Seulement ASCII (caractère <= 127)? N'importe quel octet sauf 0? Un octet du tout? Ou autre chose? (Cela affectera l'encodage que vous devez utiliser pour écrire des données binaires. Par exemple, que vous ayez besoin de base64 ou non.)
svick
1
J'ai mis à jour la réponse avec un lien vers la norme pour le bloc de texte; mais fondamentalement, le texte est interprété conformément à la norme ISO 8859-1 (8 bits, caractères sur un octet, caractères latins-1).
Josh
51

Le développeur de Monaco a en fait fait un excellent article sur la façon dont Spore et eux ont accompli cela.

Le résumé de base de ce qu’ils font est assez simple:

  • Convertissez vos données en binaire
  • Convertissez votre image cible en un bitmap brut
  • Marchez le long des pixels de l'image selon un schéma prévisible (ils font simplement de gauche à droite à partir du coin supérieur gauche).
  • Écrire un bit sur le bit d'ordre le plus bas de chaque canal de couleur de chaque pixel
  • Exportez à nouveau le bitmap modifié en png

Faites simplement cela en sens inverse pour récupérer vos données.

L'idée de base du processus est qu'il y a beaucoup de pixels dans une image et que les bits de poids faible de chaque canal de couleur ne font pas une grande différence. En outre, environ la moitié des bits que vous écrivez correspondront à ce qu’il était déjà dans l’image. Ce que vous récupérez est essentiellement la bonne image, mais avec des artefacts étranges. Il prend le temps de noter que ces artefacts ne sont vraiment visibles que si vous montez vraiment le contraste / la saturation et effectuez un zoom avant. Il a cependant des images source avec beaucoup de bruit initial.

De l'article:

Notez dans la dernière image qu’il ya une ligne horizontale à peine perceptible dans le bruit. C'est la fin des données de niveau. Cela signifie que je peux réellement insérer toutes les données de niveau dans une image de 265x120 pixels, en n'utilisant que le bit le moins significatif.

Un additif rapide:

Une chose que je pourrais faire, et je pense que les gens de Spore l’ont aussi fait, est d’utiliser en réalité TOUS les bits de couleur en pixels qui sont 100% transparents. Étant donné que ces pixels sont transparents, la couleur que vous définissez importe peu.

Cependant, je ne peux pas faire cela car j'utilise toute l'image, ce qui signifie que je n'ai pas de pixels transparents avec lesquels travailler.

Pourquoi préférer cette technique au stockage dans les métadonnées?

  • C'est funner! :)
  • Les services peuvent modifier les métadonnées (éventuellement comme une fonctionnalité de confidentialité / sécurité), mais ne doivent pas modifier les pixels de votre png, à moins qu'ils ne soient soumis à des conditions strictes en matière d'hébergement de l'image (vous regarde, facebook). Mais si elles sont complètement re-exporter votre image il n'y a rien que vous fiable pouvez faire.

Crédit supplémentaire: pour réduire la visibilité du bruit, vous pouvez utiliser un PRNG avec une valeur de départ fixe pour sélectionner les pixels à modifier. Vous pouvez également modifier certains canaux de couleur de la même manière.

Alexis Beingessner
la source
6
Il existe des algorithmes stéganographiques qui sont plus robustes que la méthode de Monaco contre le redimensionnement de l’image / le réglage des couleurs. (Bien qu'ils stockent généralement des données à une densité sensiblement plus faible) Un exemple est le tatouage utilisé dans les captures d'écran de World of Warcraft: owncore.com/forums/world-of-warcraft/…
DMGregory
@DMGregory Belle trouvaille! L'algorithme précis que vous choisissez devrait bien sûr être décidé par votre cas d'utilisation spécifique (espace, durabilité, secret, etc.).
Alexis Beingessner
1
Aussi cool que cela puisse paraître, c'est une mauvaise idée. Les images PNG utilisent la compression d' image sans perte. En manipulant les bits les plus bas de l'image, le fichier sera plus volumineux en même temps qu'il réduit (légèrement) la qualité de l'image. Absolument, toutes les informations peuvent être codées sous forme de "texte". L'utilisation d'un bloc de métadonnées est donc le moyen le plus approprié de procéder. quelqu'un qui tripote des bits d'image sans avoir réellement besoin de la stéganographie ne fait que déborder de la roue.
dfeuer
1
@dfeuer - Spore et Monaco utilisaient apparemment des frameworks de jeu dotés d'un pipeline de chargement d'actifs qui réduit le fichier .PNG à une simple image bitmap, de sorte que les blocs de métadonnées n'y parviennent pas.
Russell Borogove
1
@dfeuer J'ai fait des tests naïfs. L'approche par métadonnées semble ajouter environ 80% de la taille ajoutée par l'approche sténographique lors de l'écriture de 100 Ko de bits aléatoires sur une image de 1920x1080px. Testé sur une image vierge et une capture d'écran du bureau. Ce n'est pas vraiment une différence catastrophique, mais meatadata est certainement meilleur (et plus cohérent) si vous vous inquiétez vraiment pour plus de 40ko. Notez que les métadonnées étaient encore assez inefficaces. J'ai gagné 181 Ko pour écrire 100 Ko de données! Peut-être place pour optimiser la façon dont la chaîne est codée ou quelque chose.
Alexis Beingessner
7

J'ai téléchargé et examiné quelques créatures Spore de Sporepedia. De ceux que j'ai appris que:

  • Les images ne contiennent aucune information en plus des données d'image standard.
  • Les données sténographiques ont été stockées sans aucune considération pour l’image, on pourrait imaginer que les parties transparentes ont été utilisées exclusivement, mais ce n’est pas le cas.
  • L’utilisation de la mémoire dépend de la quantité d’informations à stocker, certaines images n’utilisent que le bit le moins significatif pour le stockage des données, certaines utilisent les deux bits les moins significatifs, d’autres peuvent en utiliser davantage.
  • Le format Spore évite d’utiliser un bit sur une partie seulement de l’image. Le bit le moins significatif change dans l’ensemble de l’image. Si le deuxième bit le moins significatif est utilisé, il est utilisé pour l’ensemble de l’image. Ceci est probablement fait en utilisant un remplissage aléatoire. Cela évite un changement de qualité qui pourrait être plus gênant pour le spectateur que le bruit lui-même.
  • Les quatre canaux sont utilisés de manière égale, le canal d'opacité ne faisant l'objet d'aucun traitement particulier, certains des pixels transparents sont légèrement opaques, tandis que d'autres des pixels opaques sont légèrement transparents.

Il convient de noter que c’est précisément ce que fait Spore, c’est une méthode qui place la simplicité avant la plupart des autres problèmes.

Le choix d'utiliser la sténographie plutôt qu'un bloc de données supplémentaire signifie que les données survivront si l'image est réencodée, par exemple par un site Web, bien qu'elle ne puisse pas survivre à la mise à l'échelle ou à la compression Jpeg.

Je pense que l'alternative la plus importante est en fait de ne coder qu'un identifiant dans l'image et de laisser les données réelles stockées sur un serveur central où cet identifiant peut être échangé contre les données exactes de la créature. Un tel identifiant serait suffisamment court pour pouvoir être encodé dans un format sténographique tolérant la mise à l'échelle et la compression.

Les améliorations simples possibles au format Spore incluent:

  • Utilisez uniquement ou préférez utiliser les valeurs de couleur des pixels transparents, elles ne font aucune différence visuelle.
  • Utilisez davantage le canal bleu et le canal vert moins, la couleur bleue a un impact moindre sur l’image.
  • En gardant la luminance de chaque pixel presque inchangée et en codant les données en chrominance, un petit bruit dans ce paramètre est pratiquement indétectable pour l'homme.
aaaaaaaaaaaa
la source