2013-03-28 59 views
1

我在從C#中的另一個線程克隆部分位圖(由矩形定義的區域)時出現問題。從不同的線程克隆部分圖像很慢

瞭解: 在我的應用程序(Windows窗體)中,用戶可以定義執行不同圖像處理功能(例如識別顏色或文本)的多個區域。圖像由圖像採集卡(30fps)提供。由於一些算法(如OCR)花費很長時間,因此應該在後臺工作人員或線程中進行計算。

我的問題: 當我克隆我的位圖使用 ((位圖)pictureBox1.Image).Clone(矩形,((位圖)pictureBox1.Image).PixelFormat)我的主線程;

該應用程序非常快速地執行此操作(對於50x50矩形,1ms以下)。

當我從不同的線程克隆它時,需要更多的時間(大約20ms +)。

當我使用「.Clone()」(不帶矩形)克隆整個圖像時,調用此方法的線程沒有區別。它需要同一時間。

有人知道爲什麼克隆只是圖像的一部分確實需要更多的時間,當方法從另一個線程調用爲擁有圖像的線程?

預先感謝您。

問候

回答

0

我也沒搞清楚爲什麼克隆過程不起作用一樣快,因爲它應該從另一個線程調用它,但我終於找到了複製問題的變通方法:

http://msdn.microsoft.com/en-us/library/aa457087.aspx顯示覆制功能,該功能可以快速由線程調用,它不擁有圖像。

我用這個複製函數寫了一個圖像包裝器。到目前爲止工作良好

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Drawing; 
using System.Threading; 
using System.Diagnostics; 

namespace FeatureConfigurator 
{ 
    public class ThreadSafeBitmapWrapper 
    { 
     public event EventHandler<EventArgs> onImageChanged; 
     ReaderWriterLockSlim thisLock; 

     Bitmap iImg; 

     public ThreadSafeBitmapWrapper() 
     { 
      this.iImg = new Bitmap(1,1); 
      this.thisLock = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion); 
     } 

     public ThreadSafeBitmapWrapper(Bitmap img) 
     { 
      this.iImg = img; 
      this.thisLock = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion); 
     } 

     public Bitmap GetImage() 
     { 
      Bitmap img; 
      this.thisLock.EnterReadLock(); 
      try 
      { 
       img = this.iImg; 
      } 
      finally 
      { 
       this.thisLock.ExitReadLock(); 
      } 
      return img; 
     } 

     public void SetImage(Bitmap img) 
     { 
      bool success = true; 
      this.thisLock.EnterWriteLock(); 
      try 
      { 
       this.iImg = img; 
      } 
      catch 
      { 
       success = false; 
      } 
      finally 
      { 
       this.thisLock.ExitWriteLock(); 
       if (onImageChanged != null && success) 
        onImageChanged(this, new EventArgs()); 
      } 
     } 

     public Bitmap CloneImage() 
     { 
      Bitmap clone; 
      this.thisLock.EnterReadLock(); 
      try 
      { 
       clone = new Bitmap(iImg); 
      } 
      finally 
      { 
       this.thisLock.ExitReadLock(); 
      } 
      return clone; 
     } 

     internal Bitmap CloneImage(Rectangle rectangle, System.Drawing.Imaging.PixelFormat pixelFormat) 
     { 
      Bitmap clone; 
      this.thisLock.EnterReadLock(); 
      try 
      { 
       Stopwatch w = new Stopwatch(); 
       w.Restart(); 
       Debug.WriteLine("clone " + w.ElapsedMilliseconds); 
       clone = iImg.Clone(rectangle, pixelFormat); 
       Debug.WriteLine("new BMP " + w.ElapsedMilliseconds); 
      } 
      finally 
      { 
       this.thisLock.ExitReadLock(); 
      } 
      return clone; 
     } 

     /// <summary> 
     /// Code from Microsoft C# Help page: http://msdn.microsoft.com/en-us/library/aa457087.aspx 
     /// </summary> 
     /// <param name="section">The region on the containing image, which should be copied</param> 
     /// <returns></returns> 
     public Bitmap CloneImage(Rectangle section) 
     { 
      // Create the new bitmap and associated graphics object 
      Bitmap bmp = new Bitmap(section.Width, section.Height); 
      // Sets the lock to protect the copy procedure 
      this.thisLock.EnterReadLock(); 
      try 
      { 
       using (Graphics g = Graphics.FromImage(bmp)) 
       { 
        // Draw the specified section of the source bitmap to the new one 
        g.DrawImage(iImg, 0, 0, section, GraphicsUnit.Pixel); 
       } 
      } 
      finally 
      { 
       this.thisLock.ExitReadLock(); 
      } 
      // Return the bitmap 
      return bmp; 
     } 
    } 
} 

我希望這會幫助有同樣問題的人。

Regards