2010-06-10 70 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