2010-06-10 49 views
2

我正在改变基于计算的图像中每个像素的颜色值。问题在于,我的机器需要5秒钟才能完成1000x1333图像,我正在寻找一种方法来优化它,使其更快。如何使用ColorMatrix计算颜色值?

我认为ColorMatrix可能是一个选项,但我很难弄清楚如何获得一组像素RGB值,然后使用它来计算并设置新的像素值。如果我只是用ColorMatrix修改(乘,减等)原始值,我可以看到如何做到这一点,但现在如何使用像素返回值来使用它来计算和新值。

例如:

Sub DarkenPicture() 
    Dim clrTestFolderPath = "C:\Users\Me\Desktop\ColorTest\" 
    Dim originalPicture = "original.jpg" 
    Dim Luminance As Single 
    Dim bitmapOriginal As Bitmap = Image.FromFile(clrTestFolderPath + originalPicture) 
    Dim Clr As Color 
    Dim newR As Byte 
    Dim newG As Byte 
    Dim newB As Byte 
    For x = 0 To bitmapOriginal.Width - 1 
     For y = 0 To bitmapOriginal.Height - 1 
      Clr = bitmapOriginal.GetPixel(x, y) 
      Luminance = ((0.21 * (Clr.R) + (0.72 * (Clr.G)) + (0.07 * (Clr.B))/ 255 
      newR = Clr.R * Luminance 
      newG = Clr.G * Luminance 
      newB = Clr.B * Luminance 
      bitmapOriginal.SetPixel(x, y, Color.FromArgb(newR, newG, newB)) 
     Next 
    Next 
    bitmapOriginal.Save(clrTestFolderPath + "colorized.jpg", ImageFormat.Jpeg) 
End Sub 

Luminance的值是所计算出的一个。我知道我可以分别将ColorMatrix的M00,M11,M22设置为0,0,0,然后在M40,M41,M42中设置一个新值,但是该新值是基于该像素分量的值乘法和相加计算的(((0.21 * (Clr.R) + (0.72 * (Clr.G)) + (0.07 * (Clr.B)),结果是 - Luminance - 乘以颜色分量)。

这是甚至可能与ColorMatrix

回答

3

否。使ColorMatrix无法使任何一种颜色成分与其自身或任何其他成分相乘。你可以用常量乘以组件,然后将这些组件加在一起。

但是你可以做的是将它写入C#并使用.LockBits而不是GetPixel/SetPixel。用ColorMatrix可能会达到更快的速度。

UPDATE:一些示例代码:

private static void myVerySpecialSepia(
     IntPtr source, 
     IntPtr destination, 
     int height, 
     int width, 
     int sourceStride, 
     int destinationStride, 
     int sourceBytesPerPixel, 
     int destinationBytesPerPixel) 
    { 
     unsafe 
     { 
      for (int y = 0 ; y < height ; y++) 
      { 
       byte* pOrig = (byte*)source.ToPointer() + sourceStride * y; 
       byte* pDest = (byte*)destination.ToPointer() + destinationStride * y; 
       for (int x = width ; x > 0 ; x--) 
       { 
        float b = pOrig[0]; 
        float g = pOrig[1]; 
        float r = pOrig[2]; 
        float b2 = b * b; 
        float g2 = g * g; 
        float r2 = r * r; 
        pDest[0] = (byte)(
         b * 0.400367618f + b2 * 0.00011502471f + 
         g * (-0.0337239578f) + g2 * 0.00056673412f + 
         r * 0.221445322f + r2 * 0.0008506606f + 
         6.2766808485f); 
        pDest[1] = (byte)(
         b * 0.493460029f + b2 * (-0.00023297003f) + 
         g * (-0.008577178f) + g2 * 0.00031247039f + 
         r * 0.5043012 + r2 * (-0.00006892065f) + 
         0.2746957206f); 
        pDest[2] = (byte)(
         b * 0.617727f + b2 * (-0.00070876251f) + 
         g * 0.00271902746f + g2 * 0.00007401942f + 
         r * 0.6954346f + r2 * (-0.00065937551f) + 
         0.116103285f); 
        pOrig += sourceBytesPerPixel; 
        pDest += destinationBytesPerPixel; 
       } 
      } 
     } 
    } 
+0

谢谢,我会检查了这一点。我正在使用VB.NET,所以我明白编组并不像VB中的不安全锁/解锁位在C#中那样快。尽管如此,我会试着让这个运行。 – 2010-06-16 06:36:35

+1

您可以将一个C#项目添加到您的VB.Net解决方案中,并将其添加到该项目中,然后从您的VB代码中调用该项目。我猜你会得到大约30倍速度提升的地方。 – 2010-06-16 09:28:05