在UWP墨迹画布上显示背景图片

8

我在我的UWP应用程序中有一个InkCanvas,并希望显示一张图片(最好作为画布的一部分,否则以某种方式叠加它(这样做的想法是我可以将更改后的图像保存回图像文件))。WPF似乎允许InkCanvas具有子元素,但在UWP中似乎不可能。我尝试了以下方法:

        <InkCanvas x:Name="drawInkCanvas">
            <Image Source="{Binding DrawingImage}"/>

        </InkCanvas>

但是那样不行;我也尝试过这个:
        <Grid Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2">
            <InkCanvas x:Name="drawInkCanvas" Opacity=".5"/>
            <Image Source="{Binding DrawingImage}" Opacity=".5"/>

        </Canvas>

说实话,我对此并没有很高的期望;尽管它有点能用,但它使图像和InkCanvas看起来不对,并且显然无法让我保存生成的图像。

理想情况下,应该有一个背景图像或类似的东西。有什么可以用来实现这一点吗?我正在考虑可能需要用标准画布替换InkCanvas,然后重新编写所有的InkCanvas功能!


似乎 InkCanvas 不支持显示图像。您可以将图像放在 InkCanvas 下面,例如:<ScrollViewer><Grid><Image Source="<path>"></Image><InkCanvas x:Name="MyInkCanvas"></InkCanvas></Grid></ScrollViewer> - Jayden
1个回答

13

所以您有几个问题:

  1. 如何在Image控件上使用InkCanvas进行绘图。
  2. 如何将结果保存到文件中。

我将在此示例中使用简单的UWP应用程序,假设您的“Assets”文件夹中有“sample.jpg”文件,并且您的清单中具有“Pictures Library”功能。

要解决第一个问题,只需将InkCanvasImage放置在同一个容器(如Grid)中,但请记住顺序很重要

<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <Grid>
        <Image Source="/Assets/sample.jpg"></Image>
        <InkCanvas x:Name="ink"></InkCanvas>
    </Grid>
    <Button Content="Save"
            Width="100"
            Height="25"
            HorizontalAlignment="Center"
            VerticalAlignment="Center" Click="BtnSave_Click"/>
</StackPanel>

如果您首先放置 InkCanvas (就像您在问题示例中所做的那样) - 它不起作用。但是,如果将 InkCanvas 放在最后 - 一切都正常工作,您可以在图像上绘制。

现在要解决第二个问题,您需要使用 Win2D(安装 nuget Win2D.uwp 包),因为标准的 RenderTargetBitmap 无法呈现 InkCanvas 的内容。首先绘制原始图像(直接从原始文件中获取原始源图像),然后绘制墨水画布的内容覆盖在其上。如果您添加 xaml,则 MainPage 的完整代码如下(您将拥有完整的工作示例):

public sealed partial class MainPage : Page {
    public MainPage() {
        this.InitializeComponent();
        // just set some properties of ink canvas, not directly relevant to your question
        ink.InkPresenter.InputDeviceTypes = CoreInputDeviceTypes.Mouse | CoreInputDeviceTypes.Touch;
        var attr = new InkDrawingAttributes();
        attr.Color = Colors.Red;
        attr.IgnorePressure = true;
        attr.PenTip = PenTipShape.Circle;
        attr.Size = new Size(4, 10);
        ink.InkPresenter.UpdateDefaultDrawingAttributes(attr);
    }

    private async void BtnSave_Click(object sender, RoutedEventArgs e) {
        // grab output file
        StorageFolder storageFolder = KnownFolders.SavedPictures;
        var file = await storageFolder.CreateFileAsync("output.jpg", CreationCollisionOption.ReplaceExisting);

        CanvasDevice device = CanvasDevice.GetSharedDevice();
        CanvasRenderTarget renderTarget = new CanvasRenderTarget(device, (int) ink.ActualWidth, (int) ink.ActualHeight, 96);

        // grab your input file from Assets folder
        StorageFolder appInstalledFolder = Windows.ApplicationModel.Package.Current.InstalledLocation;
        StorageFolder assets = await appInstalledFolder.GetFolderAsync("Assets");
        var inputFile = await assets.GetFileAsync("sample.jpg");            
        using (var ds = renderTarget.CreateDrawingSession()) {
            ds.Clear(Colors.White);                
            var image = await CanvasBitmap.LoadAsync(device, inputFile.Path);
            // draw your image first
            ds.DrawImage(image);
            // then draw contents of your ink canvas over it
            ds.DrawInk(ink.InkPresenter.StrokeContainer.GetStrokes());
        }

        // save results
        using (var fileStream = await file.OpenAsync(FileAccessMode.ReadWrite)) {
            await renderTarget.SaveAsync(fileStream, CanvasBitmapFileFormat.Jpeg, 1f);
        }
    }
}

这个可以用 - 非常感谢。不过它确实会对宽度和高度做一些奇怪的事情,但我认为那只是在调整数字和位置。 - Paul Michaels
请注意,它从墨水画布的实际尺寸中获取宽度和高度。您可能希望改用原始图像尺寸。 - Evk

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接