Android位图蒙版颜色,删除颜色

时间:2011-06-21 22:55:21

标签: android bitmap alpha mask

我正在创建位图,接下来我在它上面绘制第二个纯色位图。 现在我想改变第一个位图,所以我在它上面绘制的纯色将是透明的。

或者简单地说,我想从位图中删除一种颜色的所有像素。 我havie试过每个colorfilter,xfermode没有运气,还有其他可能去除颜色,而不是像素一样吗?

3 个答案:

答案 0 :(得分:13)

这适用于从位图中删除某种颜色。主要部分是使用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 :(得分:3)

user487252's solution就像API级别16(Jelly Bean)之类的魅力一样,之后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来使用蓝色。

答案 2 :(得分:0)

逐像素并不是一个糟糕的选择。只是不要在循环中调用setPixel。使用getPixels填充argb整数数组,如果不需要保留原始数据,则将其修改到位,然后在结尾处调用setPixels。如果内存是一个问题,你可以逐行执行此操作,或者你可以一次完成所有操作。您不需要为叠加颜色填充整个位图,因为您只需进行简单替换(如果当前像素为color1,则设置为color2)。