| | 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..."; |
| | } |
| | } |
| | } |
| |
|