使用自定义背景颜色将带alpha通道的图像复制到剪贴板?

代码:

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

我需要的 :

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

问题:

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

解决方案1:

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

不。这个厚不起作用, canvas的背景在下一个renderBitmap.Render(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 

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

 // 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 { ... } 

我找到了一个更小,更易于阅读的解决方案,我在https://social.msdn.microsoft.com/Forums/vstudio/en-US/a6972b7f-5ccb-422d-b203-134ef9f10084/how-to找到了它。 -capture-whole-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 { ... }