2017-07-08 66 views
1

我正在尋找一種更快速的方法,以基於另一種顏色替換圖像中的顏色。例如,我的圖像大多是黑色,灰色,我想根據紅色重新着色。現在我把它作爲我的基本顏色和紅色作爲我的新顏色傳遞給這個函數。然後,我逐像素地確定其RGB,並重新計算到新的紅色陰影。所以純黑色變成純紅色,而灰色變成更亮的紅色等等。需要更快的方法來替換基於另一種顏色的圖像中的顏色

有沒有更快的方法來做到這一點?可能使用單獨的圖像處理庫?我看着ImageMagick,但我找不到我正在尋找的確切功能。

這是我目前的功能。它有效,但速度很慢。

Public Function doRecolorImage(ByRef inBMP As Bitmap, ByVal baseColor As Color, ByVal newColor As Color) As Bitmap 
     Dim newimg As New Bitmap(inBMP.Width, inBMP.Height) 

      Using gIcons As Graphics = Graphics.FromImage(newimg) 
       For x = 0 To inBMP.Width - 1 
        For y = 0 To inBMP.Height - 1 
         Dim ltrans As Byte = inBMP.GetPixel(x, y).A 
         Dim lR As Byte = inBMP.GetPixel(x, y).R 
         Dim lG As Byte = inBMP.GetPixel(x, y).G 
         Dim lB As Byte = inBMP.GetPixel(x, y).B 

         Dim newpixR As Integer = CInt(newColor.R) + (CInt(lR) - CInt(baseColor.R)) 

         Dim newpixG As Integer = CInt(newColor.G) + (CInt(lG) - CInt(baseColor.G)) 

         Dim newpixB As Integer = CInt(newColor.B) + (CInt(lB) - CInt(baseColor.B)) 

         newimg.SetPixel(x, y, System.Drawing.Color.FromArgb(ltrans, newpixR, newpixG, newpixB)) 
        Next 
       Next 
      End Using 

     Return newimg 

    End Function 

在這裏,我嘗試使用嘉洛斯但它沒有工作,不知道爲什麼......也許我的嘉洛斯是如何工作的認識是錯誤的。

Public Function doNewRecolorImage(ByRef inBMP As Bitmap, ByVal baseColor As Color, ByVal newColor As Color) As Bitmap 
     Dim newimg As New Bitmap(inBMP.Width, inBMP.Height) 


      Dim iaImageProps As New ImageAttributes 

      Dim cmNewColors As ColorMatrix 

      cmNewColors = New ColorMatrix(New Single()() _ 
       {New Single() {newColor.R/baseColor.R, 0, 0, 0, 0}, _ 
       New Single() {0, newColor.G/baseColor.G, 0, 0, 0}, _ 
       New Single() {0, 0, newColor.B/baseColor.B, 0, 0}, _ 
       New Single() {0, 0, 0, 1, 0}, _ 
       New Single() {0, 0, 0, 0, 1}}) 

      iaImageProps.SetColorMatrix(cmNewColors) 

      Using g As Graphics = Graphics.FromImage(newimg) 
       g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality 
       g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality 
       g.InterpolationMode = Drawing2D.InterpolationMode.HighQualityBicubic 
       g.DrawImage(inBMP, New Rectangle(0, 0, inBMP.Width, inBMP.Height), 0, 0, inBMP.Width, inBMP.Height, GraphicsUnit.Pixel, iaImageProps) 
      End Using 


     Return newimg 

    End Function 

更新1:

下面是基於以下瑞安的回答我的更新功能。它運行,但它沒有返回預期的重新着色圖像。圖像是一種純色......基本顏色。所以我會傳遞基本顏色和新顏色並獲得結果。但是,結果應該是新顏色(深藍色),因爲圖像是純色,所以它應該是精確的顏色交換。

enter image description here

Private Function calcColorSwap(_base As Byte, _new As Byte) As Single 
    If _new > _base Then 
     Return (CInt(_new) - CInt(_base))/255.0! 
    Else 
     Return (CInt(_base) - CInt(_new))/255.0! 
    End If 
End Function 

