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; using System.Diagnostics.CodeAnalysis; using System.Runtime; using System.Text; using Encoder = System.Drawing.Imaging.Encoder; 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 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) { if (data?.Any() != true) return null; var imageSource = new BitmapImage(); using (var ms = new MemoryStream(data)) { imageSource.BeginInit(); imageSource.StreamSource = ms; imageSource.CacheOption = BitmapCacheOption.OnLoad; imageSource.EndInit(); } return imageSource; } 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; } } /// /// Load an image from image data; this will return if is or empty. /// /// /// public static BitmapImage? LoadImage(byte[]? imageData) { if(imageData is null || imageData.Length == 0) { return null; } var result = new BitmapImage(); result.LoadImage(imageData); return result; } private static void LoadImage(this BitmapImage image, byte[] imageData) { 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 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(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(); 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; } /// /// Creates color with corrected brightness. /// /// Color to correct. /// /// The brightness correction factor. Must be between -1 and 1. /// Negative values produce darker colors. /// /// /// Corrected structure. /// 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); } public static bool TryGetImageType(byte[] imageData, [NotNullWhen(true)] out ImageFormat? format) { 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) { format = signatureEntry.Key; return true; } } format = null; return false; } /// /// 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. /// /// Byte array of the image data /// ImageFormat corresponding to the image file format /// Thrown if the image type can't be determined public static ImageFormat GetImageType(byte[] imageData) { if(TryGetImageType(imageData, out var format)) { return format; } 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 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[] BitmapToPdf(Bitmap bitmap) { byte[]? _result = null; using (var _stream = new MemoryStream()) { bitmap.Save(_stream, ImageFormat.Png); _result = BitmapToPdf(_stream); } return _result; } public static byte[] BitmapToPdf(byte[] bitmap) { byte[] _result = null; using (var _stream = new MemoryStream(bitmap)) _result = BitmapToPdf(_stream); return _result; } public static byte[] BitmapToPdf(Stream stream) { byte[]? _result = null; PdfDocument _doc = new PdfDocument(); PdfPage _page = _doc.Pages.Add(); PdfGraphics _graphics = _page.Graphics; stream.Position = 0; PdfBitmap _image = new PdfBitmap(stream); _graphics.DrawImage(_image, 0, 0); using (var _out = new MemoryStream()) { _doc.Save(_out); _out.Position = 0; _doc.Close(true); _result = _out.ToArray(); } return _result; } public static bool IsPdf(byte[] data) { var pdfBytes = Encoding.ASCII.GetBytes("%PDF-"); return data.Take(pdfBytes.Length).SequenceEqual(pdfBytes); } 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 byte[] PDFToBitmap(byte[] pdfData, int page) { PdfLoadedDocument loadeddoc = new PdfLoadedDocument(pdfData); Bitmap image = loadeddoc.ExportAsImage(page, new ImageExportSettings() { KeepAspectRatio = true }); MemoryStream stream = new MemoryStream(); image.Save(stream, ImageFormat.Jpeg); return stream.ToArray(); } [System.Runtime.InteropServices.DllImport("gdi32.dll")] public static extern bool DeleteObject(IntPtr hObject); public static List RenderPDFToImageSources(byte[] pdfData, ImageEncoding encoding = ImageEncoding.JPEG) { using var profiler = new Profiler(true); var rendered = new List(); var loadeddoc = new PdfLoadedDocument(pdfData); loadeddoc.FlattenAnnotations(); var images = loadeddoc.ExportAsImage(0, loadeddoc.Pages.Count - 1); if (images != null) foreach (var image in images) { var hBitmap = image.GetHbitmap(); try { var source = (ImageSource)Imaging.CreateBitmapSourceFromHBitmap( hBitmap, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); source.Freeze(); rendered.Add(source); } finally { DeleteObject(hBitmap); } } return rendered; } public static List RenderPDFToImageBytes(byte[] pdfData, ImageEncoding encoding = ImageEncoding.JPEG) { var rendered = new List(); 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 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(); 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 ""; } public static bool IsEqual(this BitmapImage? image1, BitmapImage? image2) { if (image1 == null || image2 == null) return false; return image1.ToBytes().SequenceEqual(image2.ToBytes()); } public static byte[] ToBytes(this BitmapImage image) { byte[] data = new byte[] { }; if (image != null) { try { var encoder = new BmpBitmapEncoder(); encoder.Frames.Add(BitmapFrame.Create(image)); using (MemoryStream ms = new MemoryStream()) { encoder.Save(ms); data = ms.ToArray(); } return data; } catch (Exception ex) { } } return data; } } }