| using PNGReaderTest; |
| using SixLabors.ImageSharp; |
| using System.Data; |
| using System.Text.Json; |
| using Image = SixLabors.ImageSharp.Image; |
|
|
| namespace PNGMetadataViewer |
| { |
| public partial class PNGMetadataViewerForm : Form |
| { |
| protected bool validData; |
|
|
| string path; |
| protected List<object> textValues; |
| protected Image image; |
| protected Thread getImageThread; |
|
|
| public PNGMetadataViewerForm() |
| { |
| InitializeComponent(); |
| } |
|
|
| private void Form1_Load(object sender, EventArgs e) |
| { |
|
|
| } |
|
|
| private void formTableLayoutPanel_DragEnter(object sender, DragEventArgs e) |
| { |
| string filename; |
|
|
| validData = GetFilename(out filename, e); |
| if (validData) |
| { |
| path = filename; |
| getImageThread = new Thread(new ThreadStart(LoadImage)); |
| getImageThread.Start(); |
| e.Effect = DragDropEffects.Copy; |
| } |
| else |
| { |
| e.Effect = DragDropEffects.None; |
| } |
| } |
|
|
| private bool GetFilename(out string filename, DragEventArgs e) |
| { |
| bool ret = false; |
| filename = String.Empty; |
| if ((e.AllowedEffect & DragDropEffects.Copy) == DragDropEffects.Copy) |
| { |
| Array? data = e.Data.GetData("FileDrop") as Array; |
| if (data != null) |
| { |
| if ((data.Length == 1) && (data.GetValue(0) is String)) |
| { |
| filename = ((string[])data)[0]; |
| string ext = Path.GetExtension(filename).ToLower(); |
| if ((ext == ".jpg") || (ext == ".png") || (ext == ".bmp")) |
| { |
| ret = true; |
| } |
| } |
| } |
| } |
| return ret; |
| } |
|
|
| private void formTableLayoutPanel_DragDrop(object sender, DragEventArgs e) |
| { |
| if (validData) |
| { |
| clearAll(); |
|
|
| while (getImageThread.IsAlive) |
| { |
| Application.DoEvents(); |
| Thread.Sleep(0); |
| } |
|
|
| pictureBox.Image = ImageExtensions.ToNetImage(image.ToArray()); |
|
|
| imageMetadataGridView.DataSource = MakeImageMetadataTable(image); |
|
|
| var pngTextData = image.Metadata.GetPngMetadata().TextData; |
|
|
| if (pngTextData.Count == 1) |
| { |
| toolStripStatusLabel.Text = $"Automatic1111 Generated PNG: {path}"; |
|
|
| |
| var promptsData = image.Metadata.GetPngMetadata().TextData[0].Value.Split("\n"); |
|
|
| promptBox.Text = promptsData[0]; |
| negativePromptBox.Text = promptsData[1].Replace("Negative prompt:", string.Empty); |
|
|
| var modelData = promptsData[2].Split(',', StringSplitOptions.TrimEntries); |
| modelMetadataGridView.DataSource = MakeAutomatic1111DataTable(modelData); |
| } |
| else if (pngTextData.Count > 1) |
| { |
| toolStripStatusLabel.Text = $"ComfyUI Generated PNG: {path}"; |
|
|
| |
| var comfyUIMetadata = JsonSerializer.Deserialize<ComfyUIData>(pngTextData[1].Value); |
|
|
| if (comfyUIMetadata == null) |
| { |
| MessageBox.Show("Could not load ComfyUI Metadata", "Error"); |
| } |
| else |
| { |
| modelMetadataGridView.DataSource = MakeComfyUIKSamplerDataTable(comfyUIMetadata); |
|
|
| textValues = comfyUIMetadata.nodes.Where(x => x.type.Equals("CLIPTextEncode")).SelectMany(x => x.widgets_values).ToList(); |
|
|
| promptBox.Text = textValues.Count() > 0 ? textValues[1]?.ToString() : string.Empty; |
| negativePromptBox.Text = textValues.Count() > 0 ? textValues[0].ToString() : string.Empty; |
| } |
| } |
| else |
| { |
| |
|
|
| toolStripStatusLabel.Text = $"No text data found in PNG: {path}"; |
| } |
| } |
| } |
| protected void LoadImage() |
| { |
| image = Image.Load(path); |
| } |
|
|
| private DataTable MakeComfyUIKSamplerDataTable(ComfyUIData data) |
| { |
| var table = new DataTable(); |
|
|
| table.Columns.Add(new DataColumn("Key", typeof(string))); |
| table.Columns.Add(new DataColumn("Value", typeof(string))); |
|
|
| var ksamplerFields = new[] { "Seed", "Control After Generate", "Steps", "CFG", "Sampler Name", "Scheduler", "Denoise" }; |
|
|
| var checkpointLoader = data.nodes.Where(x => x.type.Contains("CheckpointLoaderSimple")).Select(x => x.widgets_values).FirstOrDefault(); |
| table.Rows.Add("Model Name", checkpointLoader != null ? checkpointLoader[0] ?? "Unknown" : "Unknown"); |
|
|
| var loraLoader = data.nodes.Where(x => x.type.Equals("LoraLoader")).SelectMany(x => x.widgets_values).ToList(); |
| table.Rows.Add("LORA Name", loraLoader?.Count != 0 ? loraLoader?[0] : "None"); |
|
|
| int i = 0; |
|
|
| foreach (var ksamplerItem in data.nodes.Where(x => x.type.Equals("KSampler")).Select(x => x.widgets_values).SelectMany(x => x)) |
| { |
| table.Rows.Add(ksamplerFields[i++], ksamplerItem); |
| } |
|
|
| return table; |
| } |
|
|
| private DataTable MakeAutomatic1111DataTable(string[] data) |
| { |
| var table = new DataTable(); |
|
|
| table.Columns.Add(new DataColumn("Key", typeof(string))); |
| table.Columns.Add(new DataColumn("Value", typeof(string))); |
|
|
| foreach (var item in data) |
| { |
| var k = item.Split(':'); |
| table.Rows.Add(k[0], k[1]); |
| } |
|
|
| return table; |
| } |
|
|
| private DataTable MakeImageMetadataTable(Image image) |
| { |
| var table = new DataTable(); |
|
|
| table.Columns.Add(new DataColumn("Key", typeof(string))); |
| table.Columns.Add(new DataColumn("Value", typeof(string))); |
|
|
| table.Rows.Add("Height", image.Height); |
| table.Rows.Add("Width", image.Width); |
| table.Rows.Add("AlphaRepresentation", image.PixelType.AlphaRepresentation?.ToString()); |
| table.Rows.Add("BitsPerPixel", image.PixelType.BitsPerPixel); |
| table.Rows.Add("DefaultMimeType", image.Metadata.DecodedImageFormat?.DefaultMimeType); |
| table.Rows.Add("Name", image.Metadata.DecodedImageFormat?.Name); |
| table.Rows.Add("ColorType", image.Metadata.GetPngMetadata().ColorType); |
| table.Rows.Add("FramesCount", image.Frames.Count()); |
|
|
| return table; |
| } |
|
|
| private void copyPromptMenuItem_Click(object sender, EventArgs e) |
| { |
| ToolStripItem? item = sender as ToolStripItem; |
| if (item != null) |
| { |
| ContextMenuStrip? owner = item.Owner as ContextMenuStrip; |
| if (owner != null && !string.IsNullOrEmpty(owner.SourceControl?.Text)) |
| { |
| Clipboard.SetText(owner.SourceControl.Text, TextDataFormat.Text); |
| toolStripStatusLabel.Text = "Copied..."; |
| } |
| } |
| } |
|
|
| private void clearButton_Click(object sender, EventArgs e) |
| { |
| clearAll(); |
| } |
|
|
| private void clearAll() |
| { |
| pictureBox.Image = null; |
| promptBox.Text = string.Empty; |
| negativePromptBox.Text = string.Empty; |
| modelMetadataGridView.DataSource = null; |
| imageMetadataGridView.DataSource = null; |
| toolStripStatusLabel.Text = "Waiting for input..."; |
| } |
| } |
| } |
|
|