ImageViewerControl.xaml.cs 9.0 KB
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace SmartScan.SetControl.WPF
{
    /// <summary>
    /// ImageViewerControl.xaml 的交互逻辑
    /// </summary>
    public partial class ImageViewerControl : UserControl
    {
        private const double MinZoom = 0.1;
        private const double MaxZoom = 5.0;
        private const double ZoomIncrement = 0.1;
        private System.Drawing.PointF[] originalCenters;

        public ImageViewerControl()
        {
            InitializeComponent();
            // 当控件大小改变时自动调整图片大小
            this.SizeChanged += (sender, e) => {
                if (mainImage.Source != null)
                {
                    FitToScreen();
                }
            };

            // 当ScrollViewer大小改变时调整图片
            scrollViewer.SizeChanged += (sender, e) => {
                if (mainImage.Source != null)
                {
                    FitToScreen();
                }
            };
        }




        /// <summary>
        /// 从流中加载图片
        /// </summary>
        public void LoadImageFromStream(Stream stream)
        {
            BitmapImage bitmapImage = new BitmapImage();
            bitmapImage.BeginInit();
            bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
            bitmapImage.StreamSource = stream;
            bitmapImage.EndInit();

            mainImage.Source = bitmapImage;

            // 重置缩放
            //imageScaleTransform.ScaleX = 1.0;
            //imageScaleTransform.ScaleY = 1.0;

            // 清除先前的中心点
            centerPointsCanvas.Children.Clear();
            
            // 图片加载后适应屏幕
            // 延迟调用,确保布局已更新
            Dispatcher.BeginInvoke(new Action(FitToScreen), System.Windows.Threading.DispatcherPriority.Loaded);

        }

        /// <summary>
        /// 在图片上绘制代码中心点
        /// </summary>
        public void DrawCodeCenters(System.Drawing.PointF[] centers)
        {
            centerPointsCanvas.Children.Clear();
            originalCenters = centers;

            if (centers == null || centers.Length == 0 || mainImage.Source == null)
                return;

            RedrawCenters();
        }

        /// <summary>
        /// 根据当前缩放比例重新绘制中心点
        /// </summary>
        private void RedrawCenters()
        {
            if (originalCenters == null || originalCenters.Length == 0 || mainImage.Source == null)
                return;

            centerPointsCanvas.Children.Clear();

            // 获取图像的实际显示尺寸
            var imageSource = (BitmapSource)mainImage.Source;
            double scaleX = imageScaleTransform.ScaleX;
            double scaleY = imageScaleTransform.ScaleY;

            // 计算图像在控件中的实际位置
            double offsetX = (scrollViewer.ViewportWidth - imageSource.PixelWidth * scaleX) / 2;
            double offsetY = (scrollViewer.ViewportHeight - imageSource.PixelHeight * scaleY) / 2;

            // 调整Canvas大小与图像显示尺寸一致
            centerPointsCanvas.Width = imageSource.PixelWidth * scaleX;
            centerPointsCanvas.Height = imageSource.PixelHeight * scaleY;

            foreach (var point in originalCenters)
            {
                // 创建椭圆表示中心点
                Ellipse ellipse = new Ellipse
                {
                    Width = 10,
                    Height = 10,
                    Fill = Brushes.Red,
                    Stroke = Brushes.White,
                    StrokeThickness = 2
                };

                // 设置椭圆位置,只考虑缩放,不考虑偏移
                Canvas.SetLeft(ellipse, point.X * scaleX - ellipse.Width / 2);
                Canvas.SetTop(ellipse, point.Y * scaleY - ellipse.Height / 2);

                centerPointsCanvas.Children.Add(ellipse);
            }
        }


        /// <summary>
        /// 放大按钮点击事件
        /// </summary>
        private void ZoomInButton_Click(object sender, RoutedEventArgs e)
        {
            if (imageScaleTransform.ScaleX < MaxZoom)
            {
                imageScaleTransform.ScaleX += ZoomIncrement;
                imageScaleTransform.ScaleY += ZoomIncrement;

                // 显示滚动条,因为放大后可能需要滚动查看图像细节
                if (imageScaleTransform.ScaleX > 1.0)
                {
                    scrollViewer.HorizontalScrollBarVisibility = ScrollBarVisibility.Auto;
                    scrollViewer.VerticalScrollBarVisibility = ScrollBarVisibility.Auto;
                }

                RedrawCenters();
            }
        }

        /// <summary>
        /// 缩小按钮点击事件
        /// </summary>
        private void ZoomOutButton_Click(object sender, RoutedEventArgs e)
        {
            if (imageScaleTransform.ScaleX > MinZoom)
            {
                imageScaleTransform.ScaleX -= ZoomIncrement;
                imageScaleTransform.ScaleY -= ZoomIncrement;

                // 如果缩放到原始大小或更小,隐藏滚动条
                if (imageScaleTransform.ScaleX <= 1.0)
                {
                    scrollViewer.HorizontalScrollBarVisibility = ScrollBarVisibility.Hidden;
                    scrollViewer.VerticalScrollBarVisibility = ScrollBarVisibility.Hidden;
                }

                RedrawCenters();
            }
        }

        /// <summary>
        /// 适应屏幕按钮点击事件
        /// </summary>
        private void FitToScreenButton_Click(object sender, RoutedEventArgs e)
        {
            FitToScreen();
        }

        /// <summary>
        /// 适应屏幕逻辑
        /// </summary>
        public void FitToScreen()
        {
            if (mainImage.Source == null)
                return;

            // 获取父容器的实际尺寸
            double viewportWidth = scrollViewer.ActualWidth;
            double viewportHeight = scrollViewer.ActualHeight;
            // 获取图像尺寸
            double imageWidth = ((BitmapSource)mainImage.Source).PixelWidth;
            double imageHeight = ((BitmapSource)mainImage.Source).PixelHeight;
            // 计算合适的缩放比例,考虑容器的边距
            double scaleX = viewportWidth / imageWidth;
            double scaleY = viewportHeight / imageHeight;

            // 使用较小的缩放因子确保整个图像可见
            double scale = Math.Min(scaleX, scaleY);

            // 限制缩放范围
            //scale = Math.Max(MinZoom, Math.Min(scale, MaxZoom));

            // 应用缩放
            imageScaleTransform.ScaleX = scale;
            imageScaleTransform.ScaleY = scale;
            // 强制关闭滚动条,除非确实需要
            scrollViewer.HorizontalScrollBarVisibility = ScrollBarVisibility.Auto;
            scrollViewer.VerticalScrollBarVisibility = ScrollBarVisibility.Auto;

            // 确保更新UI

            scrollViewer.UpdateLayout();
            // 更新中心点
            RedrawCenters();
        }

        /// <summary>
        /// 实际大小按钮点击事件
        /// </summary>
        private void ActualSizeButton_Click(object sender, RoutedEventArgs e)
        {
            imageScaleTransform.ScaleX = 1.0;
            imageScaleTransform.ScaleY = 1.0;
            RedrawCenters();
        }

        /// <summary>
        /// 鼠标滚轮事件处理
        /// </summary>
        private void ScrollViewer_MouseWheel(object sender, MouseWheelEventArgs e)
        {
            double delta = e.Delta > 0 ? ZoomIncrement : -ZoomIncrement;
            double newScale = imageScaleTransform.ScaleX + delta;
            if (newScale >= MinZoom && newScale <= MaxZoom)
            {
                // 获取鼠标相对于图像的位置
                Point mousePos = e.GetPosition(mainImage);
                // 更新缩放
                imageScaleTransform.ScaleX = newScale;
                imageScaleTransform.ScaleY = newScale;
                // 调整滚动条可见性
                if (newScale > 1.0)
                {
                    scrollViewer.HorizontalScrollBarVisibility = ScrollBarVisibility.Auto;
                    scrollViewer.VerticalScrollBarVisibility = ScrollBarVisibility.Auto;
                }
                else
                {
                    scrollViewer.HorizontalScrollBarVisibility = ScrollBarVisibility.Hidden;
                    scrollViewer.VerticalScrollBarVisibility = ScrollBarVisibility.Hidden;
                }
                // 更新中心点
                RedrawCenters();
                // 防止事件继续传递
                e.Handled = true;
            }
        }
    }
}