Обновите 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();
}
}