Вопрос

Есть ли способ получить DrawingContext (или что-то подобное) для WriteableBitmap?Т.е.что-то, что позволит вам позвонить просто DrawLine/DrawRectangle/etc методы, а не напрямую манипулировать необработанными пикселями.

Это было полезно?

Решение 4

Кажется слово нет.


Для дальнейшего использования мы планируем использовать порт Записываемые расширения растровых изображений для ВПФ.

Для решения, использующего чисто существующий код, подойдет любое из других предложений, упомянутых ниже.

Другие советы

Я нашел решение шестибуквенных переменных наиболее работоспособным.Однако отсутствует «drawingContext.Close()».Согласно MSDN, «A DrawingContext должен быть закрыт, прежде чем его содержимое сможет быть отображено».Результатом является следующая функция полезности:

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;
}

Затем это можно легко использовать следующим образом:

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));
    });

Если вы не против использовать System.Drawing вы могли бы сделать что-то вроде:

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();                    

Мне интересно то же самое, поскольку сейчас я делаю что-то вроде:

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;
}

Я пытаюсь использовать WriteableBitmap, чтобы разрешить многопоточный доступ к буферу пикселей, который в настоящее время не разрешен ни для DrawingContext, ни для RenderTargetBitmap.Может быть, подойдет какая-то процедура WritePixels, основанная на том, что вы получили из RenderTargetBitmap?

Другой способ решить эту проблему — использовать RenderTargetBitmap в качестве резервного хранилища, как и в WriteableBitmap пример.Затем вы сможете создавать и выполнять для него команды рисования WPF, когда захотите.Например:

// 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);

Если вы хотите перерисовать это RenderTargetBitmap в каждом кадре вы можете поймать CompositionTarget.Rendering событие, например:

CompositionTarget.Rendering += MyRenderingHandler;
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top