Reputation: 3030
I'm drawing on the backuffer of a writeablebitmap, and the applying it to the image but the image is not updating for some reason.
I've checked in the memory and the backbuffer values are changed, but setting the source of the image to the writeablebitmap doesn't change anything. The screen stays black.
Here is my program:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Threading;
namespace RayTracer
{
class Main : Application
{
Window mainWindow;
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
CreateAndShowMainWindow();
}
public void CreateAndShowMainWindow()
{
mainWindow = new Window();
mainWindow.Title = "Writeable Bitmap";
mainWindow.Height = 480;
mainWindow.Width = 640;
mainWindow.ResizeMode = ResizeMode.NoResize;
mImage = new Image();
mWriteableBitmap = new WriteableBitmap(640, 480, 96, 96, PixelFormats.Rgb24, null);
mImage.Stretch = Stretch.None;
mImage.Margin = new Thickness(0);
mBytesPerPixel = (mWriteableBitmap.Format.BitsPerPixel + 7) / 8;
mStride = mWriteableBitmap.PixelWidth * mBytesPerPixel;
StackPanel myStackPanel = new StackPanel();
myStackPanel.Orientation = Orientation.Vertical;
myStackPanel.Height = 480;
myStackPanel.VerticalAlignment = VerticalAlignment.Top;
myStackPanel.HorizontalAlignment = HorizontalAlignment.Left;
myStackPanel.Children.Add(mImage);
mainWindow.Content = myStackPanel;
mainWindow.Show();
DispatcherTimer dispatcherTimer = new DispatcherTimer();
dispatcherTimer.Tick += new EventHandler(dispatcherTimer_Tick);
dispatcherTimer.IsEnabled = true;
dispatcherTimer.Interval = new TimeSpan(0, 0, 1);
dispatcherTimer.Start();
}
private void dispatcherTimer_Tick(object sender, EventArgs e)
{
for (int i = 0; i < 480; i++)
{
for (int j = 0; j < 640; j++)
{
setPixel(j, i, Color.FromRgb(255, 255, 255));
}
}
mImage.Source = mWriteableBitmap; // image should be white but stays black
}
private Image mImage = null;
private WriteableBitmap mWriteableBitmap = null;
private int mBytesPerPixel = 0;
private int mStride = 0;
void setPixel(int x, int y, Color c)
{
int posX = x * mBytesPerPixel;
int posY = y * mStride;
unsafe
{
byte* backBuffer = (byte*)mWriteableBitmap.BackBuffer;
backBuffer[posY + posX] = c.R;
backBuffer[posY + posX + 1] = c.G;
backBuffer[posY + posX + 2] = c.B;
}
}
void clearScreen()
{
int totalBytes = mStride * 480;
unsafe
{
byte* backBuffer = (byte*)mWriteableBitmap.BackBuffer;
for (int i = 0; i < totalBytes; i++)
{
backBuffer[i] = 255;
}
}
}
}
internal static class EntryClass
{
[System.STAThread()]
private static void Main()
{
Main app = new Main();
app.Run();
}
}
}
Upvotes: 0
Views: 2062
Reputation: 128136
From the Remarks on the BackBuffer
MSDN page:
Update the back buffer only between calls to the Lock and Unlock methods. If you do not follow the Lock/Unlock workflow described in the WriteableBitmap class remarks, undefined behaviors, such as tearing, can occur.
So your Tick handler should look like this:
private void dispatcherTimer_Tick(object sender, EventArgs e)
{
mWriteableBitmap.Lock();
for (int i = 0; i < 480; i++)
{
for (int j = 0; j < 640; j++)
{
setPixel(j, i, Color.FromRgb(255, 255, 255));
}
}
mWriteableBitmap.AddDirtyRect(new Int32Rect(0, 0,
mWriteableBitmap.PixelWidth, mWriteableBitmap.PixelHeight));
mWriteableBitmap.Unlock();
mImage.Source = mWriteableBitmap; // image is white now
}
Upvotes: 2