我有一些在C#中编写的小型Winforms应用程序,该应用程序利用System.Drawing.Bitmap
和System.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);