将画布数据保存到图像文件输出是错误的

本文关键字:文件 图像 输出 错误 保存 布数据 数据 | 更新日期: 2023-09-27 18:03:24

我想在父图像上放置图像并保存最终图像。所以我在画布中使用父图像,并在画布中添加子图像。

问题:

  1. 当我加载缩略图(子)图像后,如果我点击父图像,则缩略图(子)图像变为可见。
  2. 我无法使用mouse left button up版本精确地将缩略图(子)图像放置在父图像上。
  3. 我无法用实际图像高度保存最终图像&宽度。最终保存的图像输出高度&

请指导我解决以上问题。

SpecialEffects XAML:

<Window
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:System="clr-namespace:System;assembly=mscorlib"
         x:Class="ImagePrintUtility.SpecialEffects"
        Title="SpecialEffects" Height="768" Width="1024" >

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="125"/>
            <RowDefinition Height="1*" />
        </Grid.RowDefinitions>
        <DockPanel Grid.Row="0"  HorizontalAlignment="Stretch" Margin="0" Background="AliceBlue" Name="DockPanel1">
            <WrapPanel>
                <StackPanel Margin="5">
                    <Button Content="AddLogo" Click="Button_Click"    Height="50" Width="90" />
                    <Button Content="Reset Logo" x:Name="bresetLogo" Height="50" Width="90" Margin="0,5"  />
                </StackPanel>
                <StackPanel Margin="5">
                    <Button  Name="bSave" Width="90"   Height="50"  Foreground="White" Content="Save" Click="bSave_Click" />
                    <Button x:Name="btnClose" Content="Close" Height="50" Width="90" Margin="0,5"  FontSize="20" Click="btnClose_Click"    />
                </StackPanel>
            </WrapPanel>
        </DockPanel>
        <!--<GridSplitter Grid.Row="1" Grid.RowSpan="1" ResizeDirection="Rows" Width="Auto" Height="10" HorizontalAlignment="Stretch" Margin="0" Name="GridSplitter1" />-->
        <Grid Grid.Row="1"  Margin="0" Background="AliceBlue" Name="Grid1">
            <StackPanel  >
                <Canvas x:Name="canvas"    HorizontalAlignment="Stretch" 
            MouseLeftButtonDown="CanvasMouseLeftButtonDown"
            MouseLeftButtonUp="CanvasMouseLeftButtonUp"
            MouseMove="CanvasMouseMove" Margin="0,0,31,0">
                    <Image x:Name="SpecialPhoto"    Source="IMG_0071.JPG" Height="586" Width="780"  
                     Stretch="Uniform" VerticalAlignment="Top" HorizontalAlignment="Center" />
                </Canvas>
            </StackPanel>

        </Grid>
    </Grid>
</Window>

SpecialEffects.cs代码:

