使用Alpha通道将图像复制到具有自定义背景颜色的剪贴板

Byz*_*zod 5 c# wpf clipboard canvas alpha-transparency

代码:

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);
}
Run Code Online (Sandbox Code Playgroud)

我需要的 :

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

问题:

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

解决方案1:

canvas.Background = new SolidColorBrush(Colors.White);
Run Code Online (Sandbox Code Playgroud)

没有.这厚不起作用,后台canvas不会改变 renderBitmap.Render(canvas);

相反,我必须使用计时器,给WPF一些时间来改变背景,然后在该计时器的tick事件中呈现它.它canvas很有用,但不幸的是,它的内容大于它的大小...所以白色背景只能覆盖它的一部分,仍然是丑陋的结果.(BTW有谁知道为什么需要一段时间来改变背景?我认为它应该立即改变)

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

更重要的是,我注意到如果你把它粘贴到不支持alpha通道的mspaint.exe中,一些PNG图像的背景仍然是白色,但是其他一些变成黑色.

是否有类似的东西,alternative color如果粘贴图像的地方不支持alpha通道,它会用作背景?我们可以定制吗?

现在我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
Run Code Online (Sandbox Code Playgroud)

Byz*_*zod 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(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 { ... }
Run Code Online (Sandbox Code Playgroud)