<commit_before>﻿#define ShowImage
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using CSharpGL;
using ImageSharp.Extension;
using ImGui.GraphicsImplementation;
using ImGui.Input;
using ImGui.OSAbstraction.Graphics;
using ImGui.OSImplementation.Shared;
using ImGui.OSImplementation.Windows;
using ImGui.Rendering;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;

namespace ImGui.UnitTest
{
    public static class Util
    {
        public static readonly string OutputPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "/ImGui.UnitTest.Output";

        public static readonly string UnitTestRootDir = Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"..\..\..")) + Path.DirectorySeparatorChar;

        static Util()
        {
            Directory.CreateDirectory(OutputPath);
        }

        public static void CheckEchoLogger()
        {
            var processes = Process.GetProcessesByName("EchoLogger.Server");
            if (processes.Length == 0)
            {
                throw new InvalidOperationException("EchoLogger.Server not started.");
            }
        }

        public static void SelectFile(string path)
        {
            if (!Directory.Exists(path))
            {
                throw new FileNotFoundException(path);
            }
            Process.Start("explorer", "/select," + path);
        }

        public static void OpenDirectory(string path)
        {
            if(!Directory.Exists(path))
            {
                throw new DirectoryNotFoundException(path);
            }
            Process.Start("explorer", path);
        }

        public static void OpenImage(string path)
        {
            if (!File.Exists(path))
            {
                throw new FileNotFoundException(path);
            }
            if (!File.Exists(@"C:\Program Files\Windows Photo Viewer\PhotoViewer.dll"))
            {
                throw new FileNotFoundException("Windows Photo Viewer not found.");
            }
            path = Path.GetFullPath(path);
            Process.Start("rundll32.exe", @"""C:\Program Files\Windows Photo Viewer\PhotoViewer.dll"",ImageView_Fullscreen " + path);
        }

        public static void SelectFileInExplorer(string path)
        {
            if(!File.Exists(path))
            {
                throw new FileNotFoundException();
            }
            string argument = "/select, \"" + path +"\"";
            Process.Start("explorer", argument);
        }

        public static void OpenModel(string path)
        {
            const string ModelViewerPath = @"Z:\Program Files\Side Effects Software\Houdini 18.0.460\bin\gplay.exe";
            if(!File.Exists(ModelViewerPath))
            {
                throw new FileNotFoundException("ModelViewer(Houdini gplay) not found.");
            }
            if (!File.Exists(path))
            {
                throw new FileNotFoundException(path);
            }
            Process.Start(ModelViewerPath, path);
        }

        #region Image

        public static Image<Rgba32> CreateImage(byte[] data, int width, int height, bool flip)
        {
            var img = Image.LoadPixelData<Rgba32>(Configuration.Default, data, width, height);
            if (flip)
            {
                img.Mutate(x => x.Flip(FlipMode.Vertical));
            }
            return img;
        }

        public static void SaveImage(Image<Rgba32> image, string path)
        {
            var dirPath = Path.GetDirectoryName(path);
            if (!Directory.Exists(dirPath))
            {
                Directory.CreateDirectory(dirPath);
            }
            using (var stream = File.OpenWrite(path))
            {
                image.SaveAsPng(stream);
            }
        }

        public static bool CompareImage(Image<Rgba32> a, Image<Rgba32> b)
        {
            var diffPercentage = ImageComparer.PercentageDifference(a,b, 20);
            return diffPercentage < 0.1;
        }

        public static bool CompareImage(Image<Rgba32> a, Image<Bgra32> b)
        {
            var diffPercentage = ImageComparer.PercentageDifference(a,b, 20);
            return diffPercentage < 0.1;
        }

        public static Image<Rgba32> LoadImage(string filePath)
        {
            return Image.Load<Rgba32>(filePath);
        }

        public static void CheckExpectedImage(byte[] imageRawBytes, int width, int height, string expectedImageFilePath)
        {
            var image = Util.CreateImage(imageRawBytes, width, height, flip: false);
#if DEBUG//check if it matches expected image
            var expectedImage = Util.LoadImage(expectedImageFilePath);

#if ShowImage
            var actualImagePath = Environment.ExpandEnvironmentVariables("%TEMP%") + Path.DirectorySeparatorChar + "actual.png";
            var expectedImagePath = Util.UnitTestRootDir + expectedImageFilePath;
            if (File.Exists(actualImagePath))
            {
                File.Delete(actualImagePath);
            }
            Util.SaveImage(image, actualImagePath);
            Util.OpenImage(actualImagePath);
            Util.OpenImage(expectedImagePath);
#endif

            Debug.Assert(Util.CompareImage(expectedImage, image));
#else//generate expected image
            var path = Util.UnitTestRootDir + expectedImageFilePath;
            Util.SaveImage(image, path);
            Util.SelectFileInExplorer(path);
            Util.OpenImage(path);
#endif
        }

        public static void ShowImage(byte[] imageRawBytes, int width, int height, string path)
        {
            using var image = CreateImage(imageRawBytes, width, height, flip: true);
            SaveImage(image, (string)path);
            SelectFileInExplorer((string)path);
            OpenImage((string)path);
        }

        internal static void ShowImageNotOpenFolder(byte[] imageRawBytes, int width, int height, string path)
        {
            using var image = CreateImage(imageRawBytes, width, height, flip: true);
            Util.SaveImage(image, path);
            Util.OpenImage(path);
        }

        #endregion

        #region Node

        #region Cairo

        internal static void DrawNode(Node node, [CallerMemberName] string memberName = "")
        {
            using (Cairo.ImageSurface surface = new Cairo.ImageSurface(Cairo.Format.Argb32, (int)node.Rect.Width, (int)node.Rect.Height))
            using (Cairo.Context context = new Cairo.Context(surface))
            {
                Draw(context, node);

                if (!Directory.Exists(OutputPath))
                {
                    Directory.CreateDirectory(OutputPath);
                }

                string filePath = OutputPath + "\\" + DateTime.UtcNow.ToString("yyyy-MM-dd_HH-mm-ss-fff_") + surface.GetHashCode() + memberName + ".png";
                surface.WriteToPng(filePath);
                Util.OpenImage(filePath);
            }
        }

        private static void Draw(Cairo.Context context, Visual visual)
        {<commit_msg>Don't flip when saving raw pixel bytes to an image<commit_after>﻿#define ShowImage
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using CSharpGL;
using ImageSharp.Extension;
using ImGui.GraphicsImplementation;
using ImGui.Input;
using ImGui.OSAbstraction.Graphics;
using ImGui.OSImplementation.Shared;
using ImGui.OSImplementation.Windows;
using ImGui.Rendering;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;

namespace ImGui.UnitTest
{
    public static class Util
    {
        public static readonly string OutputPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "/ImGui.UnitTest.Output";

        public static readonly string UnitTestRootDir = Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"..\..\..")) + Path.DirectorySeparatorChar;

        static Util()
        {
            Directory.CreateDirectory(OutputPath);
        }

        public static void CheckEchoLogger()
        {
            var processes = Process.GetProcessesByName("EchoLogger.Server");
            if (processes.Length == 0)
            {
                throw new InvalidOperationException("EchoLogger.Server not started.");
            }
        }

        public static void SelectFile(string path)
        {
            if (!Directory.Exists(path))
            {
                throw new FileNotFoundException(path);
            }
            Process.Start("explorer", "/select," + path);
        }

        public static void OpenDirectory(string path)
        {
            if(!Directory.Exists(path))
            {
                throw new DirectoryNotFoundException(path);
            }
            Process.Start("explorer", path);
        }

        public static void OpenImage(string path)
        {
            if (!File.Exists(path))
            {
                throw new FileNotFoundException(path);
            }
            if (!File.Exists(@"C:\Program Files\Windows Photo Viewer\PhotoViewer.dll"))
            {
                throw new FileNotFoundException("Windows Photo Viewer not found.");
            }
            path = Path.GetFullPath(path);
            Process.Start("rundll32.exe", @"""C:\Program Files\Windows Photo Viewer\PhotoViewer.dll"",ImageView_Fullscreen " + path);
        }

        public static void SelectFileInExplorer(string path)
        {
            if(!File.Exists(path))
            {
                throw new FileNotFoundException();
            }
            string argument = "/select, \"" + path +"\"";
            Process.Start("explorer", argument);
        }

        public static void OpenModel(string path)
        {
            const string ModelViewerPath = @"Z:\Program Files\Side Effects Software\Houdini 18.0.460\bin\gplay.exe";
            if(!File.Exists(ModelViewerPath))
            {
                throw new FileNotFoundException("ModelViewer(Houdini gplay) not found.");
            }
            if (!File.Exists(path))
            {
                throw new FileNotFoundException(path);
            }
            Process.Start(ModelViewerPath, path);
        }

        #region Image

        public static Image<Rgba32> CreateImage(byte[] data, int width, int height, bool flip)
        {
            var img = Image.LoadPixelData<Rgba32>(Configuration.Default, data, width, height);
            if (flip)
            {
                img.Mutate(x => x.Flip(FlipMode.Vertical));
            }
            return img;
        }

        public static void SaveImage(Image<Rgba32> image, string path)
        {
            var dirPath = Path.GetDirectoryName(path);
            if (!Directory.Exists(dirPath))
            {
                Directory.CreateDirectory(dirPath);
            }
            using (var stream = File.OpenWrite(path))
            {
                image.SaveAsPng(stream);
            }
        }

        public static bool CompareImage(Image<Rgba32> a, Image<Rgba32> b)
        {
            var diffPercentage = ImageComparer.PercentageDifference(a,b, 20);
            return diffPercentage < 0.1;
        }

        public static bool CompareImage(Image<Rgba32> a, Image<Bgra32> b)
        {
            var diffPercentage = ImageComparer.PercentageDifference(a,b, 20);
            return diffPercentage < 0.1;
        }

        public static Image<Rgba32> LoadImage(string filePath)
        {
            return Image.Load<Rgba32>(filePath);
        }

        public static void CheckExpectedImage(byte[] imageRawBytes, int width, int height, string expectedImageFilePath)
        {
            var image = Util.CreateImage(imageRawBytes, width, height, flip: false);
#if DEBUG//check if it matches expected image
            var expectedImage = Util.LoadImage(expectedImageFilePath);

#if ShowImage
            var actualImagePath = Environment.ExpandEnvironmentVariables("%TEMP%") + Path.DirectorySeparatorChar + "actual.png";
            var expectedImagePath = Util.UnitTestRootDir + expectedImageFilePath;
            if (File.Exists(actualImagePath))
            {
                File.Delete(actualImagePath);
            }
            Util.SaveImage(image, actualImagePath);
            Util.OpenImage(actualImagePath);
            Util.OpenImage(expectedImagePath);
#endif

            Debug.Assert(Util.CompareImage(expectedImage, image));
#else//generate expected image
            var path = Util.UnitTestRootDir + expectedImageFilePath;
            Util.SaveImage(image, path);
            Util.SelectFileInExplorer(path);
            Util.OpenImage(path);
#endif
        }

        public static void ShowImage(byte[] imageRawBytes, int width, int height, string path)
        {
            using var image = CreateImage(imageRawBytes, width, height, flip: false);
            SaveImage(image, (string)path);
            SelectFileInExplorer((string)path);
            OpenImage((string)path);
        }

        internal static void ShowImageNotOpenFolder(byte[] imageRawBytes, int width, int height, string path)
        {
            using var image = CreateImage(imageRawBytes, width, height, flip: false);
            Util.SaveImage(image, path);
            Util.OpenImage(path);
        }

        #endregion

        #region Node

        #region Cairo

        internal static void DrawNode(Node node, [CallerMemberName] string memberName = "")
        {
            using (Cairo.ImageSurface surface = new Cairo.ImageSurface(Cairo.Format.Argb32, (int)node.Rect.Width, (int)node.Rect.Height))
            using (Cairo.Context context = new Cairo.Context(surface))
            {
                Draw(context, node);

                if (!Directory.Exists(OutputPath))
                {
                    Directory.CreateDirectory(OutputPath);
                }

                string filePath = OutputPath + "\\" + DateTime.UtcNow.ToString("yyyy-MM-dd_HH-mm-ss-fff_") + surface.GetHashCode() + memberName + ".png";
                surface.WriteToPng(filePath);
                Util.OpenImage(filePath);
            }
        }

        private static void Draw(Cairo.Context context, Visual visual)
        {
{'fraction_non_alphanumeric': 0.09665813325953089, 'fraction_numerical': 0.005120044281464056, 'mean_word_length': 2.0213210702341136, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5248337', 'n_tokens_mistral': 3844, 'n_tokens_neox': 3668, 'n_words': 809}