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 a canvas with transparent background to image, then copy it to clipboard (Quit simple? Not really)
Problem :
When paste, I get a ugly image with black background
Solution 1 :
canvas.Background = new SolidColorBrush(Colors.White);
No. This thick do not work, the background of canvas
will not change in the next renderBitmap.Render(canvas);
Instead, I have to use a timer, give WPF some time to change the background, then render it in the tick event of that timer. It works, but unfortunately, the content of canvas
is larger than it's size...so the white background can only cover part of it, still ugly result.
(BTW anyone know why it takes sometime to change the background? I thought it should be changed instantly)
Did I do something wrong? How can I get a white background ex-transparent image in clipboard?
What's more, I've noticed that the background of some PNG images remain white if you paste it into mspaint.exe which do not support alpha channel, but some others become black.
Is there something like, say, alternative color
, which is used as background if the place where you paste your image do not support alpha channel? Can we custom it?
Now I rendered another BitmapSource
with white content, if there is a way to combine it with the renderBitmap as background, the problem solved, but I don't 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
Here's my last solution, hope it would help 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 { ... }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With