2010-07-13 356 views
0

我有一個小函數,它會將位圖中的像素從給定顏色重新着色爲新的給定顏色。是替換透明圖像中的顏色漸變

我與代碼中的問題如下:

1) 的函數給出,除非我已經定義這個結果被重新映射其不應被concidered因爲我有個閾白色像素...(計算錯誤)

2)當給定某些顏色時,例如暗綠奇怪的結果在圖像中看到的從函數返回(I beleive這是由於在加法或減法時的字節型的溢出)

我使用的基礎圖像可以在這裏找到:

我已獲得http://www.freeimagehosting.net/uploads/c8745a9de1.png

結果可以在這裏找到:

freeimagehosting.net/uploads/fa48e5a0eb.png(與Color.Magenta如remapColor,Color.Red如newColor調用,好像白色像素來實現和漸變的末端沒有正確着色)

freeimagehosting.net/uploads/8faec6a569.png(與Color.Magenta如remapColor,Color.Yellow如newColor調用,好像白色像素來實現和梯度的端部沒有正確地着色)

freeimagehosting。 net/uploads/2efd4c04aa.png(與Color.Magenta一起被稱爲remapColor,Color.Blue as newColor,看起來像漸變顏色不正確)

freeimagehosting.net/uploads/defdf04e16.png(用Color.Magenta調用爲remapColor ,Color.Teal as newColor,看起來像白色像素受到影響,並且沒有任何梯度正確計算)

我對這個代碼功能如下:每個建議

public unsafe static Bitmap RecolorImage(Bitmap original, Color remapColor, Color newColor) 
    { 
     Bitmap result = new Bitmap(original.Width, original.Height); 

     //lock the original bitmap in memory 
     BitmapData originalData = original.LockBits(
      new Rectangle(0, 0, original.Width, original.Height), 
      ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); 

     //lock the new bitmap in memory 
     BitmapData newData = result.LockBits(
      new Rectangle(0, 0, original.Width, original.Height), 
      ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); 

     //set the number of bytes per pixel 
     int pixelSize = 4; 

     int rthreshold = 128; 
     int gthreshold = 128; 
     int bthreshold = 128; 

     for (int y = 0; y < original.Height; y++) 
     { 
      //get the data from the original image 
      byte* oRow = (byte*)originalData.Scan0 + (y * originalData.Stride); 

      //get the data from the new image 
      byte* nRow = (byte*)newData.Scan0 + (y * newData.Stride); 

      for (int x = 0; x < original.Width; x++) 
      { 
       //examine the rgb values 
       byte r = (byte)((oRow[x * pixelSize])); 
       byte g = (byte)((oRow[x * pixelSize + 1])); 
       byte b = (byte)((oRow[x * pixelSize + 2])); 
       byte a = (byte)((oRow[x * pixelSize + 3])); 

       if (a > 0 && 
        Math.Abs(remapColor.R - r) <= rthreshold && 
        Math.Abs(remapColor.B - b) <= bthreshold && 
        Math.Abs(remapColor.G - g) <= gthreshold 
        ) 
       { 
        if (newColor.R == 0) 
        { 
         r = 0; 
        } 
        else 
        { 
         if (newColor.R > remapColor.R) 
          r = (byte)(r - newColor.R); 
         else 
          r = (byte)(r + newColor.R); 
        } 

        if (newColor.G == 0) 
        { 
         g = 0; 
        } 
        else 
        { 
         if (newColor.G > remapColor.G) 
          g = (byte)(g - newColor.G); 
         else 
          g = (byte)(g + newColor.G); 
        } 

        if (newColor.B == 0) 
        { 
         b = 0; 
        } 
        else 
        { 
         if (newColor.B > remapColor.B) 
          b = (byte)(b - newColor.B); 
         else 
          b = (byte)(b + newColor.B); 
        } 
       } 


       //set the new image's pixel remaped pixel color 
       nRow[x * pixelSize] = b; //B 
       nRow[x * pixelSize + 1] = g; //G 
       nRow[x * pixelSize + 2] = r; //R 
       nRow[x * pixelSize + 3] = a; //A 
      } 
     } 

     original.UnlockBits(originalData); 
     result.UnlockBits(newData); 


     return result; 
    }   

什麼提供的最新....

是什麼,我試圖做可能嗎?

可靠嗎?

在我的代碼中只有一個錯誤?

有沒有更好的方法來實現這個「重新適應技術」使用漸變位圖?

謝謝你的時間。

回答

0

我已經決定,雖然這可能是可能的,如果我研究有關顏色空間及其支持理論的各種材料。看起來這需要比remapColor的快速閾值計算和標準化稍多一點。

我打算建議不要對柵格位圖圖像執行這種類型的修改,圖形會以其向量形式進行修改。

的過程應該是這樣的:

圖形以任何成像套間設計工作在創建

它們例如保存到矢量格式使用SVG渲染引擎(http://svg.codeplex.com/

通過此解決方案,我們可以將SVG直接輸出到瀏覽器(如果支持),則可以將SVG直接輸出到瀏覽器並直接在客戶端上進行修改,或者在需要時使用服務器和PNG輸出。

我覺得這種安排將爲我們提供比我最初一起破解更多的靈活性和更強大的解決方案。

謝謝你們的時間!

+0

我也可以修改位圖調色板中的一組已知顏色,它會影響整體圖像,並且會更快地設置位圖中的每個像素! 而實際上我們最終使用普通的XAML。 Illustrator可以使用插件導出XAML,因此我們可以在與插件一起保存後編輯圖形! – Jay 2012-12-12 15:47:39

0

看起來您的閾值測試不正確。走線:

remapColor.R - r <= rthreshold 

如果當前像素是白色的,然後r將是255,測試將永遠是真實的,不管是什麼remapColor.Rrthreshold是。

我認爲Math.Abs(remapColor.R - r)可能工作。

而且你的字節值超出範圍可能是正確的。修復閾值測試可能會阻止這種情況的發生。否則,請嘗試放入一些邊界檢查以查看它發生的位置。

+0

嘿, 謝謝你的建議,但它似乎沒有按預期工作。 這是進行建議更改後代碼的輸出。 http://www.freeimagehosting.net/uploads/d5ea228622.png 調用與Color.Magenta作爲remapColor和Color.Red作爲newColor 我要對這個錯誤的方式? – Jay 2010-07-13 19:06:24