感谢上面接受的答案,因为它引导我找到解决方案,但这实际上使要求过于复杂。具体来说,您无需创建DrawingVisual 即可传递给Render 调用。您可以直接传递视图,因为它已经是 Visual,Render 调用接受它。
这是一个简化版本,我还在FrameworkElement 上更改为扩展方法,因此您可以通过任何控件轻松使用它。
注意:虽然Render 接受Visual,但您不能扩展Visual,因为您需要实际的宽度和高度来创建RenderTargetBitmap,但出于同样的原因,您可能已经无论如何使用FrameworkElement。
public static RenderTargetBitmap? CopyAsBitmap(this FrameworkElement frameworkElement) {
var targetWidth = (int)frameworkElement.ActualWidth;
var targetHeight = (int)frameworkElement.ActualHeight;
// Exit if there's no 'area' to render
if (targetWidth == 0 || targetHeight == 0)
return null;
// Prepare the rendering target
var result = new RenderTargetBitmap(targetWidth, targetHeight, 96, 96, PixelFormats.Pbgra32);
// Render the framework element into the target
result.Render(frameworkElement);
return result;
}
然后我有第二个扩展方法,它接受任何BitmapSource(RenderTargetBitmap 是其子类)并根据提供的编码器返回字节。
public static byte[] Encode(this BitmapSource bitmapSource, BitmapEncoder bitmapEncoder){
// Create a 'frame' for the BitmapSource, then add it to the encoder
var bitmapFrame = BitmapFrame.Create(bitmapSource);
bitmapEncoder.Frames.Add(bitmapFrame);
// Prepare a memory stream to receive the encoded data, then 'save' into it
var memoryStream = new MemoryStream();
bitmapEncoder.Save(memoryStream);
// Return the results of the stream as a byte array
return memoryStream.ToArray();
}
这就是你如何一起使用它。此代码将任何 FrameworkElement 呈现为 PNG:
var renderTargetBitmap = someFrameworkElement.CopyAsBitmap();
var pngData = renderTargetBitmap.Encode(new PngBitmapEncoder());
File.WriteAllBytes(@"C:\Users\SomeUser\Desktop\TestOutput.png", pngData);
或者更简洁...
var pngData = someFrameworkElement.CopyAsBitmap().Encode(new PngBitmapEncoder());
File.WriteAllBytes(@"C:\Users\SomeUser\Desktop\TestOutput.png", pngData);
要改为将其呈现为 JPG,只需更改编码器,就像这样...
var jpegData = someFrameworkElement.CopyAsBitmap().Encode(new JpegBitmapEncoder());
File.WriteAllBytes(@"C:\Users\SomeUser\Desktop\TestOutput.jpg", jpegData);
此外,由于RenderTargetBitmap 最终是ImageSource(通过BitmapSource),您也可以直接将其设置为Image 控件的Source 属性,就像这样...
someImage.Source = someFrameworkElement.CopyAsBitmap();