Проблема производительности вызвана GetPixels / SetPixels, который является чрезвычайно медленным способом доступа к данным в .NET Bitmap. Вместо этого я бы посмотрел на метод Bitmap.LockBits, чтобы получить указатель на растровое изображение и напрямую манипулировать данными. Это будет на порядок быстрее.
См. MSDN :
В следующем примере кода показано, как использовать свойства PixelFormat, Height, Width и Scan0; методы LockBits и UnlockBits; и перечисление ImageLockMode. Этот пример предназначен для использования с Windows Forms. Чтобы запустить этот пример, вставьте его в форму и обработайте событие Paint формы, вызвав метод LockUnlockBitsExample, передав e в качестве PaintEventArgs.
private void LockUnlockBitsExample(PaintEventArgs e)
{
// Create a new bitmap.
Bitmap bmp = new Bitmap("c:\\fakePhoto.jpg");
// Lock the bitmap's bits.
Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
System.Drawing.Imaging.BitmapData bmpData =
bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite,
bmp.PixelFormat);
// Get the address of the first line.
IntPtr ptr = bmpData.Scan0;
// Declare an array to hold the bytes of the bitmap.
// This code is specific to a bitmap with 24 bits per pixels.
int bytes = bmp.Width * bmp.Height * 3;
byte[] rgbValues = new byte[bytes];
// Copy the RGB values into the array.
System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes);
// Set every red value to 255.
for (int counter = 2; counter < rgbValues.Length; counter+=3)
rgbValues[counter] = 255;
// Copy the RGB values back to the bitmap
System.Runtime.InteropServices.Marshal.Copy(rgbValues, 0, ptr, bytes);
// Unlock the bits.
bmp.UnlockBits(bmpData);
// Draw the modified image.
e.Graphics.DrawImage(bmp, 0, 150);
}
Если вы хотите пойти еще быстрее, чем копировать массив, манипулировать им и копировать его обратно, вы можете работать с растровым изображением на месте, используя небезопасный указатель. В этом случае внутренняя часть изменится следующим образом:
// Lock the bitmap's bits.
Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
System.Drawing.Imaging.BitmapData bmpData =
bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite,
bmp.PixelFormat);
// Get the address of the first line.
IntPtr ptr = bmpData.Scan0;
// Declare an array to hold the bytes of the bitmap.
// This code is specific to a bitmap with 24 bits per pixels.
int bytes = bmp.Width * bmp.Height * 3;
unsafe
{
byte* rgbValues = (byte*)ptr;
// Set every red value to 255.
for (int counter = 2; counter < bytes counter+=3)
rgbValues[counter] = 255;
}
// Unlock the bits.
bmp.UnlockBits(bmpData);
Просто обратите внимание на PixelFormat растрового изображения. В приведенном выше примере предполагается, что это 24 бит на пиксель BGR. На самом деле многие растровые изображения представляют собой BGRA (32 бита на пиксель), поэтому вам нужно будет изменить четыре байта для синего, зеленого, красного и альфа в этом порядке на пиксель.