Search code examples
c#pngexifimagesharpsixlabors.imagesharp

How to tell SixLabors.ImageSharp to write metadata as tEXt and not zTXt?


I am making an editor for TavernAI character cards that encode the character data into an tEXt EXIF field.

It seemed to work fine at first until i loaded a character card into Silly Tavern, a popular TavernAI fork, at which point it said that there was no character metadata. Turns out that ImageSharp was putting long text metadata in zTXt format, which is not supported by the spec.

This is how i approached saving a character card:

using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Formats.Png.Chunks;
using SixLabors.ImageSharp.PixelFormats;

using var image = new Image<Rgba32>(1, 1);

var imageMetadata = image.Metadata.GetPngMetadata();

var metadataList = (List<PngTextData>)imageMetadata.TextData;
metadataList.RemoveAll(m => m.Keyword == "chara");

var aLotOfText = new string('a', 50000); // It seems to compress only if the text is big
var metadataEntry = new PngTextData("chara", aLotOfText, string.Empty, string.Empty);
metadataList.Add(metadataEntry);

image.SaveAsPng("test.png");

You can check that it outputs zTXt metadata by running exiftool -v test.png. Is there a way to tell SixLabors.ImageSharp to write long metadata chunks as tEXt and not zTXt?


Solution

  • Turns out that ImageSharp was putting long text metadata in zTXt format, which is not supported by the spec.

    You mean the Silly Tavern specification yeah? because zTxt chunks are absolutely supported by the png specification.

    https://www.w3.org/TR/PNG-Chunks.html

    To force ImageSharp to use tEXt you can new up a PngEncoder instance and change the Threshold property to a larger value. Then pass the encoder to your SaveAsPng method.