Có cách nào để có được một DrawingContext
(hoặc một cái gì đó tương tự) cho một WriteableBitmap
? I E. một cái gì đó để cho phép bạn gọi đơn giản DrawLine
/DrawRectangle
/etc các loại phương pháp, thay vì thao tác các pixel nguyên trực tiếp.Nhận một DrawingContext cho một wpf WriteableBitmap
Trả lời
Nó xuất hiện the word is no.
Để tham khảo trong tương lai, chúng tôi dự định sử dụng cổng của Writeable Bitmap Extensions cho WPF.
Để có giải pháp sử dụng mã hoàn toàn hiện tại, bất kỳ đề xuất nào khác được đề cập bên dưới sẽ hoạt động.
Tôi đang tự hỏi điều tương tự, như hiện nay tôi làm điều gì đó như:
DrawingVisual drawingVisual = new DrawingVisual();
using (DrawingContext drawingContext = drawingVisual.RenderOpen())
{
//
// ... draw on the drawingContext
//
RenderTargetBitmap bmp = new RenderTargetBitmap(width, height, dpi, dpi, PixelFormats.Default);
bmp.Render(drawingVisual);
image.Source = bmp;
}
Tôi đang cố gắng sử dụng WriteableBitmap cho phép truy cập đa luồng để bộ đệm pixel, mà hiện chưa được cho phép với không một DrawingContext cũng như một RenderTargetBitmap. Có lẽ một số loại thói quen WritePixels dựa trên những gì bạn đã lấy từ RenderTargetBitmap sẽ hoạt động?
Nếu bạn không nhớ sử dụng System.Drawing
bạn có thể làm một cái gì đó như:
var wb = new WriteableBitmap(width, height, dpi, dpi,
PixelFormats.Pbgra32, null);
wb.Lock();
var bmp = new System.Drawing.Bitmap(wb.PixelWidth, wb.PixelHeight,
wb.BackBufferStride,
PixelFormat.Format32bppPArgb,
wb.BackBuffer);
Graphics g = System.Drawing.Graphics.FromImage(bmp); // Good old Graphics
g.DrawLine(...); // etc...
// ...and finally:
g.Dispose();
bmp.Dispose();
wb.AddDirtyRect(...);
wb.Unlock();
Tôi đã không có cơ hội để dùng thử chỉ là, nhưng điều này có vẻ như một cách giải quyết rất hợp lý trong WPF. Cảm ơn! –
Chỉ trong trường hợp bất cứ ai đang tự hỏi, tôi đã thử nghiệm phương pháp DrawingVisual WPF được đề cập trong chủ đề này và phương pháp System.Drawing này, và phương pháp System.Drawing này là MUCH FASTER. Tôi rất thất vọng trong WPF. – Verax
Bạn có thể làm điều tương tự với WPF, với hiệu suất tương tự (hoặc tốt hơn?) Bằng cách sử dụng RenderTargetBitmap và DrawingVisual/DrawingContext –
tôi tìm thấy giải pháp sixlettervariables' một hoàn toàn khả thi nhất. Tuy nhiên, có một "drawingContext.Close()" bị thiếu. Theo MSDN, "Bản vẽ phải được đóng trước khi nội dung của nó có thể được hiển thị". Kết quả là hàm sau tiện ích:
public static BitmapSource CreateBitmap(
int width, int height, double dpi, Action<DrawingContext> render)
{
DrawingVisual drawingVisual = new DrawingVisual();
using (DrawingContext drawingContext = drawingVisual.RenderOpen())
{
render(drawingContext);
}
RenderTargetBitmap bitmap = new RenderTargetBitmap(
width, height, dpi, dpi, PixelFormats.Default);
bitmap.Render(drawingVisual);
return bitmap;
}
này sau đó có thể dễ dàng được sử dụng như thế này:
BitmapSource image = ImageTools.CreateBitmap(
320, 240, 96,
drawingContext =>
{
drawingContext.DrawRectangle(
Brushes.Green, null, new Rect(50, 50, 200, 100));
drawingContext.DrawLine(
new Pen(Brushes.White, 2), new Point(0, 0), new Point(320, 240));
});
'.Close()' là ẩn trong '.Dispose()' - toàn bộ điểm phía sau câu lệnh 'using'. Nếu bạn để lại * chỉ * lệnh 'render (...)' bên trong khối sử dụng, bạn sẽ ổn và không cần bất kỳ '.Close()'. –
Cảm ơn Eamon. Tôi đã sửa lỗi trong mã. –
Không có 'WriteableBitmap' trong câu trả lời này, tại sao nó lại là một trong số hàng đầu? :) Nó hoàn toàn không liên quan đến câu hỏi. –
Một cách khác nhau để giải quyết vấn đề này là sử dụng một RenderTargetBitmap
như một cửa hàng ủng hộ, chỉ cần như trong ví dụ WriteableBitmap
. Sau đó, bạn có thể tạo và phát hành các lệnh vẽ WPF cho nó bất cứ khi nào bạn muốn. Ví dụ:
// create the backing store in a constructor
var backingStore =
new RenderTargetBitmap(200,200,97,97,PixelFormats.Pbgra32);
myImage.Source = backingStore;
// whenever you want to update the bitmap, do:
var drawingVisual = new DrawingVisual();
var drawingContext = drawingVisual.RenderOpen();
{
// your drawing commands go here
drawingContext.DrawRectangle(
Brushes.Red, new Pen(),
new Rect(this.RenderSize));
}
Render(drawingContext);
drawingContext.Close();
backingStore.Render(drawingVisual);
Nếu bạn muốn vẽ lại RenderTargetBitmap
này mỗi khung hình, bạn có thể nắm bắt những sự kiện CompositionTarget.Rendering
, như thế này:
CompositionTarget.Rendering += MyRenderingHandler;
Đó không phải là từ chính thức. Đó chỉ là một số người nói điều gì đó trên diễn đàn. –
Điểm chụp; văn bản cập nhật. Tôi cho rằng bạn có thể nói nó có nghĩa là "chính thức" như trong "đăng lên một diễn đàn được giám sát bởi các quan chức, và không được sửa chữa bởi họ", nhưng đó là một chút căng ra :) –