using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Drawing; using System.Drawing.Imaging; using System.IO; using System.Drawing.Drawing2D; using System.Runtime.InteropServices; using System.Diagnostics; namespace Sheng.Winform.Controls.Drawing { public static class DrawingTool { #region GetImage public static Image GetImage(string filePath) { return GetImage(filePath, true); } public static Image GetImage(string filePath, bool memberCopy) { return GetImage(filePath, memberCopy, false); } /// /// 从文件中获取Image对象 /// 这个函数的主要功能是处理一些ico文件 /// 一些ico文件的格式可能比较新,直接Image.FormFile,会报内存不足的异常 /// /// /// 是否将文件读入内存操作,如果为false,将直接返回Image.FromFile,在此情况下, /// 必须手动释放Image对象,否则文件将一直处于占用状态,如果为true,则在内存中拷贝副本 /// public static Image GetImage(string filePath,bool memberCopy, bool markNotFind) { FileInfo file = new FileInfo(filePath); Image image = null; if (!file.Exists) { if (markNotFind) { image = new Bitmap(16, 16); Mark.FileNotFind(image); return image; } else { return null; } } switch (file.Extension.ToLower()) { case ".ico": try { Icon icon = new Icon(file.FullName); image = icon.ToBitmap(); } catch { image = new Bitmap(16, 16); Mark.FileCanNotRead(image); } break; default: if (memberCopy) { Image imgTemp = Image.FromFile(file.FullName); image = new System.Drawing.Bitmap(imgTemp); imgTemp.Dispose(); } else { // Image.FromFile(file.FullName);会使文件一直处于被占用状态,必须手动释放 image = Image.FromFile(file.FullName); } break; } return image; } #endregion #region ImageToIcon /// /// 将图像转为Icon对象,使用png格式 /// /// /// public static Icon ImageToIcon(Image image) { return ImageToIcon(image, ImageFormat.Png); } /// /// 将图像转为Icon对象 /// /// /// /// public static Icon ImageToIcon(Image image, ImageFormat format) { System.IO.Stream ms = new MemoryStream(); image.Save(ms, format); Icon icon = Icon.FromHandle(new Bitmap(ms).GetHicon()); ms.Close(); return icon; } #endregion #region GetScaleImage /// /// 返回适应指定容器大小的图像 /// 如果图像的尺寸(长或宽)超出了容器范围,将按比例获取图像的缩略图返回,否则直接返回图像 /// 此方法最终调用 Image.GetThumbnailImage /// 但是注意,在指定的容器尺寸过小时,返回的Image尺寸不可知,是在为了显示16x16的小缩略图是发现了此问题 /// 使用 GetScaleImage /// /// /// /// /// public static Image GetAutoScaleThumbnailImage(Image image, int containerWidth, int containerHeight) { if (image.Size.Width > containerWidth || image.Size.Height > containerHeight) { double height = containerHeight; double width = containerWidth; double new_height; double new_width; double scale; new_height = height; new_width = width; if ((image.Width > width) || (image.Height > height)) { if (image.Width > width) { scale = image.Width / width; new_width = image.Width / scale; new_height = image.Height / scale; } else { scale = image.Height / height; new_width = image.Width / scale; new_height = image.Height / scale; } } return image.GetThumbnailImage(Convert.ToInt32(new_width), Convert.ToInt32(new_height), thumbnailCallback, IntPtr.Zero); } else { return image; } } static Image.GetThumbnailImageAbort thumbnailCallback = new Image.GetThumbnailImageAbort(ThumbnailCallback); private static bool ThumbnailCallback() { return false; } /// /// 返回适应指定容器大小的图像 /// 在需要的情况下,此方法创建一个新对象,进行绘制 /// /// /// /// /// public static Image GetScaleImage(Image image, Size size) { if (image.Size.Width > size.Width || image.Size.Height > size.Height) { double width = size.Width; double height = size.Height; double new_width; double new_height; double scale; new_height = height; new_width = width; if ((image.Width > width) || (image.Height > height)) { if (image.Width > width) { scale = image.Width / width; new_width = image.Width / scale; new_height = image.Height / scale; } else { scale = image.Height / height; new_width = image.Width / scale; new_height = image.Height / scale; } } Bitmap bitmap = new Bitmap(Convert.ToInt32(new_width), Convert.ToInt32(new_height)); Graphics g = Graphics.FromImage(bitmap); g.DrawImage(image, 0, 0, bitmap.Width, bitmap.Height); return bitmap; } else { return image; } } /// /// 返回适应指定容器大小的图像 /// 在需要的情况下,此方法创建一个新对象,进行绘制 /// /// /// /// /// public static Image GetScaleImage(Image image, int containerWidth, int containerHeight) { if (containerWidth == null || containerHeight == null) { Debug.Assert(false, "containerWidth 或 containerHeight为空"); throw new ArgumentNullException(); } return GetScaleImage(image, new Size(containerWidth, containerHeight)); } #endregion /// /// Gets the bounding rectangle of an image required to fit /// in to the given rectangle keeping the image aspect ratio. /// /// The source image. /// The rectangle to fit in to. /// Horizontal image aligment in percent. /// Vertical image aligment in percent. /// New image size. public static Rectangle GetSizedImageBounds(Image image, Rectangle fit, float hAlign, float vAlign) { if (hAlign < 0 || hAlign > 100.0f) throw new ArgumentException("hAlign must be between 0.0 and 100.0 (inclusive).", "hAlign"); if (vAlign < 0 || vAlign > 100.0f) throw new ArgumentException("vAlign must be between 0.0 and 100.0 (inclusive).", "vAlign"); Size scaled = GetSizedImageBounds(image, fit.Size); int x = fit.Left + (int)(hAlign / 100.0f * (float)(fit.Width - scaled.Width)); int y = fit.Top + (int)(vAlign / 100.0f * (float)(fit.Height - scaled.Height)); return new Rectangle(x, y, scaled.Width, scaled.Height); } /// /// Gets the bounding rectangle of an image required to fit /// in to the given rectangle keeping the image aspect ratio. /// The image will be centered in the fit box. /// /// The source image. /// The rectangle to fit in to. /// New image size. public static Rectangle GetSizedImageBounds(Image image, Rectangle fit) { return GetSizedImageBounds(image, fit, 50.0f, 50.0f); } /// /// Gets the scaled size of an image required to fit /// in to the given size keeping the image aspect ratio. /// /// The source image. /// The size to fit in to. /// New image size. public static Size GetSizedImageBounds(Image image, Size fit) { float f = System.Math.Max((float)image.Width / (float)fit.Width, (float)image.Height / (float)fit.Height); if (f < 1.0f) f = 1.0f; // Do not upsize small images int width = (int)System.Math.Round((float)image.Width / f); int height = (int)System.Math.Round((float)image.Height / f); return new Size(width, height); } #region RoundedRect /// /// 获取一个圆角矩形 /// /// /// /// 角度 /// public static GraphicsPath RoundedRect(int width, int height, int radius) { RectangleF baseRect = new RectangleF(0, 0, width, height); return RoundedRect(baseRect, radius); } /// /// 获取一个圆角矩形 /// /// /// /// 角度 /// public static GraphicsPath RoundedRect(RectangleF baseRect, int radius) { //RectangleF baseRect = new RectangleF(0, 0, width, height); float diameter = radius * 2.0f; SizeF sizeF = new SizeF(diameter, diameter); RectangleF arc = new RectangleF(baseRect.Location, sizeF); GraphicsPath path = new GraphicsPath(); // top left arc path.AddArc(arc, 180, 90); // top right arc arc.X = baseRect.Right - diameter; path.AddArc(arc, 270, 90); // bottom right arc arc.Y = baseRect.Bottom - diameter; path.AddArc(arc, 0, 90); // bottom left arc arc.X = baseRect.Left; path.AddArc(arc, 90, 90); path.CloseFigure(); return path; } #endregion #region GetArrowPath public static GraphicsPath GetArrowPath(PointF startPoint, PointF endPoint) { return GetArrowPath(startPoint, endPoint, 7); } public static GraphicsPath GetArrowPath(PointF startPoint, PointF endPoint, double arrowLength) { return GetArrowPath(startPoint, endPoint, arrowLength, 1); } /// /// 返回一个表示箭头的Path /// 如果开始坐标和结束坐标之间的距离大于箭头的大小,箭头向结束坐标对齐,顶着结束坐标 /// /// 开始坐标 /// 结束坐标(顶点,方向) /// 箭头的长短,大小 /// 箭头的粗细 /// public static GraphicsPath GetArrowPath(PointF startPoint, PointF endPoint, double arrowLength, double relativeValue) { //http://www.cnblogs.com/jasenkin/archive/2011/01/04/graphic_drawing_arrow_head_II.html double distance = Math.Abs(Math.Sqrt( (startPoint.X - endPoint.X) * (startPoint.X - endPoint.X) + (startPoint.Y - endPoint.Y) * (startPoint.Y - endPoint.Y))); if (distance == 0) { return new GraphicsPath(); } double xa = endPoint.X + arrowLength * ((startPoint.X - endPoint.X) + (startPoint.Y - endPoint.Y) / relativeValue) / distance; double ya = endPoint.Y + arrowLength * ((startPoint.Y - endPoint.Y) - (startPoint.X - endPoint.X) / relativeValue) / distance; double xb = endPoint.X + arrowLength * ((startPoint.X - endPoint.X) - (startPoint.Y - endPoint.Y) / relativeValue) / distance; double yb = endPoint.Y + arrowLength * ((startPoint.Y - endPoint.Y) + (startPoint.X - endPoint.X) / relativeValue) / distance; PointF[] polygonPoints = { new PointF(endPoint.X , endPoint.Y), new PointF( (float)xa , (float)ya), new PointF( (float)xb , (float)yb) }; GraphicsPath path = new GraphicsPath(); path.AddLines(polygonPoints); return path; } #endregion #region Mark /// /// 在指定的Image上绘制特定标记 /// public static class Mark { /// /// 文件不存在 /// /// [Obsolete("改用 FileNotFind(Size size)")] public static void FileNotFind(Image image) { if (image == null) { Debug.Assert(false, "image = null"); return; } Graphics g = Graphics.FromImage(image); g.DrawRectangle(Pens.Red, 0, 0, image.Width - 1, image.Height - 1); g.DrawLine(Pens.Red, 0, 0, image.Width, image.Height); g.DrawLine(Pens.Red, image.Width, 0, 0, image.Height); g.Dispose(); } /// /// 文件不存在 /// /// public static Image FileNotFind(Size size) { Image image = new Bitmap(size.Width, size.Height); Graphics g = Graphics.FromImage(image); g.Clear(Color.White); g.DrawRectangle(Pens.Red, 0, 0, image.Width - 1, image.Height - 1); g.DrawLine(Pens.Red, 0, 0, image.Width, image.Height); g.DrawLine(Pens.Red, image.Width, 0, 0, image.Height); g.Dispose(); return image; } /// /// 无法读取文件 /// /// [Obsolete("改用 FileCanNotRead(Size size)")] public static void FileCanNotRead(Image image) { if (image == null) { Debug.Assert(false, "image = null"); return; } Graphics g = Graphics.FromImage(image); g.DrawRectangle(Pens.Red, 0, 0, image.Width - 1, image.Height - 1); g.DrawLine(Pens.Red, 0, 0, image.Width, image.Height); g.DrawLine(Pens.Red, image.Width, 0, 0, image.Height); g.Dispose(); } public static Image FileCanNotRead(Size size) { Image image = new Bitmap(size.Width, size.Height); Graphics g = Graphics.FromImage(image); g.Clear(Color.White); g.DrawRectangle(Pens.Red, 0, 0, image.Width - 1, image.Height - 1); g.DrawLine(Pens.Red, 0, 0, image.Width, image.Height); g.DrawLine(Pens.Red, image.Width, 0, 0, image.Height); g.Dispose(); return image; } } #endregion } }