Public Function doNewRecolorImage(inBMP As Bitmap, baseColor As Color, newColor As Color) As Bitmap 
    Dim newimg As New Bitmap(inBMP.Width, inBMP.Height) 
    Dim transformation As New ColorMatrix(New Single()() { 
      New Single() {1, 0, 0, 0, 0}, 
      New Single() {0, 1, 0, 0, 0}, 
      New Single() {0, 0, 1, 0, 0}, 
      New Single() {0, 0, 0, 1, 0}, 
      New Single() {calcColorSwap(baseColor.R, newColor.R), calcColorSwap(baseColor.G, newColor.G), calcColorSwap(baseColor.B, newColor.B), 0, 1} 
     }) 

    Dim imageAttributes As New ImageAttributes() 
    imageAttributes.SetColorMatrix(transformation) 


    Using g As Graphics = Graphics.FromImage(newimg) 
     g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality 
     g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality 
     g.InterpolationMode = Drawing2D.InterpolationMode.HighQualityBicubic 
     g.DrawImage(inBMP, New Rectangle(0, 0, inBMP.Width, inBMP.Height), 0, 0, inBMP.Width, inBMP.Height, GraphicsUnit.Pixel, imageAttributes) 
    End Using 

Return newimg 

End Function 

更新2(液):

這裏的解決方案:基於以下瑞安的答案。

Private Function calcColorSwap(_base As Byte, _new As Byte) As Single 
     Return (CInt(_new) - CInt(_base))/255.0! 
End Function 

Public Function doNewRecolorImage(inBMP As Bitmap, baseColor As Color, newColor As Color) As Bitmap 
    Dim newimg As New Bitmap(inBMP.Width, inBMP.Height) 
    Dim transformation As New ColorMatrix(New Single()() { 
      New Single() {1, 0, 0, 0, 0}, 
      New Single() {0, 1, 0, 0, 0}, 
      New Single() {0, 0, 1, 0, 0}, 
      New Single() {0, 0, 0, 1, 0}, 
      New Single() {calcColorSwap(baseColor.R, newColor.R), calcColorSwap(baseColor.G, newColor.G), calcColorSwap(baseColor.B, newColor.B), 0, 1} 
     }) 

    Dim imageAttributes As New ImageAttributes() 
    imageAttributes.SetColorMatrix(transformation) 


    Using g As Graphics = Graphics.FromImage(newimg) 
     g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality 
     g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality 
     g.InterpolationMode = Drawing2D.InterpolationMode.HighQualityBicubic 
     g.DrawImage(inBMP, New Rectangle(0, 0, inBMP.Width, inBMP.Height), 0, 0, inBMP.Width, inBMP.Height, GraphicsUnit.Pixel, imageAttributes) 
    End Using 

Return newimg 

End Function 

回答

1

矩陣相當於原來的 - 增加一個固定值R,G和B - 看起來是這樣的:

New Single()() { 
    New Single() {1, 0, 0, 0, 0}, 
    New Single() {0, 1, 0, 0, 0}, 
    New Single() {0, 0, 1, 0, 0}, 
    New Single() {0, 0, 0, 1, 0}, 
    New Single() {(CInt(newColor.R) - CInt(baseColor.R))/255!, (CInt(newColor.G) - CInt(baseColor.G))/255!, (CInt(newColor.B) - CInt(baseColor.B))/255!, 0, 1} 
} 

總評:

Public Function doRecolorImage(image As Image, baseColor As Color, newColor As Color) As Bitmap 
    Dim transformation As New ColorMatrix(New Single()() { 
     New Single() {1, 0, 0, 0, 0}, 
     New Single() {0, 1, 0, 0, 0}, 
     New Single() {0, 0, 1, 0, 0}, 
     New Single() {0, 0, 0, 1, 0}, 
     New Single() {(CInt(newColor.R) - CInt(baseColor.R))/255!, (CInt(newColor.G) - CInt(baseColor.G))/255!, (CInt(newColor.B) - CInt(baseColor.B))/255!, 0, 1} 
    }) 

    Dim imageAttributes As New ImageAttributes() 
    imageAttributes.SetColorMatrix(transformation) 

    Dim result As New Bitmap(image.Width, image.Height) 

    Using g As Graphics = Graphics.FromImage(result) 
     g.DrawImage(image, New Rectangle(0, 0, image.Width, image.Height), 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, imageAttributes) 
    End Using 

    Return result 
End Function 

(別請使用ByRef!)

+0

我測試了你的代碼,看到我上面更新的代碼。當'baseColor'值大於'newColor'值時,它拋出一個錯誤_(無法轉換爲Byte)_因此我添加了一個函數來切換它們......不知道這是否是正確的邏輯。另外,當圖像是純色時,它並不完全符合我的期望。 –

+0

@ChaseRocker:不應該有'If';總是以相同的順序減去CInt(newColor.R - baseColor.R)/ 255!'。 – Ryan

+0

它引發錯誤。例如,當new = 87和base = 255時,它會引發溢出異常:http://i.imgur.com/54V0e4H.jpg –

相關問題