Copy image with alpha to clipboard with custom background color?

The code:

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

What I need:

Render canvas with a transparent background for the image, then copy it to the clipboard (Quit simple? Not really)

Problem:

When pasting, I get an ugly image with a black background

Solution 1:

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

Not. This thick one doesn't work, the canvas background will not change in the next renderBitmap.Render(canvas);

Instead, I should use a timer, give WPF some time to change the background, and then display it in the tick event of this timer. It works, but unfortunately the contents of the canvas larger than its size ... so that a white background can cover only part of it, yet an ugly result. (By the way, does anyone know why it takes some time to change the background? I thought it needed to be changed immediately)

Did I do something wrong? How can I get a white background ex-transparent image on the clipboard?

What's more, I noticed that the background of some PNG images remains white if you paste it into the mspaint.exe file, which does not support the alpha channel, and some others turn black.

Is there something like, say, alternative color that is used as the background if the place where you insert the image does not support the alpha channel? Can we do this?

Now I have displayed another BitmapSource with white content, if there is a way to combine it with renderBitmap as a background, the problem is solved, but I do not know how ...

 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 
+4
source share
2 answers

Here is my last solution, hope this helps others with the same problem

 // 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
source

I found a smaller and better readable solution, I found it at 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 { ... } 
0
source

Source: https://habr.com/ru/post/1414724/


All Articles