【问题标题】:Copy image with alpha channel to clipboard with custom background color?将带有 alpha 通道的图像复制到带有自定义背景颜色的剪贴板?
【发布时间】:2016-05-10 18:47:45
【问题描述】:

代码:

private void Foo(Canvas canvas)
{
    // The content is a bit larger...
    Size size = new Size(canvas.ActualWidth * 1.1, canvas.ActualHeight * 1.2);

    // Create a render bitmap and push the surface to it
    RenderTargetBitmap renderBitmap =
        new RenderTargetBitmap(
        (int)size.Width,
        (int)size.Height,
        96d,
        96d,
        PixelFormats.Pbgra32
    );
    renderBitmap.Render(canvas);

    // Then copy to clipboard
    Clipboard.SetImage(renderBitmap);
}

我需要什么:

将具有透明背景的画布渲染为图像,然后将其复制到剪贴板(简单吗?不是真的)

问题:

粘贴时,我得到一个带有黑色背景的丑陋图像

解决方案 1:

canvas.Background = new SolidColorBrush(Colors.White);

没有。这个粗的不行,canvas的背景在下一个renderBitmap.Render(canvas);不会变

相反,我必须使用计时器,给 WPF 一些时间来更改背景,然后在该计时器的滴答事件中渲染它。它可以工作,但不幸的是,canvas 的内容大于它的大小......所以白色背景只能覆盖它的一部分,仍然是丑陋的结果。 (顺便说一句,有人知道为什么要花一些时间来更改背景吗?我认为应该立即更改)

我做错了吗?如何在剪贴板中获得白色背景的透明图像?

另外,我发现有些PNG图片如果粘贴到不支持alpha通道的mspaint.exe中,背景仍然是白色的,而有些则变成黑色。

如果您粘贴图像的位置不支持 Alpha 通道,是否有类似 alternative color 之类的东西用作背景?我们可以定制吗?

现在我用白色内容渲染了另一个BitmapSource,如果有办法将它与作为背景的renderBitmap结合起来,问题就解决了,但我不知道如何......

int dWidth = (int)size.Width;
int dHeight = (int)size.Height;
int dStride = dWidth * 4;
byte[] pixels = new byte[dHeight * dStride];
for (int i = 0; i < pixels.Length; i++)
{
    pixels[i] = 0xFF;
}
BitmapSource bg = BitmapSource.Create(
    dWidth,
    dHeight,
    96,
    96,
    PixelFormats.Pbgra32,
    null,
    pixels,
    dStride
);
// Combine bg with renderBitmap

【问题讨论】:

  • 在移除 alpha 通道而不是所有通道后,它似乎保存了位图。剪贴板上的图像是 MS BMP 吗?
  • @ColeJohnson 我不知道。正如我搜索的结果,似乎 MS 剪贴板图像不支持透明通道。我正在尝试找到一种方法,在将此图像设置为剪贴板之前为其添加白色背景
  • 您始终可以对其进行 base64 编码,并在另一端对其进行 base64 解码。但这可能会破坏兼容性。对于有图片的应用,我不知道他们是怎么做到的:(
  • 谢谢@ColeJohnson,我渲染了一个相同大小的白色BitmapSource图像,正在寻找与原始画布结合的方法,希望对您有所帮助

标签: c# wpf canvas clipboard alpha-transparency


【解决方案1】:

这是我的最后一个解决方案,希望它可以帮助其他有同样问题的人

// Create a render bitmap and push the surface to it
RenderTargetBitmap renderBitmap =
    new RenderTargetBitmap(
    (int)size.Width,
    (int)size.Height,
    96d,
    96d,
    PixelFormats.Pbgra32
);
renderBitmap.Render(surface);

// Create a white background render bitmap
int dWidth = (int)size.Width;
int dHeight = (int)size.Height;
int dStride = dWidth * 4;
byte[] pixels = new byte[dHeight * dStride];
for (int i = 0; i < pixels.Length; i++)
{
    pixels[i] = 0xFF;
}
BitmapSource bg = BitmapSource.Create(
    dWidth,
    dHeight,
    96,
    96,
    PixelFormats.Pbgra32,
    null,
    pixels,
    dStride
);

// Adding those two render bitmap to the same drawing visual
DrawingVisual dv = new DrawingVisual();
DrawingContext dc = dv.RenderOpen();
dc.DrawImage(bg, new Rect(size));
dc.DrawImage(renderBitmap, new Rect(size));
dc.Close();

// Render the result
RenderTargetBitmap resultBitmap =
    new RenderTargetBitmap(
    (int)size.Width,
    (int)size.Height,
    96d,
    96d,
    PixelFormats.Pbgra32
);
resultBitmap.Render(dv);

// Copy it to clipboard
try
{
    Clipboard.SetImage(resultBitmap);
} catch { ... }

【讨论】:

    【解决方案2】:

    我找到了一个更小更易读的解决方案,我在https://social.msdn.microsoft.com/Forums/vstudio/en-US/a6972b7f-5ccb-422d-b203-134ef9f10084/how-to-capture-entire-usercontrol-image-to-clipboard?forum=wpf 找到了它:

    // Create a render bitmap and push the surface to it
    RenderTargetBitmap renderBitmap =
        new RenderTargetBitmap(
        (int)size.Width,
        (int)size.Height,
        96d,
        96d,
        PixelFormats.Pbgra32
    );
    
    // Render a white background into buffer for clipboard to avoid black background on some elements
    Rectangle vRect = new Rectangle()
    {
        Width = (int)size.Width,
        Height = (int)size.Height,
        Fill = Brushes.White,
    };
    vRect.Arrange(new Rect(size));
    renderBitmap.Render(vRect);
    
    // renderBitmap is now white, so render your object on it
    renderBitmap.Render(surface);
    
    // Copy it to clipboard
    try
    {
        Clipboard.SetImage(resultBitmap);
    } catch { ... }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-09-27
      • 1970-01-01
      • 2020-08-18
      • 1970-01-01
      • 2019-02-18
      • 1970-01-01
      • 2013-03-19
      • 2010-10-28
      相关资源
      最近更新 更多