使用不安全的代码更改WriteableBitmap,后台工作程序无法正常工作

时间:2014-03-15 21:04:44

标签: c# wpf

我正在尝试调整我的WPF技能,并决定现在是时候让一个writablebitmap动态加载段(这样用户可以立即看到加载到整个位图的部分内容)

问题是我现在正在编辑后台缓冲区,但是当我调用AddDiryRect时,没有任何反应。

我已经设法正确设置了背景工作者,但我相信我的不安全代码出错了(我第一次使用它时)。

澄清我已经简化了一点,(删除了不相关的字段等)。

首先,我创建了一个能够将指针存储到后备缓冲区的类:

public class BgWorkerMapProperties
{
    public IntPtr pBackBuffer;
    public int Stride;

    public BgWorkerMapProperties(WriteableBitmap wb)
    {
        pBackBuffer = wb.BackBuffer;
        Stride = wb.BackBufferStride;
    }
}

在.xaml.cs类中我有以下内容:

    public WriteableBitmap WorldMap_wb = new WriteableBitmap(256 * 7, 256 * 6, 96, 96, PixelFormats.Bgr32, null);

    BackgroundWorker BgWorkerMap = new BackgroundWorker();
    public BgWorkerMapProperties BgWorker;

    public Page1()
    {
        InitializeComponent();

        BgWorkerMap.WorkerReportsProgress = true;
        BgWorkerMap.DoWork += BgWorkerMap_DoWork_Handler;
        BgWorkerMap.ProgressChanged += BgWorkerMap_ProgressChanged_Handler;

        img_WorldMap.Source = WorldMap_wb;
        WorldMap_wb.Lock();

        BgWorker = new BgWorkerMapProperties(WorldMap_wb);

        BgWorkerMap.RunWorkerAsync(BgWorker);
    }

    private void BgWorkerMap_DoWork_Handler(object sender, DoWorkEventArgs args)
    {
        BackgroundWorker worker = sender as BackgroundWorker;

        while (true)
        {

            BaseBitmap.AddMapFilePixelsToBitmapFromBuffer();

            BgWorker.X = 0;
            BgWorker.Y = 0;
            worker.ReportProgress(0, BgWorker);
            break;
        }
    }

    private void BgWorkerMap_ProgressChanged_Handler(object sender, ProgressChangedEventArgs args)
    {
        WorldMap_wb.AddDirtyRect(new Int32Rect(BgWorker.X, BgWorker.Y, 256, 256));
        WorldMap_wb.Unlock();
        MessageBox.Show("BgWorker breaked, WB is Unlocked");
    }

最后是不安全的代码:

    public static void AddMapFilePixelsToBitmapFromBuffer()
    {
       unsafe
       {
               var backBuffer = (int*)bgWorker.pBackBuffer;
               //Write a mapfile into it´s position
               for (int x = 0; x < 256; x++)
               {
                   for (int y = 0; y < 256; y++)
                   {
                       // Find the address of the pixel to draw.
                       int Bufferindex = x + (y * (bgWorker.Stride / 4));

                           // Compute the pixel's color. 
                           color_data = 255 << 16; // R
                           color_data |= 255 << 8;   // G
                           color_data |= 255 << 0;   // B 
                       }
                       // Assign the color data to the pixel.
                       backBuffer[Bufferindex] = color_data;
                   }
           }
    }

对于任何花时间阅读本文的人来说,我都非常高兴!

感谢WPF爱好者的推进!

1 个答案:

答案 0 :(得分:2)

我相信您的不安全代码正在尝试写入错误的地址。 (X *步幅,Y * 4)? 确保指向backbuffer的指针是您尝试设置的实际数据类型(int?)。 如果您直接使用整数,则不需要执行“* 4”位,因为您的颜色(假设后备缓冲区正确对齐)将对应于一个'int'而不是四个。

另外,我建议直接索引,而不是做“(int )currentBackBuffer” 这是代码的修改版本,我认为应该如何。

public static void AddMapFilePixelsToBitmapFromBuffer()
{
    unsafe
    {
        var backBuffer = (int*)bgWorker.pBackBuffer;
        //Write a mapfile into it´s position
        for (int x = 0; x < 256; x++)
        {
            for (int y = 0; y < 256; y++)
            {
                var index = x + (y * bgWorker.Width); // Assuming there's a width property somewhere, (Otherwise, this should be the same as Stride / 4)
                var pixelColour = GetPixelColour(array[index]);

                // TODO: Find out which value to set.
                // is color_data actually pixelColour?
                // what type is pixelColour?
                // are you working with ARGB, BGRA or RGB?

                backBuffer[index] = pixelColour;
            }
        }
    }
}

请注意,我在那里留下了“TODO:”,因为我不确定你到底想要做什么。

编辑: 适用于我的示例代码: MainWindow(Xaml):http://pastebin.com/rVNzMwWy MainWindow(cs):http://pastebin.com/Qrmqd8kY