2011-06-21 57 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

非常感谢!很棒 –