我正在尝试生成基于BitmapFrame
的{{1}}。这是我的功能:
UIElement
出于测试和调试的目的,我使用了一个额外的函数来创建一个简单的StackFrame,应创建一个可以表示的有效视觉元素:
private BitmapFrame RenderToBitmap2()
{
RenderTargetBitmap renderBitmap = new RenderTargetBitmap(200, 200, 96, 96, PixelFormats.Pbgra32);
DrawingVisual drawingVisual = new DrawingVisual();
DrawingContext drawingContext = drawingVisual.RenderOpen();
VisualBrush aVisualBrush = new VisualBrush(GenerateTestStackPanel());
drawingContext.DrawRectangle(aVisualBrush, new Pen(Brushes.Green, 2), new Rect(new Size(150, 150)));
drawingContext.Close();
renderBitmap.Render(drawingVisual);
return BitmapFrame.Create(renderBitmap);
}
由于某种原因,VisualBrush没有在DrawRetangle(...)函数中呈现。我可以看到绿色边框,但没有别的。另外,如果我用标准画笔换掉VisualBrush,它的效果很好:
private StackPanel GenerateTestStackPanel()
{
// Create a red Ellipse.
Ellipse myEllipse = new Ellipse();
myEllipse.Fill = Brushes.Green;
myEllipse.StrokeThickness = 2;
myEllipse.Stroke = Brushes.Black;
// Set the width and height of the Ellipse.
myEllipse.Width = 200;
myEllipse.Height = 200;
// Add the Ellipse to the StackPanel.
StackPanel myStackPanel = new StackPanel();
myStackPanel.Children.Add(myEllipse);
return myStackPanel;
}
提前致谢!
答案 0 :(得分:4)
请查看此处,了解从BitmapSource
创建UIElement
的替代方法:
我也一直试图让VisualBrush在没有任何运气的情况下工作,这让我进入了这个主题。
public static BitmapSource CreateBitmapSourceFromVisual(
Double width,
Double height,
Visual visualToRender,
Boolean undoTransformation)
{
if (visualToRender == null)
{
return null;
}
RenderTargetBitmap bmp = new RenderTargetBitmap((Int32)Math.Ceiling(width),
(Int32)Math.Ceiling(height), 96, 96, PixelFormats.Pbgra32);
if (undoTransformation)
{
DrawingVisual dv = new DrawingVisual();
using (DrawingContext dc = dv.RenderOpen())
{
VisualBrush vb = new VisualBrush(visualToRender);
dc.DrawRectangle(vb, null, new Rect(new Point(), new Size(width, height)));
}
bmp.Render(dv);
}
else
{
bmp.Render(visualToRender);
}
return bmp;
}
答案 1 :(得分:3)
之前我有同样的问题,我想将UIElement
的内容复制到图像中,我在上面的答案中使用了相同的方法,它似乎工作正常,只有我遇到的问题,我想要它为了实时工作,所以我不得不深入挖掘,我发现了一些关于使用Windows API将元素的内容复制到Bitmap的引用,然后这个位图必须转换为BitmapSource
所以它可以使用在WPF中
到目前为止它工作正常,但它似乎泄漏内存(不确定这一点)。我将尝试重用UIElement
hwnd Handle和位图对象以获得更好的性能和内存泄漏(如果存在)
[DllImport("gdi32.dll")]
private static extern bool BitBlt(
IntPtr hdcDest, // handle to destination DC
int nXDest, // x-coord of destination upper-left corner
int nYDest, // y-coord of destination upper-left corner
int nWidth, // width of destination rectangle
int nHeight, // height of destination rectangle
IntPtr hdcSrc, // handle to source DC
int nXSrc, // x-coordinate of source upper-left corner
int nYSrc, // y-coordinate of source upper-left corner
System.Int32 dwRop // raster operation code
);
[DllImport("User32.dll")]
public extern static System.IntPtr GetDC(System.IntPtr hWnd);
[DllImport("User32.dll")]
public extern static int ReleaseDC(System.IntPtr hWnd, System.IntPtr hDC); //modified to include hWnd
//[DllImport("gdi32.dll")]
//[return: MarshalAs(UnmanagedType.Bool)]
//internal static extern bool DeleteObject(IntPtr hObject);
private static Bitmap GetBitmapFromControl(Window element, int width, int height)
{
HwndSource hWnd = (HwndSource)HwndSource.FromVisual(element);
System.IntPtr srcDC = GetDC(hWnd.Handle);
Bitmap bm = new Bitmap(width, height);
Graphics g = Graphics.FromImage(bm);
System.IntPtr bmDC = g.GetHdc();
BitBlt(bmDC, 0, 0, bm.Width, bm.Height, srcDC, 0, 0, 0x00CC0020 /*SRCCOPY*/);
ReleaseDC(hWnd.Handle, srcDC);
g.ReleaseHdc(bmDC);
g.Dispose();
return bm;
}
public static BitmapSource ToWpfBitmap(this Bitmap bitmap)
{
using (MemoryStream stream = new MemoryStream())
{
bitmap.Save(stream, ImageFormat.Bmp);
stream.Position = 0;
BitmapImage result = new BitmapImage();
result.BeginInit();
// According to MSDN, "The default OnDemand cache option retains access to the stream until the image is needed."
// Force the bitmap to load right now so we can dispose the stream.
result.CacheOption = BitmapCacheOption.OnLoad;
result.StreamSource = stream;
result.EndInit();
result.Freeze();
//DeleteObject(bitmap.GetHbitmap());
bitmap.Dispose();
return result;
}
}