Обновите WritableBitmap после того, как Image.Source был установлен

Я пытаюсь использовать WritableBitmap сделать некоторые манипуляции на уровне пикселей растровых изображений. Но я не могу заставить его работать. Что я хочу сделать, это манипулировать данными пикселей из WritableBitmap после того, как я назначу Image.Source свойство с моим растровым изображением. Я гуглил, и единственное, что я нашел, это вызов bitmap.Invalidate() метод, но это кажется устаревшим, так как я не мог найти этот метод в WritableBitmap class.following - это код, который я использую для обновления изображения, но не повезло:

    wbitmap.Lock();
    wbitmap.WritePixels(rect, pixels, stride, 0);
    wbitmap.AddDirtyRect(new Int32Rect(0, 0, width, height));
    wbitmap.Unlock();

    //given that i've already assigned image.Source with "wbitmap"
    image.InvalidateVisual();

есть мысли по этому поводу?

РЕДАКТИРОВАТЬ

я был бы признателен за любое предложение для другого способа быстрого чертежа 2D в WPF лучше, чем WritableBitmap,

1 ответ

Решение

В следующем простом примере показано, как непрерывно писать WriteableBitmap, пока он назначается свойству Source элемента управления изображением.

XAML просто так:

<Window ...>
    <Grid>
        <Image x:Name="image"/>
    </Grid>
</Window>

В коде есть таймер, который перезаписывает карту WriteableBitmap десять раз в секунду со значением цвета случайного пикселя. Обратите внимание, что вы должны разрешить небезопасный код в свойствах проекта Visual Studio (на вкладке "Сборка").

В качестве альтернативы Lock/AddDirtyRect/Unlock Вы также можете позвонить writePixels, Тем не менее Lock подход также позволяет другому потоку, не являющемуся пользовательским интерфейсом, записывать в BackBuffer,

public partial class MainWindow : Window
{
    private readonly WriteableBitmap bitmap
        = new WriteableBitmap(100, 100, 96, 96, PixelFormats.Bgr32, null);

    public MainWindow()
    {
        InitializeComponent();
        image.Source = bitmap;

        var timer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(0.1) };
        timer.Tick += OnTimerTick;
        timer.Start();
    }

    private unsafe void OnTimerTick(object sender, EventArgs e)
    {
        int pixelValue = (int)DateTime.Now.Ticks & 0xFFFFFF;

        bitmap.Lock();
        var backBuffer = bitmap.BackBuffer;

        for (int y = 0; y < bitmap.PixelHeight; y++)
        {
            for (int x = 0; x < bitmap.PixelWidth; x++)
            {
                var bufPtr = backBuffer + bitmap.BackBufferStride * y + x * 4;
                *((int*)bufPtr) = pixelValue;
            }
        }

        bitmap.AddDirtyRect(new Int32Rect(0, 0, bitmap.PixelWidth, bitmap.PixelHeight));
        bitmap.Unlock();
    }
}
Другие вопросы по тегам