1

我在从 C# 中的另一个线程克隆部分位图(由矩形定义的区域)时遇到问题。

便于理解:在我的应用程序(Windows 窗体)中,用户可以定义多个区域,在这些区域上执行不同的图像处理功能(例如识别颜色或文本)。图像由图像采集卡 (30fps) 提供。由于某些算法(如 OCR)需要很长时间,它们应该在后台工作程序或线程中计算。

我的问题:当我使用 ((Bitmap)pictureBox1.Image).Clone(rectangle,((Bitmap)pictureBox1.Image).PixelFormat); 在我的主线程中克隆我的位图时

应用程序执行此操作非常快(对于 50x50 的矩形,在 1 毫秒以下)。

当我从不同的线程克隆它时,它需要更多的时间(大约 20 毫秒+)。

当我使用“.Clone()”(没有矩形)克隆整个图像时,调用该方法的线程没有区别。它需要同样的时间。

有人知道为什么当从另一个线程调用该方法作为拥有图像的线程时,克隆图像的一部分确实需要更多时间吗?

先感谢您。

问候

4

1 回答 1

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;
        }
    }
}

我希望这会帮助有同样问题的人。

问候

于 2013-04-18T07:25:33.420 回答