在UWP墨水画布上显示背景图像

时间:2016-05-12 07:15:02

标签: c# win-universal-app inkcanvas

我的UWP应用程序中有一个InkCanvas,想要显示一个图像(理想情况下是Canvas的一部分,但除此之外,以某种方式覆盖它(我的想法是我可以将更改后的图像保存回图像文件).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功能!

1 个答案:

答案 0 :(得分:11)

所以你有几个问题:

  1. 如何使用InkCanvas控制Image进行绘制。
  2. 如何将结果保存到文件中。
  3. 我将在此示例中使用简单的UWP应用程序,假设您有&#34; sample.jpg&#34;文件在您的资产文件夹中,您有&#34;图片库&#34;你的清单中的能力。

    要解决第一个问题,只需将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内容。首先绘制原始图像(直接从原始图像中获取图像,例如从原始文件中获取图像),然后在其上绘制墨迹画布的内容。 MainPage的完整代码(如果你在上面添加xaml,你将有完整的工作样本):

    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);
            }
        }
    }