win2D uwp 不会在 inkcanvas 中保存高亮笔画

win2D uwp won't save a highlight stroke in an inkcanvas

我正在拼命尝试将突出显示笔画保存为 png。我正在使用 win2d for UWP 来完成这项工作。 它适用于 100% 不透明度的笔画,但是当我设置 DrawAsHighlighter = true; 时,保存的 png 是空的,完全透明的。

这是我的代码:

    private void SetHighLight()
    {
        InkDrawingAttributes attributes = new InkDrawingAttributes();
        attributes.DrawAsHighlighter = true;
        attributes.PenTip = PenTipShape.Rectangle;
        attributes.Size = new Size(4, 10);
        attributes.Color = currentColor;
        SetAttribute(attributes);
    }

    private void GetCanvasRender(out CanvasRenderTarget renderTarget)
    {
        CanvasDevice device = CanvasDevice.GetSharedDevice();
        renderTarget = new CanvasRenderTarget(device, (int)ink.ActualWidth, (int)ink.ActualHeight, 96);
        using (var ds = renderTarget.CreateDrawingSession())
        {
            ds.Clear(Colors.Transparent); //I already tried to delete this but it doesn't change anything
            ds.DrawInk(ink.InkPresenter.StrokeContainer.GetStrokes());
        }
    }

    private async void SavePicture()
    {
        CanvasRenderTarget renderTarget;
        Image img = new Image();

        GetCanvasRender(out renderTarget);
        StorageFolder storageFolder = ApplicationData.Current.LocalFolder;
        StorageFile noteFile = await storageFolder.CreateFileAsync(i.ToString() + ".png", CreationCollisionOption.ReplaceExisting);
        using (var fileStream = await noteFile.OpenAsync(FileAccessMode.ReadWrite))
            await renderTarget.SaveAsync(fileStream, CanvasBitmapFileFormat.Png, 1f);
        img.Source = new BitmapImage(new Uri(storageFolder.Path + "/" + i++ + ".png"));
        img.VerticalAlignment = VerticalAlignment.Stretch;
        ContainerCanvas.Children.Add(img);
        Canvas.SetTop(img, ScrollViewerContainer.VerticalOffset);
        Canvas.SetZIndex(img, 5);
    }

我读过这可能是因为高亮显示没有出现在可视化树中,但我真的不确定。

顺便说一句,当我尝试更改颜色的不透明度 (attributes.Color = Color.FromArgb(128, 255, 0, 0)) 时,inkcanvas 不应用 alpha,为什么?我错过了什么吗?

尝试使用以下方法清除 canvas 的背景:

ds.Clear(Colors.White);

荧光笔在透明背景上不可见,因为它似乎将其值与背景颜色相乘。

您不能将 DrawAsHighlighter 墨迹保存为 .png 等位图格式 - 从根本上说,这不是一个值得尝试的有意义的操作。

常规的非荧光笔墨水是使用标准的 alpha 混合绘制的,因此将这些墨水形状写入位图格式是合理的。您稍后可以将该位图混合到其他一些背景图像上,并获得与直接在该背景上绘制墨水一样的结果。

然而,对于荧光笔墨水,"blend over background" 是一个更复杂的操作,而不仅仅是标准的 sourceover 混合。因此,不存在仅包含这种墨水的位图图像之类的东西 - 您还必须提供背景才能执行适当的混合。

这里有三个选项:

  1. 不要使用荧光笔墨水模式。
  2. 不要将墨迹保存为位图图像,而是保存原始墨迹笔划数据,然后使用墨迹 API 将这些笔划直接混合到它们的最终位置。
  3. 在同一位图中包括背景和墨迹笔划。

我终于想出了如何让它发挥作用。 我只是在调用 DrawInk 之前添加了一个新层并赋予它不透明度,并去掉了 attributes.DrawAsHighlighter = true;。相反,我专门为荧光笔制作了 1 个不透明度为 0.5 的 inkCanvas,看起来你正在使用荧光笔。

代码如下:

private void SetHighLight()
{
    InkDrawingAttributes attributes = new InkDrawingAttributes();
    attributes.PenTip = PenTipShape.Rectangle;
    attributes.Size = new Size(4, 10);
    attributes.Color = currentColor;
    SetAttribute(attributes);
}

private void GetCanvasRender(out CanvasRenderTarget renderTarget, float opacity)
{
    CanvasDevice device = CanvasDevice.GetSharedDevice();
    renderTarget = new CanvasRenderTarget(device, (int)ink.ActualWidth, (int)ink.ActualHeight, 96);
    using (var ds = renderTarget.CreateDrawingSession())
    {
        ds.Clear(Colors.Transparent);
        using (ds.CreateLayer(opacity))
        {
            ds.DrawInk(ink.InkPresenter.StrokeContainer.GetStrokes());
        }
    }
}

private async void SavePicture(float opacity)
{
    CanvasRenderTarget renderTarget;
    Image img = new Image();

    GetCanvasRender(out renderTarget, opacity);
    StorageFolder storageFolder = ApplicationData.Current.LocalFolder;
    StorageFile noteFile = await storageFolder.CreateFileAsync(i.ToString() + ".png", CreationCollisionOption.ReplaceExisting);
    using (var fileStream = await noteFile.OpenAsync(FileAccessMode.ReadWrite))
        await renderTarget.SaveAsync(fileStream, CanvasBitmapFileFormat.Png, 1f);
    img.Source = new BitmapImage(new Uri(storageFolder.Path + "/" + i++ + ".png"));
    img.VerticalAlignment = VerticalAlignment.Stretch;
    ContainerCanvas.Children.Add(img);
    Canvas.SetTop(img, ScrollViewerContainer.VerticalOffset);
    Canvas.SetZIndex(img, 5);
}