Копировать изображение с альфа-каналом в буфер обмена с пользовательским цветом фона?
Код:
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
больше, чем это size...so белый фон может покрыть только часть его, все равно уродливый результат.
(Кстати, кто-нибудь знает, почему требуется время, чтобы изменить фон? Я думал, что это должно быть изменено немедленно)
Я сделал что-то не так? Как я могу получить изображение белого фона ex-transparent в буфере обмена?
Более того, я заметил, что фон некоторых PNG-изображения остаются белыми, если вставить их в mspaint.exe, которые не поддерживают альфа-канал, но некоторые другие становятся черными.
Есть ли что-то вроде, скажем, 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
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 { ... }
Я нашел меньшее и лучшее для чтения решение, я нашел его в 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 { ... }