2008-09-17 2 views
19

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

ответ

4

Появляется the word is no.


На будущее, мы планируем использовать порт Writeable Bitmap Extensions для WPF.

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

+0

Это не официальное слово. Это просто какой-то парень, который что-то говорит на форуме. – 2012-01-03 12:22:59

+0

Полученный пункт; обновленный текст. Полагаю, вы могли бы сказать, что это означало «официальный», как в «размещенном на форуме, контролируемом чиновниками, и не исправляемом ими», но это немного растягивается :) – 2012-01-04 13:44:41

5

Я интересно то же самое, как и в настоящее время я делаю что-то вроде:

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, будет работать?

+0

Рендер слишком долго – lindexi 2017-06-19 09:26:01

+0

Вы не можете написать bmp.Render в использовании которые не могут получить drawingVisual. – lindexi 2017-06-19 09:29:21

15

Если вы не возражаете против использования 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();      
19

Я нашел решение sixlettervariables' наиболее работоспособной один. Однако отсутствует «drawContext.Close()». Согласно MSDN, «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)); 
    }); 
1

Другой способ решения этой проблемы заключается в использовании 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; 
Смежные вопросы