赞扬上面的答案,让我找到了解决方案的路径,但实际上这过于复杂化了需求。具体来说,您不需要创建一个
DrawingVisual
传递给
Render
调用。因为视图已经是一个
Visual
,而
Render
调用接受
Visual
,所以您可以直接传递视图。
下面是一个简化版本,我还将其改成了
FrameworkElement
的扩展方法,这样您就可以轻松地在任何控件中使用它。
注意:虽然 Render
接受 Visual
,但您不能扩展 Visual
,因为您需要实际的宽度和高度来创建 RenderTargetBitmap
,但出于同样的原因,您可能已经在使用 FrameworkElement
。
public static RenderTargetBitmap? CopyAsBitmap(this FrameworkElement frameworkElement) {
var targetWidth = (int)frameworkElement.ActualWidth;
var targetHeight = (int)frameworkElement.ActualHeight;
if (targetWidth == 0 || targetHeight == 0)
return null;
var result = new RenderTargetBitmap(targetWidth, targetHeight, 96, 96, PixelFormats.Pbgra32);
result.Render(frameworkElement);
return result;
}
我有第二个扩展方法,它接受任何
BitmapSource
(其中包括
RenderTargetBitmap
),并根据提供的编码器返回字节。
public static byte[] Encode(this BitmapSource bitmapSource, BitmapEncoder bitmapEncoder){
var bitmapFrame = BitmapFrame.Create(bitmapSource);
bitmapEncoder.Frames.Add(bitmapFrame);
var memoryStream = new MemoryStream();
bitmapEncoder.Save(memoryStream);
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
最终是通过
BitmapSource
成为
ImageSource
,因此您也可以直接将其设置为
Image
控件的
Source
属性,如下所示...
someImage.Source = someFrameworkElement.CopyAsBitmap();