在Canvas上绘图无法正确保存WPF

时间:2018-05-22 17:13:54

标签: c# wpf

我在画布中有一个图像,用户可以在图像中单击,并且绿色点出现在用户点击的位置。

Image shown

我想将图像保存在内存流中供以后使用,所有图像保存都很好,除了似乎没有正确绘制的点,我的猜测是关于我必须应用于绘制的屏幕比例绿点,因为显示的图像小于源图像。

Image saved

XAML:

<Canvas x:Name="ImageCanvas"
        Grid.Column="1"
        Background="Transparent">

    <Image x:Name="SelectedPartImage"
           Width="{Binding ElementName=ImageCanvas, Path=ActualWidth}"
           Height="{Binding ElementName=ImageCanvas, Path=ActualHeight}"
           Panel.ZIndex="0"
           MouseLeftButtonDown="OnMouseLeftButtonDown"
           Source="{Binding SelectedPartImageSource}" />

    <Ellipse x:Name="EllipseClick"
             Width="15"
             Height="15"
             Panel.ZIndex="1"
             Fill="{StaticResource GreenColor}"
             Visibility="Hidden" />
</Canvas>

DrawEllipse(我用来绘制椭圆的方法,AdjustToCanvas只是避免用户在图片所在的画布外面点击)

public void DrawEllipse()
{
    // Adjust To Canvas
    (double x, double y) = AdjustToCanvas(Mouse.GetPosition(ImageCanvas));

    // Center Ellipse
    x -= EllipseClick.Width / 2;
    y -= EllipseClick.Height / 2;

    Canvas.SetLeft(EllipseClick, x);
    Canvas.SetTop(EllipseClick, y);
}

OnMouseLeftButtonDown(绘制椭圆的click方法)

public void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    DrawEllipse();

    Point point = Mouse.GetPosition(SelectedPartImage);

    if (!(point.ConvertWPFPointToImagePoint(
                  SelectedPartImageSource.PixelWidth,
                  SelectedPartImageSource.PixelHeight,
                  SelectedPartImage.ActualWidth,
                  SelectedPartImage.ActualHeight))
    {
        return;
    }

    // CheckAlpha checks that the clicked point is inside the image and not outside of it.
    SelectPositionSuccess = CheckAlpha((int)point.X, (int)point.Y);

    EllipseClick.Visibility = SelectPositionSuccess ? Visibility.Visible : Visibility.Hidden;

    if (SelectPositionSuccess)
    {
        //Saving the Canvas
        RenderTargetBitmap rtb = new RenderTargetBitmap(
            (int)SelectedPartImageSource.Width,
            (int)SelectedPartImageSource.Height,
            96d,
            96d,
            System.Windows.Media.PixelFormats.Default);

        rtb.Render(ImageCanvas);

        //endcode as PNG
        PngBitmapEncoder pngEncoder = new PngBitmapEncoder();
        pngEncoder.Frames.Add(BitmapFrame.Create(rtb));

        //save to memory stream
        System.IO.MemoryStream ms = new System.IO.MemoryStream();
        pngEncoder.Save(ms);
        ms.Close();

        var bitmap = new BitmapImage();
        bitmap.BeginInit();
        bitmap.StreamSource = ms;
        bitmap.CacheOption = BitmapCacheOption.OnLoad;
        bitmap.EndInit();

        System.IO.File.WriteAllBytes("test.png", ms.ToArray());
    }
}

我有什么想法可以解决这个问题?

提前致谢!

1 个答案:

答案 0 :(得分:1)

在您的代码中设置其属性后,UIElement不会立即呈现。它只会在返回该方法后才能完成。

在这种情况下,尝试在更新其位置后立即保存EllipseClick将不会保存新位置,但是它的原始位置是(0,0),因为它没有设置!

要解决此问题,请将Save()方法移至另一个事件或调用

ImageCanvas.UpdateLayout(); 

更新EllipseClick的位置后。