using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Data; using System.Linq; using System.Text; using System.Windows.Forms; using System.Drawing.Imaging; using System.Threading.Tasks; using System.Threading; using Eventech.DynPicture.Model; using System.Collections.Concurrent; namespace Eventech.DynPicture.WinFrmUI { /// /// 图片视图控件 /// 获取视图点 /// public partial class PictureEditBasic : UserControl { /// /// 构造函数 /// public PictureEditBasic() { InitializeComponent(); #region 防止闪烁 SetStyle(ControlStyles.AllPaintingInWmPaint, true); SetStyle(ControlStyles.DoubleBuffer, true); SetStyle(ControlStyles.UserPaint, true); #endregion this.MinimumSize = new Size(10, 10); _oldClientRectf = GetClientRectangleF(); this.AsyncLoadingImage = Properties.Resources.Loading; } #region 事件 /// /// 异步加载图片完成事件 /// /// 第一个返回值为bool型,判断异步操作是否成功 /// 如果异步操作失败,第二个参数为异常信息,否则为null public event Action LoadImageAsyncCompletedEvent; /// /// 点击图片后触发 /// /// 第一个参数为源图位置信息 /// 第二个参数为鼠标相关信息 public event Action ImageViewPointFClickEvent; #endregion #region 公开属性 /// /// 源图(赋值后不在对此图片做任何处理) /// [Browsable(true)] [Description("源图")] public virtual Image Image { get { return _img; } set { _img = value; this.DisplayImage = value; } } /// /// 源图 /// protected Image _img = null; /// /// 获取用于显示的图片的副本(此图片是根据Image进行处理过的图片) /// public virtual Image DisplayImage { get { if (_displayImage == null) return null; return _displayImage.CloneC(); } protected set { if (_displayImage != null) _displayImage.Dispose(); _displayImage = CreateOriginDisplayImage(value); this.Invalidate(); } } /// /// 创建原始显示图片 /// /// 源图 /// 初始化的显示图片 protected virtual Image CreateOriginDisplayImage(Image img) { if (img == null) return null; var cmg = img.CloneC(); _isAutoFit = true; _displayAngle = 0; CalcuAutoSize(cmg); return cmg; } /// /// 用于显示的图片 /// protected Image _displayImage = null; /// /// 当控件释放时是否释放Image /// [Browsable(true)] [Description("当控件释放时是否释放图片资源")] public bool IsDisposeImageWhenDisposed { get { return _isDisposeImageWhenDisposed; } set { _isDisposeImageWhenDisposed = value; } } private bool _isDisposeImageWhenDisposed = false; /// /// Image至DisplayImage的旋转角度(顺时针) /// protected int _displayAngle = 0; /// /// 无图片时用于显示的提示文本 /// [Browsable(true)] [Description("无图片时显示文字")] public string NullText { get { return _nullText; } set { _nullText = value; } } private string _nullText = "无图片"; #endregion #region 同步加载 /// /// 同步加载 /// /// public void LoadImageSync(string fileName) { if (System.IO.File.Exists(fileName)) this.Image = Image.FromFile(fileName); } #endregion #region 异步加载图片 private Task _load_async_task = null;//当前异步加载任务 private readonly ConcurrentDictionary _dict_load_async_task_cancel = new ConcurrentDictionary(); private object _locker_load_async_task = new object();//任务锁 /// /// 异步加载图片时用于显示的图片 /// [Browsable(true)] [Description("异步加载图片时的显示动画")] public virtual Image AsyncLoadingImage { set { if (_asyncLoadingImage != null) { if (_animateImage != null) _animateImage.Dispose(); else _asyncLoadingImage.Dispose(); } _asyncLoadingImage = null; _animateImage = null; if (value != null) { _asyncLoadingImage = (Image)value.Clone(); if (_asyncLoadingImage != null && ImageAnimator.CanAnimate(_asyncLoadingImage)) { _animateImage = new AnimateImage(_asyncLoadingImage); _animateImage.OnFrameChanged += delegate { this.Invalidate(); }; } else { _animateImage = null; } } } } /// /// 异步加载图片时的动态图 /// protected Image _asyncLoadingImage; /// /// 是否正在异步加载图片 /// protected bool _isAsyncLoading = false; /// /// 动态图片操作对象 /// protected AnimateImage _animateImage = null; /// /// 异步加载图片 /// /// 文件磁盘路径 /// public void LoadImageAsync(string fileName) { _isAsyncLoading = true; if (_animateImage != null) _animateImage.Play(); this.Invalidate(); var task = Task.Factory.StartNew(() => { return Image.FromFile(fileName); }); task.ContinueWith((tas) => { if (IsDisposed) return; while (!IsHandleCreated) { Thread.Sleep(10); } this.Invoke(new Action(() => { _isAsyncLoading = false; if (_animateImage != null) { _animateImage.Stop(); } this.Image = tas.Result; if (this.LoadImageAsyncCompletedEvent != null) { var flag = tas.IsFaulted ? false : true; var ex = tas.Exception == null ? null : tas.Exception.GetBaseException(); this.LoadImageAsyncCompletedEvent(flag, ex); } })); }); } /// /// 异步加载图片 /// /// 参数为返回图片路径的委托 public void LoadImageAsync(Func dele) { _isAsyncLoading = true; if (_animateImage != null) _animateImage.Play(); this.Invalidate(); var task = Task.Factory.StartNew(() => { return Image.FromFile(dele()); }); task.ContinueWith((tas) => { if (IsDisposed) return; while (!IsHandleCreated) { Thread.Sleep(10); } this.Invoke(new Action(() => { _isAsyncLoading = false; if (_animateImage != null) { _animateImage.Stop(); } this.Image = tas.Result; if (this.LoadImageAsyncCompletedEvent != null) { var flag = tas.IsFaulted ? false : true; var ex = tas.Exception == null ? null : tas.Exception.GetBaseException(); this.LoadImageAsyncCompletedEvent(flag, ex); } })); }); } /// /// 异步加载图片 /// /// 参数为返回图片的委托 public void LoadImageAsync(Func dele) { lock (_locker_load_async_task) { if (_load_async_task != null) { if (_isAsyncLoading) { _isAsyncLoading = false; if (_animateImage != null) { _animateImage.Stop(); } _dict_load_async_task_cancel.AddOrUpdate(_load_async_task.Id, true, (key, oldValue) => true); } } } _isAsyncLoading = true; if (_animateImage != null) _animateImage.Play(); this.Invalidate(); var task = Task.Factory.StartNew(() => { _dict_load_async_task_cancel.TryAdd(Task.CurrentId.Value, false); return dele(); }); lock (_locker_load_async_task) { _load_async_task = task; } task.ContinueWith((tas) => { bool cancel = false; if (IsDisposed) { _dict_load_async_task_cancel.TryRemove(tas.Id, out cancel); return; } while (!IsHandleCreated) { Thread.Sleep(10); } if (_dict_load_async_task_cancel.TryRemove(tas.Id, out cancel)) { if (cancel) return; this.Invoke(new Action(() => { _isAsyncLoading = false; if (_animateImage != null) { _animateImage.Stop(); } this.Image = tas.Result; if (this.LoadImageAsyncCompletedEvent != null) { var flag = tas.IsFaulted ? false : true; var ex = tas.Exception == null ? null : tas.Exception.GetBaseException(); this.LoadImageAsyncCompletedEvent(flag, ex); } })); } }); } /// /// 异步加载图片 /// /// 参数为返回图片的委托 //public void LoadImageAsync(Func loadImage_cb,Action finish_cb) //{ // _isAsyncLoading = true; // if (_animateImage != null) // _animateImage.Play(); // this.Invalidate(); // var task = Task.Factory.StartNew(() => // { // return loadImage_cb(); // }); // task.ContinueWith((tas) => // { // if (IsDisposed) // return; // while (!IsHandleCreated) // { // Thread.Sleep(10); // } // this.Invoke(new Action(() => // { // _isAsyncLoading = false; // if (_animateImage != null) // { // _animateImage.Stop(); // } // var img = tas.Result; // this.Image = img; // if (finish_cb != null && img != null) // { // finish_cb.Invoke(img); // } // if (this.LoadImageAsyncCompletedEvent != null) // { // var flag = tas.IsFaulted ? false : true; // var ex = tas.Exception == null ? null : tas.Exception.GetBaseException(); // this.LoadImageAsyncCompletedEvent(flag, ex); // } // })); // }); //} #endregion #region 边框 /// /// 边框颜色 /// [Browsable(true)] [Description("自定义边框颜色")] public Color CustomBorderColor { get { return _customBorderColor; } set { _customBorderColor = value; } } private Color _customBorderColor = Color.Black; /// /// 边框宽度 /// [Browsable(true)] [Description("自定义边框宽度")] public int CustomBorderWidth { get { return _customBorderWidth; } set { _customBorderWidth = value; } } private int _customBorderWidth = 1; /// /// 边框是否显示 /// [Browsable(true)] [Description("自定义边框可见性")] [DefaultValue(false)] public bool CustomBorderVisible { get { return _customBorderVisible; } set { _customBorderVisible = value; } } private bool _customBorderVisible = false; /// /// 绘制边框 /// protected virtual void DrawBorder(Graphics g) { if (this.CustomBorderVisible) { var x = this.CustomBorderWidth / 2f; var y = this.CustomBorderWidth / 2f; var width = this.Width - this.CustomBorderWidth; var height = this.Height - this.CustomBorderWidth; using (var pen = new Pen(this.CustomBorderColor, this.CustomBorderWidth)) { g.DrawRectangle(pen, x, y, width, height); } } } #endregion #region 鼠标左键按下拖动图片 /// /// 是否允许鼠标左键按下拖动图片 /// [Browsable(true)] [Description("是否允许鼠标左键按下拖动图片")] [DefaultValue(true)] public bool AllowMouseDownMoveImage { get { return _allowMouseDownMoveImage; } set { _allowMouseDownMoveImage = value; } } private bool _allowMouseDownMoveImage = true; //鼠标左键是否按下 private bool _mouseLeftDown = false; //鼠标左键移动点位置 private Point _mouseLeftMovePoint; /// /// 鼠标按下 /// /// protected override void OnMouseDown(MouseEventArgs e) { base.OnMouseDown(e); if (e.Button == MouseButtons.Left) { if (_displayImage != null) { if (this.AllowMouseDownMoveImage) { if (_desRectf.Contains(e.Location)) { _mouseLeftDown = true; _mouseLeftMovePoint = e.Location; } } } } } /// /// 鼠标移动 /// /// protected override void OnMouseMove(MouseEventArgs e) { base.OnMouseMove(e); if (_displayImage != null) { if (_desRectf.Contains(e.Location)) { this.Cursor = Cursors.Hand; if (_allowMouseDownMoveImage) { if (_mouseLeftDown) { MoveImage(e.Location); } } return; } } this.Cursor = Cursors.Default; } /// /// 鼠标弹起 /// /// protected override void OnMouseUp(MouseEventArgs e) { base.OnMouseUp(e); _mouseLeftDown = false; } #endregion #region 鼠标点击满足相关条件后触发 ImageViewPointFClickEvent 事件 /// /// 鼠标点击触发获取控件位置点对应源图片位置点事件 /// /// protected override void OnMouseClick(MouseEventArgs e) { base.OnMouseClick(e); if (_displayImage != null) { if (this.ImageViewPointFClickEvent != null) { if (_desRectf.Contains(e.Location)) { var dp = ViewPointToDisplay(e.Location); var sp = DisplayPointToSource(dp); this.ImageViewPointFClickEvent(sp, e); } } } } #endregion #region 相关参数 /// /// 源矩形 /// protected RectangleF _srcRectf; /// /// 图片缩放矩形 /// protected RectangleF _zoomRectf; /// /// 目标矩形 /// protected RectangleF _desRectf; /// /// 上一次控件矩形 /// protected RectangleF _oldClientRectf; /// /// 最小缩放系数 /// protected int _minZoom = 1; /// /// 最大缩放系数 /// protected int _maxZoom = 3200; /// /// 当前缩放系数 /// protected float _currentZoom; /// /// 是否为自适应状态 /// protected bool _isAutoFit = false; #endregion #region 事件处理程序 /// /// 控件改变大小 /// /// protected override void OnResize(EventArgs e) { base.OnResize(e); if (_displayImage != null) { if (_isAutoFit) { CalcuAutoSize(_displayImage); } else { //如果之前图片全在容器内 if (_oldClientRectf.Contains(_zoomRectf)) { var borderWidth = _customBorderVisible ? _customBorderWidth : 0; _zoomRectf.X = (_zoomRectf.X - borderWidth) / _oldClientRectf.Width * (this.Width - 2 * _customBorderWidth); _zoomRectf.Y = (_zoomRectf.Y - borderWidth) / _oldClientRectf.Height * (this.Height - 2 * _customBorderWidth); } _desRectf = GetClientRectangleF(); _desRectf.Intersect(_zoomRectf); _srcRectf = CalcuSrcRectangleF(_zoomRectf, _desRectf); } } _oldClientRectf = GetClientRectangleF(); this.Invalidate(); } /// /// 控件重绘 /// /// protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); DrawBorder(e.Graphics); if (_isAsyncLoading) { DrawAsyncLodingImage(e.Graphics); } else { if (_displayImage == null) { DrawNullText(e.Graphics); } else { e.Graphics.DrawImage(_displayImage, _desRectf, _srcRectf, GraphicsUnit.Pixel); } } } /// /// 绘制NullText /// /// protected virtual void DrawNullText(Graphics g) { if (!string.IsNullOrEmpty(this.NullText)) { var rectf = GetClientRectangleF(); using (var brush = new SolidBrush(this.ForeColor)) { var stringformat = new StringFormat(); stringformat.Alignment = StringAlignment.Center; stringformat.LineAlignment = StringAlignment.Center; var p = new PointF(rectf.Width / 2 + rectf.X, rectf.Height / 2 + rectf.Y); g.DrawString(this.NullText, this.Font, brush, p, stringformat); } } } /// /// 绘制异步加载图片 /// /// protected virtual void DrawAsyncLodingImage(Graphics g) { lock (_asyncLoadingImage) { if (_asyncLoadingImage != null) { var clientRectf = GetClientRectangleF(); var scale = 1f; if (_asyncLoadingImage.Width > clientRectf.Width || _asyncLoadingImage.Height > clientRectf.Height) { var xscale = _asyncLoadingImage.Width / clientRectf.Width; var yscale = _asyncLoadingImage.Height / clientRectf.Height; scale = xscale > yscale ? xscale : yscale; } var autoWidth = _asyncLoadingImage.Width / scale; var autoHeight = _asyncLoadingImage.Height / scale; var zoomx = (clientRectf.Width - autoWidth) / 2; var zoomy = (clientRectf.Height - autoHeight) / 2; var desRectf = new RectangleF(zoomx, zoomy, autoWidth, autoHeight); var srcRectf = new RectangleF(0, 0, _asyncLoadingImage.Width, _asyncLoadingImage.Height); if (_animateImage != null) { g.DrawImage(_animateImage.Image, desRectf, srcRectf, GraphicsUnit.Pixel); } else { g.DrawImage(_asyncLoadingImage, desRectf, srcRectf, GraphicsUnit.Pixel); } } } } /// /// 鼠标滚轮移动 /// /// protected override void OnMouseWheel(MouseEventArgs e) { base.OnMouseWheel(e); if (_displayImage == null) return; if (!this.ClientRectangle.Contains(e.Location)) return; var flag = e.Delta > 0 ? 1 : 0; ZoomImage(flag, e.Location); } #endregion #region 可继承方法 /// /// flag为0代表缩小,其他代表放大,p为放大或缩小的中心点 /// /// /// protected void ZoomImage(int flag, Point? p = null) { _isAutoFit = false; #region zoom float zoom; if (flag == 0)//缩小 { if (_currentZoom > _minZoom) zoom = _currentZoom * 0.9f; else zoom = _minZoom; if (zoom < _minZoom) zoom = _minZoom; } else { if (_currentZoom < _maxZoom) { zoom = _currentZoom * 1.1f; } else { zoom = _maxZoom; } if (zoom > _maxZoom) zoom = _maxZoom; } #endregion #region RectangleF PointF px; if (p != null && _desRectf.Contains(p.Value)) { px = new PointF(p.Value.X, p.Value.Y); } else { px = new PointF(_desRectf.X + _desRectf.Width / 2, _desRectf.Y + _desRectf.Height / 2); } var pxScaleX = (px.X - _zoomRectf.X) / _zoomRectf.Width; var pxScaleY = (px.Y - _zoomRectf.Y) / _zoomRectf.Height; _zoomRectf.X = _zoomRectf.X - _displayImage.Width / 100f * (zoom - _currentZoom) * pxScaleX; _zoomRectf.Y = _zoomRectf.Y - _displayImage.Height / 100f * (zoom - _currentZoom) * pxScaleY; _zoomRectf.Width = _displayImage.Width / 100f * zoom; _zoomRectf.Height = _displayImage.Height / 100f * zoom; _desRectf = GetClientRectangleF(); _desRectf.Intersect(_zoomRectf); _srcRectf = CalcuSrcRectangleF(_zoomRectf, _desRectf); #endregion _currentZoom = zoom; this.Invalidate(); } /// /// 移动图片 /// /// protected void MoveImage(Point p) { if (this.Image == null) return; _isAutoFit = false; _zoomRectf.X += p.X - _mouseLeftMovePoint.X; _zoomRectf.Y += p.Y - _mouseLeftMovePoint.Y; _desRectf = GetClientRectangleF(); _desRectf.Intersect(_zoomRectf); _srcRectf = CalcuSrcRectangleF(_zoomRectf, _desRectf); _mouseLeftMovePoint = p; this.Invalidate(); } /// /// 通过_zoomRectf和desRectf计算_srcRectf /// /// /// /// protected RectangleF CalcuSrcRectangleF(RectangleF zoomRectf, RectangleF desRectf) { var srcScaleX = (desRectf.X - zoomRectf.X) / zoomRectf.Width; var srcScaleY = (desRectf.Y - zoomRectf.Y) / zoomRectf.Height; var srcScaleW = desRectf.Width / zoomRectf.Width; var srcScaleH = desRectf.Height / zoomRectf.Height; var x = _displayImage.Width * srcScaleX; var y = _displayImage.Height * srcScaleY; var width = _displayImage.Width * srcScaleW; var height = _displayImage.Height * srcScaleH; return new RectangleF(x, y, width, height); } /// /// 计算自适应的相关参数 /// /// protected void CalcuAutoSize(Image img) { if (img == null) return; var crectf = GetClientRectangleF(); var scale = 1f; if (img.Width > crectf.Width || img.Height > crectf.Height) { var xscale = img.Width / crectf.Width; var yscale = img.Height / crectf.Height; scale = xscale > yscale ? xscale : yscale; } _currentZoom = 100 / scale; var autoWidth = img.Width / scale; var autoHeight = img.Height / scale; var zoomx = (crectf.Width - autoWidth) / 2; var zoomy = (crectf.Height - autoHeight) / 2; _srcRectf = new RectangleF(0, 0, img.Width, img.Height); _zoomRectf = new RectangleF(zoomx, zoomy, autoWidth, autoHeight); _desRectf = _zoomRectf; } /// /// 获取工作区域(去除边框) /// /// protected RectangleF GetClientRectangleF() { if (_customBorderVisible) { return new RectangleF(_customBorderWidth, _customBorderWidth, this.Width - 2 * _customBorderWidth, this.Height - 2 * _customBorderWidth); } else { return new RectangleF(0, 0, this.Width, this.Height); } } /// /// 旋转图片 /// /// protected void RotateImage(Image img) { var angle = _displayAngle % 360; switch (angle) { case 90: img.RotateFlip(RotateFlipType.Rotate90FlipNone); break; case 180: img.RotateFlip(RotateFlipType.Rotate180FlipNone); break; case 270: img.RotateFlip(RotateFlipType.Rotate270FlipNone); break; default: break; } } #endregion #region 公有方法 /// /// 重置图片 /// public void ResetImage() { this.DisplayImage = _img; } /// /// 显示加载界面 /// public void ShowLoading() { _isAsyncLoading = true; if (_animateImage != null) _animateImage.Play(); this.Invalidate(); } /// /// 隐藏加载界面 /// public void HideLoading() { _isAsyncLoading = false; if (_animateImage != null) _animateImage.Stop(); this.Invalidate(); } /// /// 自适应(针对于显示图片) /// public void SetAutoFit() { if (_displayImage == null) return; _isAutoFit = true; CalcuAutoSize(_displayImage); this.Invalidate(); } /// /// 保存图片 /// /// /// public bool SaveDisplayImage(string fileName) { if (_displayImage == null) return false; try { _displayImage.Save(fileName); return true; } catch { return false; } } /// /// 保存至Png格式 /// public bool ExportToBmp() { string file_path = null; return ExportToBmp(out file_path); } /// /// 保存至BMP格式 /// public bool ExportToBmp(out string file_path) { file_path = null; if (_displayImage == null) return false; var dlg = new SaveFileDialog(); dlg.Title = "保存Bmp格式图片"; dlg.Filter = "图片|*.bmp"; dlg.AutoUpgradeEnabled = true; dlg.AddExtension = true; dlg.DefaultExt = ".bmp"; if (dlg.ShowDialog() == DialogResult.OK) { _displayImage.Save(dlg.FileName, ImageFormat.Bmp); file_path = dlg.FileName; return true; } else { return false; } } /// /// 保存至Png格式 /// public bool ExportToPng() { string file_path = null; return ExportToPng(out file_path); } /// /// 保存至Png格式 /// public bool ExportToPng(out string file_path) { file_path = null; if (_displayImage == null) return false; var dlg = new SaveFileDialog(); dlg.Title = "保存PNG格式图片"; dlg.Filter = "图片|*.png"; dlg.AutoUpgradeEnabled = true; dlg.AddExtension = true; dlg.DefaultExt = ".png"; if (dlg.ShowDialog() == DialogResult.OK) { _displayImage.Save(dlg.FileName, ImageFormat.Png); file_path = dlg.FileName; return true; } else { return false; } } /// /// 保存至Png格式 /// /// /// public bool ExportToPng(string filePath) { _displayImage.Save(filePath, ImageFormat.Png); return true; } /// /// 保存至Png格式 /// public bool ExportToJpeg() { string file_path = null; return ExportToJpeg(out file_path); } /// /// 保存至Jpeg格式 /// public bool ExportToJpeg(out string file_path) { file_path = null; if (_displayImage == null) return false; var dlg = new SaveFileDialog(); dlg.Title = "保存Jpeg格式图片"; dlg.Filter = "图片|*.jpeg"; dlg.AutoUpgradeEnabled = true; dlg.AddExtension = true; dlg.DefaultExt = ".jpeg"; if (dlg.ShowDialog() == DialogResult.OK) { file_path = dlg.FileName; _displayImage.Save(dlg.FileName, ImageFormat.Jpeg); return true; } return false; } /// /// 向右旋转90度 /// public void RotateToRight() { if (_displayImage == null) return; _displayImage.RotateFlip(RotateFlipType.Rotate90FlipNone); _displayAngle += 90; SetAutoFit(); } /// /// 向左旋转90度 /// public void RotateToLeft() { if (_displayImage == null) return; _displayImage.RotateFlip(RotateFlipType.Rotate270FlipNone); _displayAngle += 270; SetAutoFit(); } /// /// 替换图片(如果尺寸相同保持状态,否则重置) /// /// public virtual void ReplaceImage(Image img) { if (img != null && _img != null) { if (img.Size == _img.Size) { _img = img; var cimg = _img.CloneC(); RotateImage(cimg); if (_displayImage != null) _displayImage.Dispose(); _displayImage = cimg; this.Invalidate(); return; } } this.Image = img; } /// /// 放大 /// public void ZoomOut() { if (this.Image == null) return; ZoomImage(1); } /// /// 缩小 /// public void ZoomIn() { if (this.Image == null) return; ZoomImage(0); } #endregion #region 坐标转换 /// /// 根据容器上的点获取相对于显示图片的点位置 /// /// /// protected virtual PointF ViewPointToDisplay(PointF vp) { var dp = new PointF(); dp.X = (vp.X - _zoomRectf.X) / _currentZoom * 100; dp.Y = (vp.Y - _zoomRectf.Y) / _currentZoom * 100; return dp; } /// /// 根据容器上的点获取相对于源图的点位置 /// /// /// public virtual PointF? ViewPointToImage(PointF vf) { if (Image == null) return null; if (!_desRectf.Contains(vf)) return null; var dp = ViewPointToDisplay(vf); var sp = DisplayPointToSource(dp); return sp; } /// /// 将DisplayImage上的点坐标转换为Image上的坐标 /// /// /// protected virtual PointF DisplayPointToSource(PointF dp) { var sp = dp; var angle = _displayAngle % 360; switch (angle) { case 90: sp = new PointF(dp.Y, _displayImage.Width - dp.X); break; case 180: sp = new PointF(_displayImage.Width - dp.X, _displayImage.Height - dp.Y); break; case 270: sp = new PointF(_displayImage.Height - dp.Y, dp.X); break; default: break; } return sp; } /// /// 将Image上的点坐标转换为DisplayImage上的坐标 /// /// /// protected virtual PointF SourcePointToDisplay(PointF sp) { var dp = sp; var angle = _displayAngle % 360; switch (angle) { case 90: dp = new PointF(_img.Height - sp.Y, sp.X); break; case 180: dp = new PointF(_img.Width - sp.X, this.Image.Height - sp.Y); break; case 270: dp = new PointF(sp.Y, _img.Width - sp.X); break; default: break; } return dp; } /// /// 通过源图点获取zoom图片点 /// /// /// protected virtual PointF SourcePointToZoom(PointF sp) { var dp = SourcePointToDisplay(sp); var zp = DisplayPointToZoom(dp); return zp; } /// /// 通过DislayImage上的点获取Zoom上的点 /// /// /// protected virtual PointF DisplayPointToZoom(PointF dp) { var zp = new PointF(); zp.X = dp.X * _currentZoom / 100 + _zoomRectf.X; zp.Y = dp.Y * _currentZoom / 100 + _zoomRectf.Y; return zp; } #endregion /// /// 释放图片资源 /// protected virtual void DisposeImages() { if (_displayImage != null) _displayImage.Dispose(); if (_animateImage == null) { if (_asyncLoadingImage != null) _asyncLoadingImage.Dispose(); } else { _animateImage.Dispose(); } if (_img != null) { if (this.IsDisposeImageWhenDisposed) { _img.Dispose(); } } } } }