public partial class SpecialEffects : Window
    {
        private string FileNmae;
        private int actualWidth;
        private int actualHeight;
        public SpecialEffects(string getTheFN) //Load the selected Image from ParentWindow
        {
            InitializeComponent();
             FileNmae = getTheFN;
            BitmapImage src = new BitmapImage();
            src.BeginInit();
            src.UriSource = new Uri(FileNmae, UriKind.Relative);
            src.CacheOption = BitmapCacheOption.OnLoad;
            src.EndInit();
            SpecialPhoto.Source = src;
        }
        private Image draggedImage;
        private Point mousePosition;
        bool captured = false;
        private void CanvasMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            var image = e.Source as Image;
            if (image != null && canvas.CaptureMouse())
            {
                mousePosition = e.GetPosition(canvas);
                draggedImage = image;
                Panel.SetZIndex(draggedImage, 1); // in case of multiple images
            }
        }
        private void CanvasMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            if (draggedImage != null)
            {
                canvas.ReleaseMouseCapture();
                Panel.SetZIndex(draggedImage, 0);
                draggedImage = null;
                Mouse.Capture(null);
                captured = false;
            }
        }
        private void CanvasMouseMove(object sender, MouseEventArgs e)
        {
            if (draggedImage != null)
            {
                var position = e.GetPosition(canvas);
                var offset = position - mousePosition;
                mousePosition = position;
                double left = Canvas.GetLeft(draggedImage) + offset.X;
                double top = Canvas.GetTop(draggedImage) + offset.Y;
                if (left < 0)
                {
                    left = 0;
                }
                if (top < 0)
                {
                    top = 0;
                }
                if (left + draggedImage.ActualWidth > SpecialPhoto.ActualWidth)
                {
                    left = SpecialPhoto.ActualWidth - draggedImage.ActualWidth;
                }
                if (top + draggedImage.ActualHeight > SpecialPhoto.ActualHeight)
                {
                    top = SpecialPhoto.ActualHeight - draggedImage.ActualHeight;
                }
                Canvas.SetLeft(draggedImage, left);
                Canvas.SetTop(draggedImage, top);
            }
        }
        private void btnClose_Click(object sender, RoutedEventArgs e)
        {
            this.Close();
        }
        private void bSave_Click(object sender, RoutedEventArgs e)
        {
            string fileLocation = System.IO.Path.GetDirectoryName(FileNmae);// get the selected file location
            string getFileName = System.IO.Path.GetFileName(FileNmae); //get the seleceted filename
            DateTime time = DateTime.Now;              // Use current time
            string format = "MMMddddHHmmssyyyy";
            string s2 = time.ToString(format) + getFileName; // add $ at front along with the folde name

            string filenamecombined = System.IO.Path.Combine(fileLocation, s2);//combine path. 
            RenderTargetBitmap renderTarget = new RenderTargetBitmap(
             (int)SpecialPhoto.Height,
             (int)SpecialPhoto.Width,
             96, 96, PixelFormats.Pbgra32);
            //renderTarget.Render(ViewedPhoto);
            ModifyPosition(canvas as FrameworkElement);
            renderTarget.Render(canvas);
            ModifyPositionBack(canvas as FrameworkElement);
            JpegBitmapEncoder encoder = new JpegBitmapEncoder();
            encoder.Frames.Add(BitmapFrame.Create(renderTarget));
            //string imagePath = System.IO.Path.GetTempFileName();
            using (FileStream stream = new FileStream(filenamecombined, FileMode.Create))
            {
                encoder.Save(stream);
                stream.Dispose();
            }
        }
        private void ModifyPosition(FrameworkElement fe)
        {
            /// get the size of the visual with margin
            System.Windows.Size fs = new System.Windows.Size(
                fe.ActualWidth +
                fe.Margin.Left + fe.Margin.Right,
                fe.ActualHeight +
                fe.Margin.Top + fe.Margin.Bottom);
            /// measure the visual with new size
            fe.Measure(fs);
            /// arrange the visual to align parent with (0,0)
            fe.Arrange(new Rect(
                -fe.Margin.Left, -fe.Margin.Top,
                fs.Width, fs.Height));
        }
        private void ModifyPositionBack(FrameworkElement fe)
        {
            /// remeasure a size smaller than need, wpf will
            /// rearrange it to the original position
            fe.Measure(new System.Windows.Size());
        }
        private void Button_Click(object sender, RoutedEventArgs e) // To load another image
        {
            var dialog = new Microsoft.Win32.OpenFileDialog();
            dialog.Filter =
                "Image Files (*.jpg;*.png; *.jpeg; *.gif; *.bmp)|*.jpg;*.png; *.jpeg; *.gif; *.bmp";
            if ((bool)dialog.ShowDialog())
            {
                BitmapImage src = new BitmapImage();
                src.BeginInit();
                src.UriSource = new Uri(dialog.FileName, UriKind.Relative);
                src.DecodePixelHeight = 120;
                src.DecodePixelWidth = 120;
                src.CacheOption = BitmapCacheOption.OnLoad;
                src.EndInit();
                var image = new Image { Source = src };
                Canvas.SetLeft(image, 0);
                Canvas.SetTop(image, 0);
                canvas.Children.Add(image);
            }
        }
}

将画布数据保存到图像文件输出是错误的

问题1 -在图像的xaml中,添加IsEnabled="False"。这将阻止点击隐藏子图像。

<Image x:Name="SpecialPhoto" Source="IMG_0071.JPG" Height="586" Width="780"
        IsEnabled="False"
    Stretch="Uniform" VerticalAlignment="Top" HorizontalAlignment="Center" />

问题2 -我没有遇到过这种情况,也许你在窗口中打开了某种鼠标加速功能?

问题3 -你用高度代替宽度用宽度代替高度。变化:

RenderTargetBitmap renderTarget = new RenderTargetBitmap(
             (int)SpecialPhoto.Height,
             (int)SpecialPhoto.Width,
             96, 96, PixelFormats.Pbgra32);

:

RenderTargetBitmap renderTarget = new RenderTargetBitmap(
             (int)SpecialPhoto.Width,
             (int)SpecialPhoto.Height,
             96, 96, PixelFormats.Pbgra32);

你问的注释问题的代码:

