| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949 | using InABox.Core;using Syncfusion.Pdf.Parsing;using System.Drawing.Drawing2D;using System.Drawing.Imaging;using System.Globalization;using System.IO;using System.Runtime.InteropServices;using System.Windows;using System.Windows.Interop;using System.Windows.Media;using System.Windows.Media.Imaging;using System.Xml.Linq;using ColorHelper;using Color = System.Drawing.Color;using Pen = System.Drawing.Pen;using PixelFormat = System.Drawing.Imaging.PixelFormat;using Point = System.Drawing.Point;using Size = System.Drawing.Size;using System.Windows.Controls;using System.Drawing;using System.Collections.Generic;using System;using System.Linq;using Syncfusion.Pdf.Graphics;using Syncfusion.Pdf;namespace InABox.WPF{    public static class ImageUtils    {                // https://en.wikipedia.org/wiki/List_of_file_signatures        /* Bytes in c# have a range of 0 to 255 so each byte can be represented as         * a two digit hex string. */        private static readonly Dictionary<ImageFormat, string[][]> SignatureTable = new()        {            {                ImageFormat.Jpeg,                new[]                {                    new[] { "FF", "D8", "FF", "DB" },                    new[] { "FF", "D8", "FF", "EE" },                    new[] { "FF", "D8", "FF", "E0", "00", "10", "4A", "46", "49", "46", "00", "01" }                }            },            {                ImageFormat.Gif,                new[]                {                    new[] { "47", "49", "46", "38", "37", "61" },                    new[] { "47", "49", "46", "38", "39", "61" }                }            },            {                ImageFormat.Png,                new[]                {                    new[] { "89", "50", "4E", "47", "0D", "0A", "1A", "0A" }                }            },            {                ImageFormat.Bmp,                new[]                {                    new[] { "42", "4D" }                }            }        };        public static Size Adjust(this Size src, double maxWidth, double maxHeight, bool enlarge = false)        {            maxWidth = enlarge ? maxWidth : Math.Min(maxWidth, src.Width);            maxHeight = enlarge ? maxHeight : Math.Min(maxHeight, src.Height);            var rnd = Math.Min((decimal)maxWidth / src.Width, (decimal)maxHeight / src.Height);            return new Size((int)Math.Round(src.Width * rnd), (int)Math.Round(src.Height * rnd));        }        public static Bitmap AsGrayScale(this Bitmap source)        {            //create a blank bitmap the same size as original            var newBitmap = new Bitmap(source.Width, source.Height);            //get a graphics object from the new image            var g = Graphics.FromImage(newBitmap);            //create the grayscale ColorMatrix            var colorMatrix = new ColorMatrix(                new[]                {                    new[] { .3f, .3f, .3f, 0, 0 },                    new[] { .59f, .59f, .59f, 0, 0 },                    new[] { .11f, .11f, .11f, 0, 0 },                    new float[] { 0, 0, 0, 1, 0 },                    new float[] { 0, 0, 0, 0, 1 }                });            //create some image attributes            var attributes = new ImageAttributes();            //set the color matrix attribute            attributes.SetColorMatrix(colorMatrix);            //draw the original image on the new image            //using the grayscale color matrix            g.DrawImage(source, new Rectangle(0, 0, source.Width, source.Height),                0, 0, source.Width, source.Height, GraphicsUnit.Pixel, attributes);            //dispose the Graphics object            g.Dispose();            return newBitmap;        }        public static BitmapImage AsBitmapImage(this Bitmap src, int height, int width, bool transparent = true)        {            var resized = new Bitmap(src, new Size(width, height));            return AsBitmapImage(resized, transparent);        }        public static BitmapImage AsBitmapImage(this Bitmap src, Color transparent)        {            src.MakeTransparent(transparent);            return src.AsBitmapImage();        }        public static Bitmap ChangeColor(this Bitmap image, Color fromColor, Color toColor)        {            var attributes = new ImageAttributes();            attributes.SetRemapTable(new ColorMap[]            {                new()                {                    OldColor = fromColor,                    NewColor = toColor                }            }, ColorAdjustType.Bitmap);            using (var g = Graphics.FromImage(image))            {                g.DrawImage(                    image,                    new Rectangle(Point.Empty, image.Size),                    0, 0, image.Width, image.Height,                    GraphicsUnit.Pixel,                    attributes);            }            return image;        }        public static Bitmap Fade(this Bitmap source, float opacity)        {            var result = new Bitmap(source.Width, source.Height);            //create a graphics object from the image              using (var gfx = Graphics.FromImage(result))            {                if (opacity < 1.0)                    gfx.Clear(Color.White);                //create a color matrix object                  var matrix = new ColorMatrix();                //set the opacity                  matrix.Matrix33 = opacity;                //create image attributes                  var attributes = new ImageAttributes();                //set the color(opacity) of the image                  attributes.SetColorMatrix(matrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);                //now draw the image                  gfx.DrawImage(source, new Rectangle(0, 0, source.Width, source.Height), 0, 0, source.Width, source.Height, GraphicsUnit.Pixel,                    attributes);            }            return result;        }        public static BitmapImage AsBitmapImage(this Bitmap src, Color replace, Color with)        {            return src.ChangeColor(replace, with).AsBitmapImage(false);        }        public static Bitmap AsBitmap(this BitmapImage bitmapImage)        {            using (var outStream = new MemoryStream())            {                BitmapEncoder enc = new BmpBitmapEncoder();                enc.Frames.Add(BitmapFrame.Create(bitmapImage));                enc.Save(outStream);                var bitmap = new Bitmap(outStream);                return new Bitmap(bitmap);            }        }        public static Bitmap AsBitmap(this BitmapSource source)        {            var width = source.PixelWidth;            var height = source.PixelHeight;            var stride = width * ((source.Format.BitsPerPixel + 7) / 8);            var ptr = IntPtr.Zero;            try            {                ptr = Marshal.AllocHGlobal(height * stride);                source.CopyPixels(new Int32Rect(0, 0, width, height), ptr, height * stride, stride);                using (var btm = new Bitmap(width, height, stride, PixelFormat.Format1bppIndexed, ptr))                {                    return new Bitmap(btm);                }            }            finally            {                if (ptr != IntPtr.Zero)                    Marshal.FreeHGlobal(ptr);            }        }        public static Bitmap AsBitmap2(this BitmapSource source)        {            var bmp = new Bitmap(                source.PixelWidth,                source.PixelHeight,                PixelFormat.Format32bppPArgb);            var data = bmp.LockBits(                new Rectangle(Point.Empty, bmp.Size),                ImageLockMode.WriteOnly,                PixelFormat.Format32bppPArgb);            source.CopyPixels(                Int32Rect.Empty,                data.Scan0,                data.Height * data.Stride,                data.Stride);            bmp.UnlockBits(data);            return bmp;        }        public static BitmapImage? BitmapImageFromBase64(string base64)        {            return BitmapImageFromBytes(Convert.FromBase64String(base64));        }        public static BitmapImage? BitmapImageFromBytes(byte[] data)        {            var imageSource = new BitmapImage();            if(data.Length > 0)            {                using (var ms = new MemoryStream(data))                {                    imageSource.BeginInit();                    imageSource.StreamSource = ms;                    imageSource.CacheOption = BitmapCacheOption.OnLoad;                    imageSource.EndInit();                }                return imageSource;            }            return null;        }                public static BitmapImage? BitmapImageFromStream(Stream data)        {            var imageSource = new BitmapImage();            imageSource.BeginInit();            imageSource.StreamSource = data;            imageSource.CacheOption = BitmapCacheOption.OnLoad;            imageSource.EndInit();            return imageSource;        }        public static BitmapImage AsBitmapImage(this Bitmap src, bool transparent = true)        {            if (transparent)            {                var pixel = src.GetPixel(0, 0);                if(pixel.A == byte.MaxValue)                {                    src.MakeTransparent(pixel);                }            }            var bitmapImage = new BitmapImage();            using (var memory = new MemoryStream())            {                src.Save(memory, ImageFormat.Png);                memory.Position = 0;                bitmapImage.BeginInit();                bitmapImage.StreamSource = memory;                bitmapImage.CacheOption = BitmapCacheOption.OnLoad;                bitmapImage.EndInit();            }            return bitmapImage;        }        public static BitmapSource AsBitmapSource(this Metafile metafile, int width, int height, Color background)        {            var src = new Bitmap(metafile.Width, metafile.Height);            src.SetResolution(metafile.HorizontalResolution, metafile.VerticalResolution);            using (var g = Graphics.FromImage(src))            {                g.DrawImage(metafile, 0, 0, metafile.Width, metafile.Height);            }            var scale = Math.Min(width / (float)metafile.Width, height / (float)metafile.Height);            var scaleWidth = src.Width * scale;            var scaleHeight = src.Height * scale;            var xoffset = (width - scaleWidth) / 2.0F;            var yoffset = (height - scaleHeight) / 2.0F;            using (var bmp = new Bitmap(width, height))            {                bmp.SetResolution(metafile.HorizontalResolution, metafile.VerticalResolution);                using (var g = Graphics.FromImage(bmp))                {                    g.InterpolationMode = InterpolationMode.High;                    g.CompositingQuality = CompositingQuality.HighQuality;                    g.SmoothingMode = SmoothingMode.AntiAlias;                    g.FillRectangle(new SolidBrush(background), new RectangleF(0, 0, width, height));                    g.DrawImage(src, xoffset, yoffset, scaleWidth, scaleHeight);                }                bmp.Save("c:\\development\\emf2bmp.png");                return Imaging.CreateBitmapSourceFromHBitmap(bmp.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());            }        }        public static Bitmap BitmapSourceToBitmap(BitmapSource source)        {            if (source == null)                return null;            var pixelFormat = System.Drawing.Imaging.PixelFormat.Format32bppArgb;  //Bgr32 equiv default            if (source.Format == PixelFormats.Bgr24)                pixelFormat = System.Drawing.Imaging.PixelFormat.Format24bppRgb;            else if (source.Format == PixelFormats.Pbgra32)                pixelFormat = System.Drawing.Imaging.PixelFormat.Format32bppPArgb;            else if (source.Format == PixelFormats.Prgba64)                pixelFormat = System.Drawing.Imaging.PixelFormat.Format64bppPArgb;            Bitmap bmp = new Bitmap(                source.PixelWidth,                source.PixelHeight,                pixelFormat);            BitmapData data = bmp.LockBits(                new Rectangle(System.Drawing.Point.Empty, bmp.Size),                ImageLockMode.WriteOnly,                pixelFormat);            source.CopyPixels(                Int32Rect.Empty,                data.Scan0,                data.Height * data.Stride,                data.Stride);            bmp.UnlockBits(data);            return bmp;        }        public static BitmapImage ToBitmapImage(this Bitmap bitmap)        {            using (var memory = new MemoryStream())            {                bitmap.Save(memory, ImageFormat.Png);                memory.Position = 0;                var bitmapImage = new BitmapImage();                bitmapImage.BeginInit();                bitmapImage.StreamSource = memory;                bitmapImage.CacheOption = BitmapCacheOption.OnLoad;                bitmapImage.EndInit();                bitmapImage.Freeze();                return bitmapImage;            }        }        public static BitmapImage LoadImage(byte[] imageData)        {            var result = new BitmapImage();            result.LoadImage(imageData);            return result;        }        public static void LoadImage(this BitmapImage image, byte[]? imageData)        {            if (imageData == null || imageData.Length == 0)                return;            using (var mem = new MemoryStream(imageData))            {                mem.Position = 0;                image.BeginInit();                image.CreateOptions = BitmapCreateOptions.PreservePixelFormat;                image.CacheOption = BitmapCacheOption.OnLoad;                image.UriSource = null;                image.StreamSource = mem;                image.EndInit();            }            image.Freeze();        }                public static Bitmap? MergeBitmaps(IEnumerable<Bitmap> bitmaps, int padding)        {            if (!bitmaps.Any())                return null;                        var totalwidth = bitmaps.Aggregate(0, (total, next) => total + next.Width + (total > 0 ? padding : 0) );            var maxheight = bitmaps.Aggregate(0, (max, next) => Math.Max(next.Height,max) );            Bitmap result = new Bitmap(totalwidth, maxheight);              using (Graphics g = Graphics.FromImage(result))              {                  g.Clear(Color.Transparent);                int left = 0;                foreach (var bitmap in bitmaps)                {                    g.DrawImage(bitmap, left, 0);                    left += bitmap.Width + padding;                }            }            return result;          }                  public static byte[] ToArray<T>(this BitmapImage image) where T : BitmapEncoder, new()        {            byte[] data;            var encoder = new T();            encoder.Frames.Add(BitmapFrame.Create(image));            using (var ms = new MemoryStream())            {                encoder.Save(ms);                data = ms.ToArray();            }            return data;        }        public static BitmapImage Resize(this BitmapImage image, int height, int width)        {            var buffer = image.ToArray<BmpBitmapEncoder>();            var ms = new MemoryStream(buffer);            var result = new BitmapImage();            result.BeginInit();            result.CacheOption = BitmapCacheOption.None;            result.CreateOptions = BitmapCreateOptions.IgnoreColorProfile;            result.DecodePixelWidth = width;            result.DecodePixelHeight = height;            result.StreamSource = ms;            result.Rotation = Rotation.Rotate0;            result.EndInit();            buffer = null;            return result;        }        public static Bitmap Resize(this Bitmap bitmap, int width, int height)        {            if ((width == bitmap.Width) && (height == bitmap.Height))                return bitmap;            return new Bitmap(bitmap,new Size(width,height));        }        public static BitmapImage Scale(this BitmapImage image, int maxheight, int maxwidth)        {            var scaleHeight = maxheight / (float)image.Height;            var scaleWidth = maxwidth / (float)image.Width;            var scale = Math.Min(scaleHeight, scaleWidth);            return image.Resize((int)(image.Height * scale), (int)(image.Width * scale));        }        public static Bitmap BitmapFromColor(Color color, int width, int height, Color frame)        {            var result = new Bitmap(width, height);            var g = Graphics.FromImage(result);            g.Clear(color);            if (frame != Color.Transparent)                g.DrawRectangle(new Pen(new SolidBrush(frame), 1), new Rectangle(0, 0, width-1, height-1));            return result;        }                public static Bitmap BitmapFromColor(System.Windows.Media.Color color, int width, int height, System.Windows.Media.Color frame)        {            var result = new Bitmap(width, height);            var g = Graphics.FromImage(result);            g.Clear(Color.FromArgb(color.A,color.R,color.G,color.B));            if (frame != Colors.Transparent)                g.DrawRectangle(new Pen(new SolidBrush(Color.FromArgb(frame.A,frame.R,frame.G,frame.B)), 1F), new Rectangle(0, 0, width-1, height-1));            return result;        }        public static Color MixColors(this Color color1, double factor, Color color2)        {            if (factor < 0) throw new Exception($"Factor {factor} must be >= 0.");            if (factor > 1) throw new Exception($"Factor {factor} must be <= 1.");            if (factor == 0) return color2;            if (factor == 1) return color1;            var factor1 = 1 - factor;            return Color.FromArgb(                (byte)(color1.A * factor + color2.A * factor1),                (byte)(color1.R * factor + color2.R * factor1),                (byte)(color1.G * factor + color2.G * factor1),                (byte)(color1.B * factor + color2.B * factor1));        }        public static System.Windows.Media.Color MixColors(this System.Windows.Media.Color color1, double factor, System.Windows.Media.Color color2)        {            if (factor < 0) throw new Exception($"Factor {factor} must be >= 0.");            if (factor > 1) throw new Exception($"Factor {factor} must be <= 1.");            if (factor == 0) return color2;            if (factor == 1) return color1;            var factor1 = 1 - factor;            return System.Windows.Media.Color.FromArgb(                (byte)(color1.A * factor + color2.A * factor1),                (byte)(color1.R * factor + color2.R * factor1),                (byte)(color1.G * factor + color2.G * factor1),                (byte)(color1.B * factor + color2.B * factor1));        }        public static string ColorToString(Color color)        {            return string.Format("#{0:X2}{1:X2}{2:X2}{3:X2}",                color.A,                color.R,                color.G,                color.B            );        }        public static Color StringToColor(string colorcode)        {            var col = Color.Transparent;            if (!string.IsNullOrEmpty(colorcode))            {                var code = colorcode.Replace("#", "");                if (code.Length == 6)                    col = Color.FromArgb(255,                        byte.Parse(code.Substring(0, 2), NumberStyles.HexNumber),                        byte.Parse(code.Substring(2, 2), NumberStyles.HexNumber),                        byte.Parse(code.Substring(4, 2), NumberStyles.HexNumber));                else if (code.Length == 8)                    col = Color.FromArgb(                        byte.Parse(code.Substring(0, 2), NumberStyles.HexNumber),                        byte.Parse(code.Substring(2, 2), NumberStyles.HexNumber),                        byte.Parse(code.Substring(4, 2), NumberStyles.HexNumber),                        byte.Parse(code.Substring(6, 2), NumberStyles.HexNumber));            }            return col;        }        public static System.Windows.Media.Color StringToMediaColor(string colorcode)        {            var col = Colors.Transparent;            if (!string.IsNullOrEmpty(colorcode))            {                var code = colorcode.Replace("#", "");                if (code.Length == 6)                    col = System.Windows.Media.Color.FromArgb(255,                        byte.Parse(code.Substring(0, 2), NumberStyles.HexNumber),                        byte.Parse(code.Substring(2, 2), NumberStyles.HexNumber),                        byte.Parse(code.Substring(4, 2), NumberStyles.HexNumber));                else if (code.Length == 8)                    col = System.Windows.Media.Color.FromArgb(                        byte.Parse(code.Substring(0, 2), NumberStyles.HexNumber),                        byte.Parse(code.Substring(2, 2), NumberStyles.HexNumber),                        byte.Parse(code.Substring(4, 2), NumberStyles.HexNumber),                        byte.Parse(code.Substring(6, 2), NumberStyles.HexNumber));            }            return col;        }        /// <summary>        ///     Creates color with corrected brightness.        /// </summary>        /// <param name="color">Color to correct.</param>        /// <param name="correctionFactor">        ///     The brightness correction factor. Must be between -1 and 1.        ///     Negative values produce darker colors.        /// </param>        /// <returns>        ///     Corrected <see cref="Color" /> structure.        /// </returns>        public static System.Windows.Media.Color AdjustBrightness(this System.Windows.Media.Color color, float correctionFactor)        {            float red = color.R;            float green = color.G;            float blue = color.B;            if (correctionFactor < 0)            {                correctionFactor = 1 + correctionFactor;                red *= correctionFactor;                green *= correctionFactor;                blue *= correctionFactor;            }            else            {                red = (255 - red) * correctionFactor + red;                green = (255 - green) * correctionFactor + green;                blue = (255 - blue) * correctionFactor + blue;            }            return System.Windows.Media.Color.FromArgb(color.A, (byte)red, (byte)green, (byte)blue);        }        /// <summary>        ///     Takes a byte array and determines the image file type by        ///     comparing the first few bytes of the file to a list of known        ///     image file signatures.        /// </summary>        /// <param name="imageData">Byte array of the image data</param>        /// <returns>ImageFormat corresponding to the image file format</returns>        /// <exception cref="ArgumentException">Thrown if the image type can't be determined</exception>        public static ImageFormat GetImageType(byte[] imageData)        {            foreach (var signatureEntry in SignatureTable)            foreach (var signature in signatureEntry.Value)            {                var isMatch = true;                for (var i = 0; i < signature.Length; i++)                {                    var signatureByte = signature[i];                    // ToString("X") gets the hex representation and pads it to always be length 2                    var imageByte = imageData[i]                        .ToString("X2");                    if (signatureByte == imageByte)                        continue;                    isMatch = false;                    break;                }                if (isMatch) return signatureEntry.Key;            }            throw new ArgumentException("The byte array did not match any known image file signatures.");        }        public static System.Drawing.Bitmap Invert(this System.Drawing.Bitmap source)        {            Bitmap bmpDest = new Bitmap(source.Width,source.Height);            ColorMatrix clrMatrix = new ColorMatrix(new float[][]            {                new float[] {-1, 0, 0, 0, 0},                new float[] {0, -1, 0, 0, 0},                new float[] {0, 0, -1, 0, 0},                new float[] {0, 0, 0, 1, 0},                new float[] {1, 1, 1, 0, 1}            });            using (ImageAttributes attrImage = new ImageAttributes())            {                attrImage.SetColorMatrix(clrMatrix);                using (Graphics g = Graphics.FromImage(bmpDest))                {                    g.DrawImage(source, new Rectangle(0, 0,                            source.Width, source.Height), 0, 0,                        source.Width, source.Height, GraphicsUnit.Pixel,                        attrImage);                }            }            return bmpDest;                   }                        public static Font AdjustSize(this Font font, Graphics graphics, string text, int width)        {            Font result = null;            for (int size = (int)font.Size; size > 0; size--)            {                result = new Font(font.Name, size, font.Style);                SizeF adjustedSizeNew = graphics.MeasureString(text, result);                if (width > Convert.ToInt32(adjustedSizeNew.Width))                    return result;            }            return result;                    }        public static Bitmap WatermarkImage(this Bitmap image, String text, System.Windows.Media.Color color, int maxfontsize = 0)        {            return image.WatermarkImage(text, Color.FromArgb(color.A, color.R, color.G, color.B),maxfontsize);        }                public static Bitmap WatermarkImage(this Bitmap image, String text, Color color, int maxfontsize = 0)        {            int w = image.Width;            int h = image.Height;            Bitmap result = new System.Drawing.Bitmap(w, h);            Graphics graphics = System.Drawing.Graphics.FromImage((System.Drawing.Image)result);            graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;            graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;            graphics.Clear(System.Drawing.Color.Transparent);            graphics.DrawImage(image, 0, 0, w, h);                        Font drawFont = new System.Drawing.Font("Arial", 96).AdjustSize(graphics,text,(int)(image.Width * 0.9F));            if ((maxfontsize > 0) && (drawFont.Size > maxfontsize))                drawFont = new System.Drawing.Font("Arial", maxfontsize);                        SolidBrush drawBrush = new System.Drawing.SolidBrush(color);                        StringFormat stringFormat = new StringFormat();            stringFormat.Alignment = StringAlignment.Center;            stringFormat.LineAlignment = StringAlignment.Center;                        graphics.DrawString(text, drawFont, drawBrush, new Rectangle(0,0,w,h), stringFormat);                        graphics.Dispose();            return result;        }                private static System.Windows.Media.Color AdjustColor(System.Windows.Media.Color color, Action<HSL> action)        {            var hsl = ColorHelper.ColorConverter.RgbToHsl(new RGB(color.R,color.G,color.B));            action(hsl);            var rgb = ColorHelper.ColorConverter.HslToRgb(hsl);            return System.Windows.Media.Color.FromArgb(color.A, rgb.R, rgb.G, rgb.B);                   }        private static int AdjustPercentage(int original, int percentage)        {            int percent = Math.Min(100, Math.Max(-100, percentage));            int newvalue = (percent < 0)                ? (byte)((percent * original) / 100)                : (byte)((percent * (100 - original)) / 100);            return original + newvalue;        }                public static System.Windows.Media.Color AdjustHue(this System.Windows.Media.Color color, int degrees) =>             AdjustColor(color, (hsl => hsl.H += degrees));        public static System.Windows.Media.Color AdjustSaturation(this System.Windows.Media.Color color, int percentage) =>            AdjustColor(color, (hsl =>            {                hsl.S = (byte)AdjustPercentage(hsl.S, percentage);            }));                        public static System.Windows.Media.Color SetSaturation(this System.Windows.Media.Color color, int percentage) =>            AdjustColor(color, (hsl => hsl.S = (byte)percentage));                public static System.Windows.Media.Color AdjustLightness(this System.Windows.Media.Color color, int percentage) =>            AdjustColor(color, (hsl =>            {                hsl.L = (byte)AdjustPercentage(hsl.L, percentage);            }));          public static System.Windows.Media.Color SetLightness(this System.Windows.Media.Color color, int percentage) =>             AdjustColor(color, (hsl => hsl.L = (byte)percentage));        public static System.Windows.Media.Color SetAlpha(this System.Windows.Media.Color color, byte alpha) =>            System.Windows.Media.Color.FromArgb(alpha, color.R, color.G, color.B);        public static HSL ToHSL(this System.Windows.Media.Color color)        {            return ColorHelper.ColorConverter.RgbToHsl(new RGB(color.R, color.G, color.B));        }        public static System.Windows.Media.Color ToColor(this HSL hsl)        {            var rgb = ColorHelper.ColorConverter.HslToRgb(hsl);            return System.Windows.Media.Color.FromRgb(rgb.R, rgb.G, rgb.B);        }                public static HSL ToHSL(this System.Drawing.Color color)        {            return ColorHelper.ColorConverter.RgbToHsl(new RGB(color.R, color.G, color.B));        }        public static System.Windows.Media.Color GetForegroundColor(this System.Windows.Media.Color c, int threshold = 130)        {            var perceivedbrightness = (int)Math.Sqrt(                    c.R * c.R * .299 +                    c.G * c.G * .587 +                    c.B * c.B * .114);            return perceivedbrightness >= threshold ? Colors.Black : Colors.White;        }                public static uint ToUint(this System.Drawing.Color color) => (uint)((color.A << 24) | (color.R << 16) | (color.G << 8)  | (color.B << 0));        public static uint ToUint(this System.Windows.Media.Color color) => (uint)((color.A << 24) | (color.R << 16) | (color.G << 8)  | (color.B << 0));        public enum ImageEncoding        {            JPEG        }        public static ImageCodecInfo? GetEncoder(ImageFormat format)        {            ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();            foreach (ImageCodecInfo codec in codecs)            {                if (codec.FormatID == format.Guid)                {                    return codec;                }            }            return null;        }        public static byte[] GetPDFThumbnail(byte[] pdfData, int width, int height)        {            PdfLoadedDocument loadeddoc = new PdfLoadedDocument(pdfData);            Bitmap image = loadeddoc.ExportAsImage(0, new SizeF(width, height), true);            MemoryStream stream = new MemoryStream();            image.Save(stream, ImageFormat.Jpeg);            return stream.ToArray();        }        public static List<byte[]> RenderPDFToImages(byte[] pdfData, ImageEncoding encoding = ImageEncoding.JPEG)        {            var rendered = new List<byte[]>();            PdfLoadedDocument loadeddoc = new PdfLoadedDocument(pdfData);            loadeddoc.FlattenAnnotations();            Bitmap[] images = loadeddoc.ExportAsImage(0, loadeddoc.Pages.Count - 1);            var jpgEncoder = GetEncoder(ImageFormat.Jpeg)!;            var quality = Encoder.Quality;            var encodeParams = new EncoderParameters(1);            encodeParams.Param[0] = new EncoderParameter(quality, 100L);            if (images != null)                foreach (var image in images)                {                    using (var data = new MemoryStream())                    {                        image.Save(data, jpgEncoder, encodeParams);                        rendered.Add(data.ToArray());                    }                }            return rendered;        }        public static List<byte[]> RenderTextFileToImages(string textData)        {            var pdfDocument = new PdfDocument();            var page = pdfDocument.Pages.Add();            var font = new PdfStandardFont(PdfFontFamily.Courier, 14);            var textElement = new PdfTextElement(textData, font);            var layoutFormat = new PdfLayoutFormat            {                Layout = PdfLayoutType.Paginate,                Break = PdfLayoutBreakType.FitPage            };            textElement.Draw(page, new RectangleF(0, 0, page.GetClientSize().Width, page.GetClientSize().Height), layoutFormat);            using var docStream = new MemoryStream();            pdfDocument.Save(docStream);            var loadeddoc = new PdfLoadedDocument(docStream.ToArray());            Bitmap[] bmpImages = loadeddoc.ExportAsImage(0, loadeddoc.Pages.Count - 1);            var jpgEncoder = GetEncoder(ImageFormat.Jpeg)!;            var quality = Encoder.Quality;            var encodeParams = new EncoderParameters(1);            encodeParams.Param[0] = new EncoderParameter(quality, 100L);            var images = new List<byte[]>();            if (bmpImages != null)                foreach (var image in bmpImages)                {                    using var data = new MemoryStream();                    image.Save(data, jpgEncoder, encodeParams);                    images.Add(data.ToArray());                }            return images;        }        public static ContentControl CreatePreviewWindowButtonContent(string caption, Bitmap bitmap)        {            Frame frame = new Frame();            frame.Padding = new Thickness(0);            frame.Margin = new Thickness(10, 10, 10, 5);            Grid grid = new Grid();            grid.Margin = new Thickness(0);            grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) });            grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Auto) });            var img = new System.Windows.Controls.Image            {                Source = bitmap.AsBitmapImage(),                Height = 32.0F,                Width = 32.0F,                Margin = new Thickness(10)            };            img.SetValue(Grid.RowProperty, 0);            img.Margin = new Thickness(0);            grid.Children.Add(img);            var txt = new System.Windows.Controls.TextBox();            txt.IsEnabled = false;            txt.Text = caption;            txt.BorderThickness = new Thickness(0);            txt.TextWrapping = TextWrapping.WrapWithOverflow;            txt.MaxWidth = 90;            txt.HorizontalContentAlignment = System.Windows.HorizontalAlignment.Center;            txt.SetValue(Grid.RowProperty, 1);            grid.Children.Add(txt);            frame.Content = grid;            return frame;        }        public static String AsExtension(this ImageFormat format)        {            if (format.Equals(ImageFormat.Bmp) || format.Equals(ImageFormat.MemoryBmp))                return "bmp";            if (format.Equals(ImageFormat.Emf))                return "emf";            if (format.Equals(ImageFormat.Wmf))                return "wmf";            if (format.Equals(ImageFormat.Gif))                return "gif";            if (format.Equals(ImageFormat.Jpeg))                return "jpeg";            if (format.Equals(ImageFormat.Png))                return "png";            if (format.Equals(ImageFormat.Tiff))                return "tiff";            if (format.Equals(ImageFormat.Exif))                return "exif";            if (format.Equals(ImageFormat.Icon))                return "ico";            return "";        }    }}
 |