// Spludlow Software // Copyright © Samuel P. Ludlow 2020 All Rights Reserved // Distributed under the terms of the GNU General Public License version 3 // Distributed WITHOUT ANY WARRANTY; without implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE // https://www.spludlow.co.uk/LICENCE.TXT // The Spludlow logo is a registered trademark of Samuel P. Ludlow and may not be used without permission // v1.14 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.IO; using System.Drawing; using System.Drawing.Imaging; using System.Drawing.Drawing2D; namespace Spludlow.Drawing { public class Bitmaps { private static ImageCodecInfo JpegCodecInfo = null; static Bitmaps() { foreach (ImageCodecInfo codec in ImageCodecInfo.GetImageDecoders()) { if (codec.FormatID == ImageFormat.Jpeg.Guid) JpegCodecInfo = codec; } if (JpegCodecInfo == null) throw new ApplicationException("Bitmaps; Can not find Jpeg Encoder"); } public static void ConfigureGraphicsPixel(Graphics graphics) { graphics.PageUnit = GraphicsUnit.Pixel; graphics.SmoothingMode = SmoothingMode.HighQuality; graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; } public static void SetPalette(Bitmap indexBitmap) { int paletteSize = 256; Color[] paletteColours = new Color[paletteSize]; for (int index = 0; index < paletteSize; ++index) paletteColours[index] = Color.FromArgb(index, index, index); SetPalette(indexBitmap, paletteColours); } public static void SetPalette(Bitmap indexBitmap, Color[] paletteColours) { ColorPalette palette = indexBitmap.Palette; for (int index = 0; index < paletteColours.Length; ++index) palette.Entries[index] = paletteColours[index]; indexBitmap.Palette = palette; } public static void SetPalette(Bitmap indexBitmap, byte[] paletteData) { int paletteSize = 256; ColorPalette palette = indexBitmap.Palette; for (int index = 0; index < paletteSize; ++index) { int offset = index * 3; Color colour = Color.FromArgb(paletteData[offset], paletteData[offset + 1], paletteData[offset + 2]); palette.Entries[index] = colour; } indexBitmap.Palette = palette; } public static void WriteBitmapData(Bitmap bitmap, byte[] data, PixelFormat pixelFormat) { BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.WriteOnly, pixelFormat); System.Runtime.InteropServices.Marshal.Copy(data, 0, bitmapData.Scan0, data.Length); bitmap.UnlockBits(bitmapData); } public static byte[] ReadBitmapData(Bitmap bitmap, PixelFormat pixelFormat) { BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly, pixelFormat); byte[] data = new byte[bitmapData.Stride * bitmapData.Height]; System.Runtime.InteropServices.Marshal.Copy(bitmapData.Scan0, data, 0, data.Length); bitmap.UnlockBits(bitmapData); return data; } public static void QualitySaveJpeg(Bitmap bitmap, string filename, int qualityPercent) { EncoderParameters myEncoderParameters = new EncoderParameters(1); myEncoderParameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, (long)qualityPercent); // level of 0 corresponds to the greatest compression, and a quality level of 100 corresponds to the least compression bitmap.Save(filename, JpegCodecInfo, myEncoderParameters); } public static Size Resize(string sourceFilename, Size size, string targetFilename, ImageFormat imageFormat, PixelFormat pixelFormat, int dpi) { using (Image image = Image.FromFile(sourceFilename)) { return Resize(image, size, targetFilename, imageFormat, pixelFormat, dpi); } } public static Size Resize(Image image, Size size, string filename, ImageFormat imageFormat, PixelFormat pixelFormat, int dpi) { using (Bitmap bitmap = Resize(image, size, pixelFormat, dpi)) { if (imageFormat == ImageFormat.Jpeg) QualitySaveJpeg(bitmap, filename, 100); else bitmap.Save(filename, imageFormat); return new Size(bitmap.Width, bitmap.Height); } } public static Bitmap Resize(Image image, Size size, PixelFormat pixelFormat, int dpi) { float newWidth = 0; float newHeight = 0; // Fit Rectangle if (size.Width != 0 && size.Height != 0) { float xScale = (float)image.Width / (float)size.Width; float yScale = (float)image.Height / (float)size.Height; float aspect = xScale / yScale; if (aspect < 1) size.Width = 0; else size.Height = 0; } // Fixed Width if (size.Width != 0 && size.Height == 0) { newWidth = size.Width; newHeight = (float)image.Height * (newWidth / (float)image.Width); } // Fixed Height if (size.Width == 0 && size.Height != 0) { newHeight = size.Height; newWidth = (float)image.Width * (newHeight / (float)image.Height); } // Keep Size if (size.Width == 0 && size.Height == 0) { newWidth = image.Width; newHeight = image.Height; } int width = (int)newWidth; int height = (int)newHeight; if (width <= 0 || height <= 0) throw new ApplicationException("ImageSize.Resize, Bad new Size:\t" + width + " x " + height); Bitmap bitmap = new Bitmap(width, height, pixelFormat); bitmap.SetResolution(dpi, dpi); using (Graphics graphics = Graphics.FromImage(bitmap)) { ConfigureGraphicsPixel(graphics); graphics.DrawImage(image, new Rectangle(0, 0, width, height)); } return bitmap; } public static Size Dimensions(string filename) { return Dimensions(File.ReadAllBytes(filename)); } public static Size Dimensions(byte[] data) { using (MemoryStream stream = new MemoryStream(data)) { using (Bitmap bitmap = new Bitmap(stream)) return new Size(bitmap.Width, bitmap.Height); } } public static SizeF GetDpi(string filename) { return GetDpi(File.ReadAllBytes(filename)); } public static SizeF GetDpi(byte[] data) { using (MemoryStream stream = new MemoryStream(data)) { using (Bitmap bitmap = new Bitmap(stream)) return new SizeF(bitmap.HorizontalResolution, bitmap.VerticalResolution); } } public static byte[] TextBitmap(string text, string pageSize, int dpi) { float boarder = 5.0F; using (Spludlow.TempDirectory tempDir = new TempDirectory()) { Spludlow.Printing.PrintDoc printDoc = new Printing.PrintDoc(pageSize, false); printDoc.TextBox(text, "Arial, 9", boarder, boarder, printDoc.Width - (boarder * 2), printDoc.Height - (boarder * 2)); string printData = printDoc.Save(); string filename = tempDir.Path + @"\bitmap.png"; Spludlow.Printing.Printer.Print(printData, "bitmap", filename + ", " + dpi, true); return File.ReadAllBytes(filename); } } public static bool ValidFile(string filename) { try { using (Image image = Image.FromFile(filename)) { if (image.Width > 0 && image.Height > 0) return true; } } catch (Exception ee) { Spludlow.Log.Warning("Bitmaps, ValidFile: " + filename, ee); } return false; } public static void Crop(string sourceFilename, string targetFilename, int x, int y, int width, int height, int dpi) { using (Image image = Image.FromFile(sourceFilename)) { using (Bitmap bitmap = new Bitmap(width, height, image.PixelFormat)) { bitmap.SetResolution(dpi, dpi); using (Graphics graphics = Graphics.FromImage(bitmap)) { Spludlow.Drawing.Bitmaps.ConfigureGraphicsPixel(graphics); graphics.DrawImageUnscaled(image, -x, -y); } bitmap.Save(targetFilename, image.RawFormat); } } } } }