我有一些用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;
}
答案 0 :(得分:3)
如果您已经有现有代码,我认为最简单,最快(尽管处理速度最快)可能是维护代码并在需要显示图像时转换为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,它可以提高效率,但可能需要您移植更多代码。您可以使用与Bitmap对象相同的方式创建WritableBitmap,并且可以访问其原始后备缓冲区(和IntPtr),并且可以根据需要操作图像数据。此链接应该为您提供有关WritableBitmap的所有信息: WriteableBitmap
以下是您的案例示例(请注意您需要知道您的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);