我有searched并了解如何使用BmpBitmapEncoder
在WPF中保存图像。我的程序有一个MVVM视图,我想保存为图像。是否可以将其设置为BitmapFrame
,以便对其进行编码?如果是的话,是否有在线教程?
下面列出了我要保存的视图。
<Grid>
<view:OverallView Grid.Row="1"
Visibility="{Binding IsOverallVisible,Converter={StaticResource B2VConv}}"
/>
</Grid>
OverallView
是用户控件。
如果无法将视图设置为BitmapFrame
,可以将哪些wpf元素设置为BitmapSource/Frame
?
答案 0 :(得分:19)
您可以将其作为RenderTargetBitmap返回:
public static RenderTargetBitmap GetImage(OverallView view)
{
Size size = new Size(view.ActualWidth, view.ActualHeight);
if (size.IsEmpty)
return null;
RenderTargetBitmap result = new RenderTargetBitmap((int)size.Width, (int)size.Height, 96, 96, PixelFormats.Pbgra32);
DrawingVisual drawingvisual = new DrawingVisual();
using (DrawingContext context = drawingvisual.RenderOpen())
{
context.DrawRectangle(new VisualBrush(view), null, new Rect(new Point(), size));
context.Close();
}
result.Render(drawingvisual);
return result;
}
之后,您可以使用PngBitmapEncoder将其保存为PNG并将其保存为流,例如:
public static void SaveAsPng(RenderTargetBitmap src, Stream outputStream)
{
PngBitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(src));
encoder.Save(outputStream);
}
FIX:bitmap =&gt;结果
答案 1 :(得分:0)
对上面已接受的答案表示敬意,因为它使我走上了解决之路,但这实际上使要求变得过于复杂。具体来说,您无需创建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
),因此您也可以直接将其设置为Source
控件的Image
属性,就像这样...
someImage.Source = someFrameworkElement.CopyAsBitmap();