Uielement에서 Bitmapsource를 생성합니다
문제
나는 a를 생성하려고한다 BitmapFrame
그것은 a UIElement
. 내 기능은 다음과 같습니다.
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);
}
테스트 및 디버깅 목적으로 간단한 스택 프레임을 만드는 추가 기능을 사용하고 있습니다. ~해야 한다 표현할 수있는 유효한 시각적 요소를 만듭니다.
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;
}
어떤 이유로, VisualBrush는 DrawRetangle (...) 함수로 렌더링되지 않습니다. 나는 녹색 경계를 볼 수 있지만 다른 것은 없습니다. 또한 표준 브러시로 VisualBrush를 교체하면 훌륭하게 작동합니다.
drawingContext.DrawRectangle(Brushes.Plum, new Pen(Brushes.Green, 2), new Rect(new Size(150, 150)));
미리 감사드립니다!
해결책
대체 방법을 위해 이것을 살펴보십시오. BitmapSource
a UIElement
:
나는 또한이 스레드에 나를 데려온 운이없는 비주얼 브러쉬가 작동하도록 노력하고 있습니다.
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;
}
다른 팁
전에 같은 문제가 있었는데 UIElement
이미지에 위의 답변에서 동일한 접근 방식을 사용했는데 잘 작동하는 것 같습니다. 문제 만있는 것만으로도 실시간으로 작동하기를 원했기 때문에 더 깊이 파고 들었습니다. 요소의 내용을 비트 맵으로 복사 한 다음이 비트 맵을 BitmapSource
따라서 WPF에서는 사용할 수 있습니다
지금까지는 잘 작동하지만 메모리가 새는 것 같습니다 (확실하지 않음). 나는 재사용하려고 노력할 것이다 UIElement
더 나은 성능 및 메모리 누출을위한 HWND 핸들 및 비트 맵 객체 (존재하는 경우)
[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;
}
}
제휴하지 않습니다 StackOverflow