private void bSave_Click(object sender, RoutedEventArgs e)
{
    string fileLocation = System.IO.Path.GetDirectoryName(FileNmae);// get the selected file location
    string getFileName = System.IO.Path.GetFileName(FileNmae); //get the seleceted filename
    DateTime time = DateTime.Now;              // Use current time
    string format = "MMMddddHHmmssyyyy";
    string s2 = time.ToString(format) + getFileName; // add $ at front along with the folde name

    string filenamecombined = System.IO.Path.Combine(fileLocation, s2);//combine path. 
    #region Change the SpecialPhoto to be the size of its image and adjust the other images to match
    double w = SpecialPhoto.Width;
    double h = SpecialPhoto.Height;
    SpecialPhoto.Width = SpecialPhoto.Source.Width;
    SpecialPhoto.Height = SpecialPhoto.Source.Height;
    // Get the ratio of the change in width/height
    double rw = SpecialPhoto.Width / w;
    double rh = SpecialPhoto.Height / h;
    // Adjust the logos added to keep in the same relative position and size
    foreach (Image img in canvas.Children)
    {
        if (img == SpecialPhoto)
            continue;
        double left = Canvas.GetLeft(img);
        double top = Canvas.GetTop(img);
        Canvas.SetLeft(img, left * rw);
        Canvas.SetTop(img, top * rh);
        img.RenderTransform = new ScaleTransform(rw, rh);
    }
    #endregion
    RenderTargetBitmap renderTarget = new RenderTargetBitmap(
        (int)SpecialPhoto.Width,
        (int)SpecialPhoto.Height,
        96, 96, PixelFormats.Pbgra32);
    //renderTarget.Render(ViewedPhoto);
    ModifyPosition(canvas as FrameworkElement);
    renderTarget.Render(canvas);
    ModifyPositionBack(canvas as FrameworkElement);
    #region Undo the changes we did to the SpecialPhoto/logos
    SpecialPhoto.Width = w;
    SpecialPhoto.Height = h;
    foreach (Image img in canvas.Children)
    {
        if (img == SpecialPhoto)
            continue;
        double left = Canvas.GetLeft(img);
        double top = Canvas.GetTop(img);
        Canvas.SetLeft(img, left / rw);
        Canvas.SetTop(img, top / rh);
        img.RenderTransform = new ScaleTransform(1, 1);
    }
    #endregion
    JpegBitmapEncoder encoder = new JpegBitmapEncoder();
    encoder.Frames.Add(BitmapFrame.Create(renderTarget));
    //string imagePath = System.IO.Path.GetTempFileName();
    using (FileStream stream = new FileStream(filenamecombined, FileMode.Create))
    {
        encoder.Save(stream);
        stream.Dispose();
    }
}

第二个注释问题的代码(将子图像保留在父图像中):

我们需要改变两个方法。第一个方法是CanvasMouseMove:

private void CanvasMouseMove(object sender, MouseEventArgs e)
{
    if (draggedImage != null)
    {
        var position = e.GetPosition(canvas);
        var offset = position - mousePosition;
        mousePosition = position;
        double left = Canvas.GetLeft(draggedImage) + offset.X;
        double top = Canvas.GetTop(draggedImage) + offset.Y;
        Point tl = SpecialPhoto.TranslatePoint(new Point(0, 0), canvas);
        Point br = SpecialPhoto.TranslatePoint(new Point(SpecialPhoto.ActualWidth, SpecialPhoto.ActualHeight), canvas);
        if (left < tl.X)
        {
            left = tl.X;
        }
        if (top < tl.Y)
        {
            top = tl.Y;
        }
        if (left + draggedImage.ActualWidth > br.X)
        {
            left = br.X - draggedImage.ActualWidth;
        }
        if (top + draggedImage.ActualHeight > br.Y)
        {
            top = br.Y - draggedImage.ActualHeight;
        }
        Canvas.SetLeft(draggedImage, left);
        Canvas.SetTop(draggedImage, top);
    }
}
第二个方法是Button_Click:
private void Button_Click(object sender, RoutedEventArgs e) // To load another image
{
    var dialog = new Microsoft.Win32.OpenFileDialog();
    dialog.Filter =
        "Image Files (*.jpg;*.png; *.jpeg; *.gif; *.bmp)|*.jpg;*.png; *.jpeg; *.gif; *.bmp";
    if ((bool)dialog.ShowDialog())
    {
        BitmapImage src = new BitmapImage();
        src.BeginInit();
        src.UriSource = new Uri(dialog.FileName, UriKind.Relative);
        src.DecodePixelHeight = 120;
        src.DecodePixelWidth = 120;
        src.CacheOption = BitmapCacheOption.OnLoad;
        src.EndInit();
        var image = new Image { Source = src };
        Point p = SpecialPhoto.TranslatePoint(new Point(0, 0), canvas);
        Canvas.SetLeft(image, p.X);
        Canvas.SetTop(image, p.Y);
        canvas.Children.Add(image);
    }
}