如何在C#中读取PNG文件元数据中的Stable Diffusion提示词
如何在C#中读取PNG文件元数据中的Stable Diffusion提示词
我明白你现在卡在哪了——用Bitmap类读取PNG里的Stable Diffusion提示词时,不管试0x0110还是其他ID,都找不到对应的元数据项对吧?我来帮你梳理下问题根源和解决办法。
首先,先看看你当前的代码:
using (var image = new Bitmap(imagePath)) { // Get the metadata property items var propertyItems = image.PropertyItems; // Find the Stable Diffusion prompt property var stableDiffusionPrompt = Array.Find(propertyItems, p => p.Id == 0x0110); // 0x0110 is the ID for the Stable Diffusion prompt property if (stableDiffusionPrompt != null) { string prompt = GetStringFromProperty(stableDiffusionPrompt); Debug.WriteLine($"Stable Diffusion Prompt: {prompt}"); } else { Debug.WriteLine("Stable Diffusion Prompt not found in the image metadata."); } }
问题出在哪?
Bitmap类的PropertyItems主要读取的是标准EXIF元数据,但Stable Diffusion生成的提示词大多不会存在这些标准字段里。像Automatic1111这类主流工具,会把提示词、采样步数、模型参数等信息存在PNG文件的自定义tEXt chunk里,而GDI+的Bitmap并不会解析这些自定义chunk。
解决办法:直接解析PNG的tEXt chunk
大多数Stable Diffusion工具会把提示词存在名为parameters的tEXt chunk中,我们可以直接读取PNG文件的结构来提取这个信息,不用依赖Bitmap类。
这里给你写了一个实用的方法:
using System.IO; using System.Text; using System.Linq; public static string ReadStableDiffusionPromptFromPng(string imagePath) { using (var fs = new FileStream(imagePath, FileMode.Open, FileAccess.Read)) using (var br = new BinaryReader(fs)) { // 验证PNG文件头 var pngHeader = br.ReadBytes(8); if (!pngHeader.SequenceEqual(new byte[] { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A })) { throw new InvalidDataException("输入文件不是有效的PNG格式"); } while (fs.Position < fs.Length) { // 读取chunk长度(PNG用大端字节序) var lengthBytes = br.ReadBytes(4).Reverse().ToArray(); int chunkLength = BitConverter.ToInt32(lengthBytes, 0); // 读取chunk类型 string chunkType = Encoding.ASCII.GetString(br.ReadBytes(4)); if (chunkType == "tEXt") { // 读取tEXt chunk的内容 byte[] textData = br.ReadBytes(chunkLength); int nullSeparatorIndex = Array.IndexOf(textData, (byte)0); if (nullSeparatorIndex != -1) { // 提取关键字和对应的内容 string keyword = Encoding.UTF8.GetString(textData, 0, nullSeparatorIndex); if (keyword.Equals("parameters", StringComparison.OrdinalIgnoreCase)) { string promptContent = Encoding.UTF8.GetString(textData, nullSeparatorIndex + 1, textData.Length - nullSeparatorIndex - 1); return promptContent; } } } else { // 跳过非tEXt类型的chunk数据和CRC校验位 fs.Seek(chunkLength + 4, SeekOrigin.Current); } } } // 没找到对应chunk时返回null return null; } // 调用示例 var prompt = ReadStableDiffusionPromptFromPng(imagePath); if (!string.IsNullOrEmpty(prompt)) { Debug.WriteLine($"Stable Diffusion Prompt: {prompt}"); } else { Debug.WriteLine("未在图片元数据中找到Stable Diffusion提示词"); }
额外说明
- 如果你的图片是用其他工具生成的,可能需要调整关键字(比如有的工具会用
prompt而不是parameters),可以根据实际情况修改代码里的判断条件。 - 这个方法直接操作PNG文件流,不依赖GDI+的元数据解析,能更准确地提取Stable Diffusion的自定义信息。
备注:内容来源于stack exchange,提问作者Philip
相关产品推荐
相关产品推荐

