2016-12-30 137 views
0

我有一些用C#編寫的小型WinForms應用程序,它們利用System.Drawing.BitmapSystem.Windows.Forms.PictureBox來顯示應用程序隨時間保留的原始字節緩衝區的位圖。在某種程度上,這類似於窮人的動畫。WPF中的位圖繪製

我想端口這些應用程序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; 
} 
+1

使用(有據可查)[' BitmapSource.Create'](https://msdn.microsoft.com/en-us/library/ms616045(v = vs.110).aspx)方法。將BitmapSource分配給['Image']的'Source'屬性(https://msdn.microsoft.com/en-us/library/system.windows.controls.image(v = vs.110).aspx)控制。 – Clemens

+1

我打算髮佈一個關於如何使用'WriteableBitmap'完成這個問題的答案,但問題已經關閉。 FWIW,我把它放在這裏:http://pastebin.com/Ufmx4giD –

+0

謝謝你,@Clemens。你的簡潔的回答幫助我找到了自己的腳。 – Jono

回答

1

如果您已經有現有的代碼,我想,也許是最簡單和最快(不處理速度最快的,雖然)將是保持你的代碼,並轉換成的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, System.Windows.Media.PixelFormat.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); 
+0

謝謝。我嘗試了你和Clemens的建議(分別爲WriteableBitmap和BitmapSource.Create),都適合我。我試圖改變你的代碼示例使用PixelFormats.Bgra32 - 與s - 但我的編輯不夠長,以便stackoverflow接受我的建議。我根本沒有嘗試你最初的建議 - 我認爲它涉及到其中一個混淆了(*&%^首先是我)的類。 – Jono