WriteableBitmap Backbuffer不适用于图像

时间:2014-03-14 18:36:50

标签: c# wpf bitmap

我正在使用writeablebitmap的后备,并将其应用于图像,但图像由于某种原因没有更新。

我已经检查了内存并且后备缓冲区值已更改,但是将图像源设置为writeablebitmap不会改变任何内容。屏幕保持黑色。

这是我的计划:

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

1 个答案:

答案 0 :(得分:2)

来自BackBuffer MSDN页面上的备注:

  

仅在对Lock和Unlock的调用之间更新后台缓冲区   方法。如果您不遵循中所述的锁定/解锁工作流程   WriteableBitmap类备注,未定义的行为,如   撕裂,可能会发生。

所以你的Tick处理程序应如下所示:

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
}