如何从带Alpha通道的Bitmap生成保留透明区域的单色Bitmap
如何替换Bitmap颜色并保留原有Alpha通道?
嘿,这个需求我之前也碰到过,核心就是要保留原图的透明/半透明区域,只把非透明部分换成指定单色对吧?用Canvas结合PorterDuff混合模式就能高效实现,比遍历每个像素快多了,给你详细说下:
实现思路
我们要利用PorterDuff.Mode.SRC_IN这个混合模式——它的作用是只保留源图像(原Bitmap)和目标图像(我们要的单色)重叠的区域,简单说就是用原Bitmap的Alpha通道来“裁剪”我们设置的单色,这样原有的透明区域还是透明,半透明区域会变成对应透明度的目标色,完全符合你的需求。
完整代码实现
我写了一个工具方法,直接调用就行:
public static Bitmap replaceBitmapColor(Bitmap originalBitmap, int targetColor) { // 先判断原Bitmap是否有效 if (originalBitmap == null) { return null; } // 创建和原Bitmap尺寸一致、支持Alpha通道的新Bitmap Bitmap resultBitmap = Bitmap.createBitmap( originalBitmap.getWidth(), originalBitmap.getHeight(), Bitmap.Config.ARGB_8888 ); Canvas canvas = new Canvas(resultBitmap); Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); // 第一步:把整个画布填充成目标颜色(比如红色) canvas.drawColor(targetColor); // 第二步:设置混合模式为SRC_IN,让后续绘制的原Bitmap只保留非透明区域的颜色 paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); // 绘制原Bitmap,此时只有原Bitmap的非透明区域会显示目标色,Alpha通道完全保留 canvas.drawBitmap(originalBitmap, 0, 0, paint); // 记得清除混合模式,避免影响后续其他绘制操作 paint.setXfermode(null); return resultBitmap; }
用法示例
比如你要把原Bitmap换成红色,直接这样调用:
// 你原来获取Bitmap的代码 int resID = context.getResources().getIdentifier(bitmapName, "drawable", context.getPackageName()); Bitmap originalBitmap = BitmapFactory.decodeResource(context.getResources(), resID); // 生成替换颜色后的新Bitmap Bitmap coloredBitmap = replaceBitmapColor(originalBitmap, Color.RED); // 用完原Bitmap如果不需要了,记得回收释放内存 if (originalBitmap != null && !originalBitmap.isRecycled()) { originalBitmap.recycle(); }
注意事项
- 原Bitmap必须是带Alpha通道的(你的PNG已经满足,没问题)
Bitmap.Config.ARGB_8888是必须的,这个配置支持完整的Alpha通道- 如果你不需要原Bitmap了,一定要调用
recycle()释放内存,避免内存泄漏
内容的提问来源于stack exchange,提问作者gibsonff
相关产品推荐
相关产品推荐

