2011-06-21 67 views
9

我正在創建位圖,接下來我在其上繪製第二個純色位圖。 現在我想改變第一個位圖,所以我在其上繪製的純色將是透明的。或者乾脆,我想從位圖中刪除一種顏色的所有像素。 我havie嘗試過所有colorfilter,和xfermode沒有運氣,是否有任何其他的可能性去除其他像素逐像素的顏色?Android位圖遮罩顏色,移除顏色

回答

0

像素逐像素不是一個壞的選擇。只是不要在你的循環中調用setPixel。用getPixels填充一個argb ints數組,如果不需要保存原始數據,則將其修改,然後在最後調用setPixels。如果記憶是一個問題,你可以逐行進行,或者你可以一次完成整個事情。您不需要爲疊加顏色填充整個位圖,因爲您只需進行簡單的替換(如果當前像素爲color1,則設置爲color2)。

+0

謝謝,但我終於想出瞭如何用porterduff,xfermode(xor)做到這一點,但適用於其他位圖,首先我合併了面具和來源,並試圖用colorfilter在畫布上繪製它,但最後我想我應該在使用xfermode的同時在源代碼上繪製蒙版,而不是畫布:) – ZZZ

12

這適用於從位圖中去除某種顏色。主要部分是使用AvoidXfermode。如果試圖將一種顏色改爲另一種顏色,它也應該可以工作。

我應該補充說,這回答了從位圖中移除顏色的問題標題。使用PorterDuff Xfermode可能會更好地解決具體問題,就像OP所說的那樣。

// start with a Bitmap bmp 

// make a mutable copy and a canvas from this mutable bitmap 
Bitmap mb = bmp.copy(Bitmap.Config.ARGB_8888, true); 
Canvas c = new Canvas(mb); 

// get the int for the colour which needs to be removed 
Paint p = new Paint(); 
p.setARGB(255, 255, 0, 0); // ARGB for the color, in this case red 
int removeColor = p.getColor(); // store this color's int for later use 

// Next, set the alpha of the paint to transparent so the color can be removed. 
// This could also be non-transparent and be used to turn one color into another color    
p.setAlpha(0); 

// then, set the Xfermode of the pain to AvoidXfermode 
// removeColor is the color that will be replaced with the pain't color 
// 0 is the tolerance (in this case, only the color to be removed is targetted) 
// Mode.TARGET means pixels with color the same as removeColor are drawn on 
p.setXfermode(new AvoidXfermode(removeColor, 0, AvoidXfermode.Mode.TARGET)); 

// draw transparent on the "brown" pixels 
c.drawPaint(p); 

// mb should now have transparent pixels where they were red before 
+1

這似乎不適用於API級別16,並且AvoidXferMode已被棄用而沒有解釋。不過,該解決方案確實可以在API級別15中一直工作。 –

+1

@LeoAccend查看源代碼的更改歷史記錄,似乎已被棄用,因爲它不受硬件加速支持。 –

2

user487252's solution的作品就像一個魅力直到API級別16(果凍豆),之後AvoidXfermode似乎並沒有在所有的工作。

在我的特殊用例中,我已經將一個PDF頁面(通過APV PDFView)渲染成像素數組int[],我將要傳入Bitmap.createBitmap(int[], int, int, Bitmap.Config)。此頁面包含繪製到白色背景上的線條藝術,並且我需要在保留抗鋸齒的同時移除背景。

我無法找到一個完全符合我想要的Porter-Duff模式,所以我最終屈曲並遍歷像素並逐個轉換它們。其結果是令人驚訝的簡單和高性能:

int [] pixels = ...; 

for(int i = 0; i < pixels.length; i++) { 
    // Invert the red channel as an alpha bitmask for the desired color. 
    pixels[i] = ~(pixels[i] << 8 & 0xFF000000) & Color.BLACK; 
} 

Bitmap bitmap = Bitmap.createBitmap(pixels, width, height, Bitmap.Config.ARGB_8888); 

這是完美的引出配線技術中,由於任何顏色可以用於線路,而不會失去所述抗混疊。我在這裏使用紅色通道,但可以通過將16位替換爲8來使用綠色,或者通過移動24來改變藍色。

+0

我想使用你的代碼,但我不知道如何使用它的自定義顏色。請幫助 –

+0

您可以在上面的代碼中替換'Color.BLACK'以獲得不同的彩色線條(例如:'Color.RED'或'0xFF3399FF')。 –

+0

非常感謝!很棒 –