Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Общие вопросы по .NET и C# > [VC#] Быстрое копирование Bitmap


Автор: MuForum 1.5.2009, 19:58
Доброе время суток!
Работаю на "Microsoft Visual Studio 2008". Язык программирования C#.

# Задача: Реализовать быстрое копирование изображения.
- Сначала может показаться, что тут ничего сложного нету, однако, если графические файлы достаточно большого размера, то стандартный способ является достаточно долгим.

# 1 способ: (В лоб)
Код

Bitmap newImg = new Bitmap(oldImg);


# 2 способ: (Копирование всего участка памяти)
Код

Bitmap newImg = (Bitmap)oldImg.Clone(); // ICloneable - Clone()

P.S. -> Данный способ очень быстрый, однако возникают проблемы при использовании функции RotateFlip() частенько вылетает ошибка. (Чаще всего с форматом *.bmp)
-- Текст ошибки: "ExternalExtension was unhandled. A generic error occurred in GDI+."


# 3 способ: (Примерно в два раза быстрее чем вариант в лоб)
Код

private Bitmap CopyBitmap(Bitmap source)
{
   Bitmap bmp = new Bitmap(source.Width, source.Height, source.PixelFormat);
   Graphics g = Graphics.FromImage(bmp);
   g.DrawImage(source, 0, 0, source.Width, source.Height);
   g.Dispose();
   // ----
   return bmp;
}

P.S. -> Пример позаимствован с MSDN.


# 4 способ:
Код

private Bitmap CloneBitmap(Bitmap srcBmp)
{
   Bitmap dstBmp = new Bitmap(srcBmp.Width, srcBmp.Height);
   BitmapData srcBmpData = srcBmp.LockBits(new Rectangle(0, 0, srcBmp.Width, srcBmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
   BitmapData dstBmpData = dstBmp.LockBits(new Rectangle(0, 0, dstBmp.Width, dstBmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
   unsafe
   {
      int* srcVal = (int*)srcBmpData.Scan0;
      int* dstVal = (int*)dstBmpData.Scan0;
      int iSize = srcBmpData.Width * srcBmpData.Height;
      for (int i = 0; i < iSize; i++, srcVal++, dstVal++) *dstVal = *srcVal;
   }
   srcBmp.UnlockBits(srcBmpData);
   dstBmp.UnlockBits(dstBmpData);
   return dstBmp;
}

P.S. -> Оптимизированный пример от "-Mikle-".



# Результаты тестирования:
Цитата

1. Изображение 189x103.
-- 1 способ: 0-1 мсек.
-- 2 способ: 0 мсек.
-- 3 способ: 1 мсек.
-- 4 способ: 0 мсек.
2. Изображение 805x563.
-- 1 способ: 9 мсек.
-- 2 способ: 0 мсек.
-- 3 способ: 5 мсек.
-- 4 способ: 8 мсек.
3. Изображение 4941x6936.
-- 1 способ: ~730 мсек.
-- 2 способ: 0 мсек.
-- 3 способ: ~350 мсек.
-- 4 способ: ~565 мсек.



P.S. -> Парни, может кто-то подскажет ещё какие-то способы?

Автор: -Mikle- 1.5.2009, 20:55
Думаю что быстрее, чем этот способ, не получится. Попробуй.
Код

        private Bitmap CloneBitmap(Bitmap srcBmp)
        {
            Bitmap dstBmp = new Bitmap(srcBmp.Width, srcBmp.Height);

            BitmapData srcBmpData = srcBmp.LockBits(new Rectangle(0, 0, srcBmp.Width, srcBmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
            BitmapData dstBmpData = dstBmp.LockBits(new Rectangle(0, 0, dstBmp.Width, dstBmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
            unsafe
            {
                int* srcVal = (int*)srcBmpData.Scan0;
                int* dstVal = (int*)dstBmpData.Scan0;
                for (int i = 0; i < (srcBmpData.Width * srcBmpData.Height); i++, srcVal++, dstVal++)
                    *dstVal = *srcVal;
            }
            srcBmp.UnlockBits(srcBmpData);
            dstBmp.UnlockBits(dstBmpData);

            return dstBmp;
        }

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)