首页 > 其他分享 >WPF将超大图像分割成多个小图像使用多任务Task并行处理显示

WPF将超大图像分割成多个小图像使用多任务Task并行处理显示

时间:2023-02-17 11:59:18浏览次数:42  
标签:Task Windows System new 图像 using WPF public imageMerge

using Microsoft.Win32;
using System;
using System.Collections.Generic;
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;
using System.Windows.Forms;
using MouseEventArgs = System.Windows.Input.MouseEventArgs;
using OpenFileDialog = System.Windows.Forms.OpenFileDialog;
using System.Threading;
using DataFormats = System.Windows.DataFormats;
using System.IO;
using OpenCvSharp;
using System.Runtime.InteropServices;
using Point = System.Windows.Point;

namespace 拼图排序
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : System.Windows.Window {
        Point previousPoint;
        bool isTranslateStart = false;
        ImageMerge imageMerge = new ImageMerge();
        ushort[] gray;
        ushort[] mat_gray;


        ushort slider_value = 0;
        Image[] Images = new Image[100];
        OpenCvSharp.Mat OriginalMat = new OpenCvSharp.Mat();
        int UpDateTime = 1000;

        public BitmapSource MatToBitmapSource(Mat mat, ref ushort[] gray) {
            PixelFormat pf = PixelFormats.Gray16;
            int rawStride = (mat.Width * pf.BitsPerPixel + 7) / 8;
            mat.GetArray(out gray);
            return BitmapSource.Create(mat.Width, mat.Height, 96, 96, pf, null, gray, rawStride);
        }

        private void OpenImages(string[] files) {
            OriginalMat = Cv2.ImRead(files[0], ImreadModes.Unchanged);
            mat_gray = new ushort[OriginalMat.Height * OriginalMat.Width];
            OriginalMat.GetArray(out mat_gray);
            imageMerge.ImageHeight = OriginalMat.Height / 4;
            imageMerge.ImageWidth = OriginalMat.Width / 4;
            gray = new ushort[imageMerge.ImageHeight * imageMerge.ImageWidth];
            for (int i = 0; i < 16; i++) {
                BitmapImage bmp = new BitmapImage();
                Image img = new Image();
                img.Source = bmp;
                img.Stretch = Stretch.Uniform;
                img.Width = imageMerge.ImageWidth;
                img.Height = imageMerge.ImageHeight;
                img.SetValue(RenderOptions.BitmapScalingModeProperty, BitmapScalingMode.NearestNeighbor);//取消抗锯齿
                inside.Children.Add(img);
                Images[imageMerge.ImageTotalPages] = img;

                imageMerge.ImageRow = imageMerge.ImageTotalPages / imageMerge.ImageColumnPages;//该照片所在行
                imageMerge.ImageColumn = imageMerge.ImageTotalPages % imageMerge.ImageColumnPages;//该照片所在列

                Canvas.SetTop(img, 0 + imageMerge.ImageRow * (imageMerge.ImageHeight + imageMerge.ImageMargin.Bottom));
                Canvas.SetLeft(img, 0 + imageMerge.ImageColumn * (imageMerge.ImageWidth + imageMerge.ImageMargin.Right));
                imageMerge.ImageTotalPages++;
            }
        }
        private void TaskImage(int i) {
            while (true) {
                Thread.Sleep(UpDateTime);
                if (imageMerge.ImageTotalPages > 0) {
                    OpenCvSharp.Rect rect = new OpenCvSharp.Rect(imageMerge.ImageWidth * (i % 4), imageMerge.ImageHeight * (i / 4), imageMerge.ImageWidth, imageMerge.ImageHeight);//设置范围
                    Mat cropped_image = new Mat(OriginalMat, rect);//裁剪图像
                    cropped_image = cropped_image * slider_value;
                    this.Dispatcher.Invoke(new Action(() =>
                    {
                        Images[i].Source = MatToBitmapSource(cropped_image, ref gray);
                    }));
                }
            }
        }
        public MainWindow()
        {
            InitializeComponent();

            imageMerge.ImageMargin.Left = 0;
            imageMerge.ImageMargin.Right = 0;
            imageMerge.ImageMargin.Top = 0;
            imageMerge.ImageMargin.Bottom = 0;
            imageMerge.ImageTotalPages = 0;
            imageMerge.ImageRowPages = 4;//行图片张数
            imageMerge.ImageColumnPages = 4;//列图片张数

            List<int> list = new List<int>();

            int taskCount = 16;
            for (int i = 0; i < taskCount; i++) {
                list.Add(i);
            }

            var tasks = list.Select(i => {
                return Task.Run(() => TaskImage(i));
            });
            Task.WhenAll(tasks);
        }

        private void outsidewrapper_PreviewMouseDown(object sender, MouseButtonEventArgs e)
        {
            if (e.MiddleButton == MouseButtonState.Pressed && e.LeftButton == MouseButtonState.Released && e.RightButton == MouseButtonState.Released)
            {
                previousPoint = e.GetPosition(outside);
                isTranslateStart = true;
            }
            e.Handled = true;
        }

        private void outsidewrapper_PreviewMouseMove(object sender, MouseEventArgs e)
        {
            if (e.MiddleButton == MouseButtonState.Pressed && e.LeftButton == MouseButtonState.Released && e.RightButton == MouseButtonState.Released)
            {
                if (isTranslateStart)
                {
                    Point currentPoint = e.GetPosition(outside);  //不能用 inside,必须用outside
                    System.Windows.Vector v = currentPoint - previousPoint;
                    TransformGroup tg = inside.RenderTransform as TransformGroup;
                    tg.Children.Add(new TranslateTransform(v.X, v.Y));  //centerX和centerY用外部包装元素的坐标,不能用内部被变换的Canvas元素的坐标
                    previousPoint = currentPoint;
                }
            }
            else
            {
                //适用于静止图像
                Point point2 = Mouse.GetPosition(inside);//获取Canvas坐标
                UInt32 x, y;
                x = (UInt32)point2.X;
                y = (UInt32)point2.Y;
                //xyGray.Text = $"x:{x} y:{y}";//显示坐标值
                if (x >= 0 && x < OriginalMat.Width && y >= 0 && y < OriginalMat.Height)
                    xyGray.Text = $"x:{x} y:{y} gray:{mat_gray[y * OriginalMat.Width + x]}";
                else
                    xyGray.Text = $"x:{x} y:{y} gray:- ";

            }
            e.Handled = true;
        }

        private void outside_PreviewMouseUp(object sender, MouseButtonEventArgs e)
        {
            if (e.MiddleButton == MouseButtonState.Pressed && e.LeftButton == MouseButtonState.Released && e.RightButton == MouseButtonState.Released)
            {
                if (isTranslateStart)
                {
                    isTranslateStart = false;
                }
            }
            e.Handled = true;
        }
        private void outside_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
        {
            Point currentPoint = e.GetPosition(outside);  //不能用 inside,必须用outside
            TransformGroup tg = inside.RenderTransform as TransformGroup;
            double s = ((double)e.Delta) / 1000.0 + 1.0;
            if (OriginalMat.Height * tg.Value.M22 < 200 || OriginalMat.Width * tg.Value.M11 < 200)
            {
                if (s > 1.0)//当图像像素宽度和高度小于200的时候只能放大,不再缩小
                    tg.Children.Add(new ScaleTransform(s, s, currentPoint.X, currentPoint.Y));
            }
            else
                tg.Children.Add(new ScaleTransform(s, s, currentPoint.X, currentPoint.Y));
            e.Handled = true;
        }


        private void BtnClickLoadPic(object sender, RoutedEventArgs e)
        {
            OpenFileDialog openFileDialog1 = new OpenFileDialog();

            //openFileDialog1.InitialDirectory = "E:\\"; //打开默认路径
            openFileDialog1.Filter = "All Files|*.*|PNG Files|*.png|JPG Files|*.jpg|TIF Files|*.tif";
            openFileDialog1.FilterIndex = 1;
            openFileDialog1.RestoreDirectory = true;
            openFileDialog1.Multiselect = true;

            if (openFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                try
                {
                    OpenImages(openFileDialog1.FileNames);
                }
                catch (Exception ex)
                {
                    System.Windows.MessageBox.Show("Error: Could not read file from disk. Original error: " + ex.Message);
                }
            }
        }

        private void BtnClickFullScreen(object sender, RoutedEventArgs e)
        {
            TransformGroup tg = inside.RenderTransform as TransformGroup;
            System.Windows.Media.Matrix value = new System.Windows.Media.Matrix();
            value.M11 = outside.ActualWidth / OriginalMat.Width / tg.Value.M11;//缩放倍数为Border的尺寸
            value.M22 = outside.ActualHeight / OriginalMat.Height / tg.Value.M22;
            value.OffsetX = (0 - tg.Value.OffsetX) * value.M11;//调整偏移XY到(0,0)
            value.OffsetY = (0 - tg.Value.OffsetY) * value.M22;
            MatrixTransform matrixTransform = new MatrixTransform(value);//添加矩阵变换
            tg.Children.Add(matrixTransform);
            e.Handled = true;
        }

        private void BtnClickClearScreen(object sender, RoutedEventArgs e)
        {
            imageMerge.ImageTotalPages = 0;
            inside.Children.Clear();
            inside.Children.RemoveRange(0, inside.Children.Count);
        }

        private void ImagePanel_Drop(object sender, System.Windows.DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
            {
                // Note that you can have more than one file.
                string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
                OpenImages(files);
            }
        }
        private void SliderValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            slider_value = (ushort)SliderGray.Value;
        }
    }

    //图像合并
    public class ImageMerge
    {
        public int ImageWidth;
        public int ImageHeight;
        public UInt32 ImageTotalPages;//图像总共张数
        public UInt32 ImageSelectPage;//选中的图片
        public UInt32 ImageRowPages;//一行存放照片的张数
        public UInt32 ImageColumnPages;//一列存放照片的张数
        public Margin ImageMargin;//相邻照片之间的边距
        public UInt32 ImageRow;//照片所在行
        public UInt32 ImageColumn;//照片所在列
        public bool IsBusy;
    }

    public struct Margin
    {
        public UInt32 Left;
        public UInt32 Right;
        public UInt32 Top;
        public UInt32 Bottom;
    }
}
MainWindow.xaml.cs
<Window x:Class="拼图排序.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:拼图排序"
        mc:Ignorable="d"
        Title="MainWindow" Height="800" Width="1000">

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="40"/>
            <RowDefinition Height="40"/>
        </Grid.RowDefinitions>
        <Border x:Name="outside" Background="Gray" 
                PreviewMouseDown="outsidewrapper_PreviewMouseDown" 
                PreviewMouseMove="outsidewrapper_PreviewMouseMove" 
                PreviewMouseUp="outside_PreviewMouseUp"
                PreviewMouseWheel="outside_PreviewMouseWheel"
                Drop="ImagePanel_Drop" AllowDrop="true"
                ClipToBounds="True" ScrollViewer.HorizontalScrollBarVisibility="Visible" >

            <Canvas x:Name="inside"   Width="{Binding ActualWidth, RelativeSource={RelativeSource AncestorType={x:Type Border}}}" 
                    Height="{Binding ActualHeight, RelativeSource={RelativeSource AncestorType={x:Type Border}}}" ScrollViewer.HorizontalScrollBarVisibility="Visible">
                <Canvas.RenderTransform>
                    <TransformGroup/>
                </Canvas.RenderTransform>
            </Canvas>
        </Border>
        <Slider x:Name="SliderGray"   Minimum ="1" Maximum="100" SmallChange="1" LargeChange="1"  Grid.Row="1" VerticalAlignment="Center" Margin="40,0,60,0"  ValueChanged="SliderValueChanged" ></Slider>
        <TextBlock Text="{Binding ElementName=SliderGray,Path=Value, StringFormat=0}" Grid.Row="1" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="0,0,10,0" ></TextBlock>

        <TextBlock x:Name="xyGray" Grid.Row="2" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="20,0,0,0" ></TextBlock>
        <Button Click="BtnClickLoadPic" Grid.Row="2" HorizontalAlignment="Right" Content="加载图片" />
        <Button Click="BtnClickFullScreen" Grid.Row="2" HorizontalAlignment="Right" Content="   全屏   " Margin="0,0,60,0" />
        <Button Click="BtnClickClearScreen" Grid.Row="2" HorizontalAlignment="Right" Content="   清屏   " Margin="0,0,120,0" />

    </Grid>

</Window>
MainWindow.xaml

本程序使用了OpenCvSharp第三方库

标签:Task,Windows,System,new,图像,using,WPF,public,imageMerge
From: https://www.cnblogs.com/lizhiqiang0204/p/17129658.html

相关文章