WPF中的位图绘制



我有一些在C#中编写的小型Winforms应用程序,该应用程序利用System.Drawing.BitmapSystem.Windows.Forms.PictureBox在应用程序随着时间的时间维护的原始字节缓冲区显示一个位图。从某种意义上说,这类似于穷人的动画。

我想将这些应用程序移植到WPF,但是在字节缓冲区写作中有很多自定义逻辑,我不愿意更改。谷歌搜索后,我尝试使用System.Windows.Media.Imaging.WriteableBitmap类,但无法使其正常工作。该类应该如何使用,并且与我的原始设计适合吗?

这是来自原始Winforms应用程序的摘要,该应用程序将随机颜色累积地写入位图上的随机位置:

private void Form1_Load(object sender, EventArgs e)
{
    _timer.Tick += new EventHandler(Timer_Tick);
    _timer.Interval = 25;
    _timer.Enabled = true;
}
private void Timer_Tick(object sender, EventArgs e)
{
    Animate();
}
private void Animate()
{
    Bitmap bitmap = (Bitmap)pictureBox1.Image;
    if (bitmap != null)
    {
        bitmap.Dispose();
    }
    bitmap = new Bitmap(pictureBox1.Width, pictureBox1.Height);
    var data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
    if (_buffer == null)
    {
        _buffer = new byte[data.Stride * bitmap.Height];
    }
    for (int i = 0; i < 1000; i++)
    {
        var x = _random.Next(bitmap.Width);
        var y = _random.Next(bitmap.Height);
        var red = (byte)_random.Next(byte.MaxValue);
        var green = (byte)_random.Next(byte.MaxValue);
        var blue = (byte)_random.Next(byte.MaxValue);
        var alpha = (byte)_random.Next(byte.MaxValue);
        _buffer[y * data.Stride + x * 4] = blue;
        _buffer[y * data.Stride + x * 4 + 1] = green;
        _buffer[y * data.Stride + x * 4 + 2] = red;
        _buffer[y * data.Stride + x * 4 + 3] = alpha;
    }
    Marshal.Copy(_buffer, 0, data.Scan0, _buffer.Length);
    bitmap.UnlockBits(data);
    pictureBox1.Image = bitmap;
}

如果您已经有现有代码,我认为可能最简单,最快(虽然处理最快)是维护您的代码并在需要显示图像时转换为bitmapsource:

  BitmapImage bmpImage = new BitmapImage();
  MemoryStream stream = new MemoryStream();
  bitmap.Save(stream, ImageFormat.MemoryBmp);
  bmpImage.BeginInit();
  bmpImage.StreamSource = stream;
  bmpImage.EndInit();
  bmpImage.Freeze();
  return bmpImage;

另一种选择会更有效,但可能需要您移植更多代码,就是使用WritableBitMap。您可以以与位图对象相同的方式创建WritableBitMap,并且可以访问其RAW Backing Buffer(和INTPTR),并且可以根据需要操纵图像数据。此链接应为您提供有关WritableBitMap所需的所有信息:WritablebitMap

这是您案件的示例(请注意,您需要了解您的DPI):

      WriteableBitmap bitmap = new WriteableBitmap(pictureBox1.Width, pictureBox1.Height, dpi, dpi, PixelFormats.Bgra32, null);
  if (_buffer == null)
  {
    _buffer = new byte[bitmap.BackBufferStride * pictureBox1.Height];
  }
  for (int i = 0; i < 1000; i++)
  {
    var x = _random.Next(bitmap.Width);
    var y = _random.Next(bitmap.Height);
    var red = (byte)_random.Next(byte.MaxValue);
    var green = (byte)_random.Next(byte.MaxValue);
    var blue = (byte)_random.Next(byte.MaxValue);
    var alpha = (byte)_random.Next(byte.MaxValue);
    _buffer[y * bitmap.BackBufferStride + x * 4] = blue;
    _buffer[y * bitmap.BackBufferStride + x * 4 + 1] = green;
    _buffer[y * bitmap.BackBufferStride + x * 4 + 2] = red;
    _buffer[y * bitmap.BackBufferStride + x * 4 + 3] = alpha;
  }
  bitmap.WritePixels(new System.Windows.Int32Rect(0, 0, bitmap.PixelWidth, bitmap.PixelHeight),
      _buffer, bitmap.PixelWidth * bitmap.Format.BitsPerPixel / 8, 0);

最新更新