using System; using System.Drawing; using System.IO; using System.Drawing.Imaging; using System.Runtime.InteropServices; using System.Drawing.Drawing2D; using System.Security.Permissions; namespace MarketData.CNNProcessing { public class ImageHelper : IDisposable { private Bitmap bitmap = null; private Graphics graphics=null; private PointMapping pointMapping; private int width; private int height; public ImageHelper() { } public void Dispose() { if(null!=bitmap) { bitmap.Dispose(); bitmap=null; } if(null!=graphics) { graphics.Dispose(); graphics=null; } } public bool LoadImage(string pathFileName) { Stream bitmapStream = null; try { bitmapStream = File.Open(pathFileName,FileMode.Open); Image image = Image.FromStream(bitmapStream); bitmap=new Bitmap(image); width=bitmap.Width; height=bitmap.Height; return true; } catch(Exception) { return false; } finally { if(null!=bitmapStream) { bitmapStream.Close(); bitmapStream.Dispose(); bitmapStream.Dispose(); } } } /// /// Resize image to given width maintaining aspect ration for height. /// If aspect ration is used for CNN then you will need to introduce padding. For instance 640,640 image and then paste the aspect /// mainained image onto that. The CNN will then have to learn that black means nothing. Resizing is the recommended way to go. /// public bool Resize(int newWidth) { double aspectRatio=(double)bitmap.Width/(double)bitmap.Height; int newHeight=(int)(((double)newWidth)/aspectRatio); if(0!=newHeight%2)newHeight++; return Resize(newWidth,newHeight); } /// /// Resize image to given width and height. The documenation on CNN's indicates that resizing will work better than maintaining apsect /// ration with padding /// public bool Resize(int newWidth, int newHeight) { Graphics graphics = null; ImageAttributes imageAttributes = null; try { Validate(); Rectangle destRect=new Rectangle(0,0,newWidth,newHeight); Bitmap destBitmap = new Bitmap(newWidth,newHeight); destBitmap.SetResolution(bitmap.HorizontalResolution,bitmap.VerticalResolution); graphics = Graphics.FromImage(destBitmap); graphics.CompositingMode = CompositingMode.SourceCopy; graphics.CompositingQuality = CompositingQuality.HighQuality; graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; graphics.SmoothingMode = SmoothingMode.HighQuality; graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; imageAttributes = new ImageAttributes(); imageAttributes.SetWrapMode(WrapMode.TileFlipXY); graphics.DrawImage(bitmap, destRect, 0,0, bitmap.Width, bitmap.Height, GraphicsUnit.Pixel, imageAttributes); bitmap.Dispose(); bitmap=destBitmap; imageAttributes.Dispose(); graphics.Dispose(); return true; } catch(Exception) { return false; } finally { if(null!=graphics) { graphics.Dispose(); graphics=null; } if(null!=imageAttributes) { imageAttributes.Dispose(); imageAttributes=null; } } } /// /// Resize the image to the specified width and height. /// /// The image to resize. /// The width to resize to. /// The height to resize to. /// The resized image. //public static Bitmap ResizeImage(Image image, int width, int height) //{ // var destRect = new Rectangle(0, 0, width, height); // var destImage = new Bitmap(width, height); // destImage.SetResolution(image.HorizontalResolution, image.VerticalResolution); // using (var graphics = Graphics.FromImage(destImage)) // { // graphics.CompositingMode = CompositingMode.SourceCopy; // graphics.CompositingQuality = CompositingQuality.HighQuality; // graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; // graphics.SmoothingMode = SmoothingMode.HighQuality; // graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; // using (var wrapMode = new ImageAttributes()) // { // wrapMode.SetWrapMode(WrapMode.TileFlipXY); // graphics.DrawImage(image, destRect, 0, 0, image.Width,image.Height, GraphicsUnit.Pixel, wrapMode); // } // } // return destImage; //} public void CreateImage(int width, int height,PointMapping pointMapping) { this.width=width; this.height=height; this.pointMapping=pointMapping; bitmap=new Bitmap(width,height,System.Drawing.Imaging.PixelFormat.Format24bppRgb); Validate(); graphics=Graphics.FromImage(bitmap); } public Stream SaveBlackAndWhiteJPG() { Validate(); Bitmap bwBitmap=ToBlackAndWhite(bitmap); Stream memoryStream=new MemoryStream(); BitmapExtensions.SaveJPG100(bwBitmap,memoryStream); memoryStream.Position=0; bwBitmap.Dispose(); return memoryStream; } public void SaveGrayScaleJPG(String pathFileName) { Validate(); Bitmap bwBitmap=ToBlackAndWhite(bitmap); Save(pathFileName,bwBitmap); bwBitmap.Dispose(); } public void SaveBlackAndWhiteJPG(String pathFileName) { Validate(); Bitmap bwBitmap=ToBlackAndWhite(bitmap); Save(pathFileName,bwBitmap); bwBitmap.Dispose(); } public void Save(String pathFileName) { Save(pathFileName,null); } private void Save(String pathFileName,Bitmap altBitmap=null) { Validate(); if(null==altBitmap)BitmapExtensions.SaveJPG100(bitmap,pathFileName); else BitmapExtensions.SaveJPG100(altBitmap,pathFileName); } // Convert to 8 bits per pixel black and white private Bitmap ToBlackAndWhite(Bitmap bmp) { var result = new Bitmap(bmp.Width, bmp.Height, System.Drawing.Imaging.PixelFormat.Format8bppIndexed); BitmapData data = result.LockBits(new Rectangle(0, 0, result.Width, result.Height), ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed); byte[] bytes = new byte[data.Height * data.Stride]; Marshal.Copy(data.Scan0, bytes, 0, bytes.Length); for (int y = 0; y < bmp.Height; y++) { for (int x = 0; x < bmp.Width; x++) { Color color = bmp.GetPixel(x, y); byte rgb = (byte)((color.R + color.G + color.B) / 3); if(rgb>0)rgb=255; bytes[y * data.Stride + x] = rgb; } } Marshal.Copy(bytes, 0, data.Scan0, bytes.Length); result.UnlockBits(data); return result; } // Convert to 8 bits per pixel gray scale private Bitmap ToGrayScale(Bitmap bmp) { var result = new Bitmap(bmp.Width, bmp.Height, System.Drawing.Imaging.PixelFormat.Format8bppIndexed); BitmapData data = result.LockBits(new Rectangle(0, 0, result.Width, result.Height), ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed); byte[] bytes = new byte[data.Height * data.Stride]; Marshal.Copy(data.Scan0, bytes, 0, bytes.Length); for (int y = 0; y < bmp.Height; y++) { for (int x = 0; x < bmp.Width; x++) { Color color = bmp.GetPixel(x, y); byte rgb = (byte)((color.R + color.G + color.B) / 3); bytes[y * data.Stride + x] = rgb; } } Marshal.Copy(bytes, 0, data.Scan0, bytes.Length); result.UnlockBits(data); return result; } public Color GetPixel(int x,int y) { return bitmap.GetPixel(x,y); } public void SetPixel(int x, int y,Color color) { bitmap.SetPixel(x,y,color); } public Point TranslatePoint(Point point) { return pointMapping.TranslatePoint(point); } public void Validate() { if(null==bitmap)throw new InvalidDataException("The image has not been initialized"); } public int Width { get{return width;} } public int Height { get{return height;} } public void Fill(Brush brush) { Validate(); Region region=new Region(new Rectangle(0,0,bitmap.Width,bitmap.Height)); graphics.FillRegion(brush,region); } public void DrawPoint(Pen pen,Point drawPoint) { Validate(); Point txPoint=pointMapping.MapPoint(drawPoint); graphics.DrawImage(bitmap,txPoint); } public void AddNoise(Color color,double percentDecimal) { Random random=new Random(); int amount=(int)(percentDecimal*(Width*Height)); for(int index=0;index