如何在android中更改位图图像颜色?

Posted

技术标签:

【中文标题】如何在android中更改位图图像颜色?【英文标题】:How to change Bitmap image color in android? 【发布时间】:2011-08-07 16:10:39 【问题描述】:

我正在开发一个 android 应用程序,我在其中将图像设置为 imageview。现在编程我想更改位图图像颜色。假设我的图像最初是红色的,现在我需要将其更改为橙色。我怎样才能做到这一点?请帮忙。

这是我的代码。我设法改变了不透明度,但我不知道如何改变颜色。

  @Override
    public void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        ImageView iv = (ImageView) findViewById(R.id.img);
        Drawable d = getResources().getDrawable(R.drawable.pic1);
        Bitmap mNewBitmap = ((BitmapDrawable)d).getBitmap();
        Bitmap nNewBitmap = adjustOpacity(mNewBitmap);
        iv.setImageBitmap(nNewBitmap);
    

    private Bitmap adjustOpacity( Bitmap bitmap ) 
        int width = bitmap.getWidth();
        int height = bitmap.getHeight();
        Bitmap dest = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        int[] pixels = new int[width * height];
        bitmap.getPixels(pixels, 0, width, 0, 0, width, height);
        dest.setPixels(pixels, 0, width, 0, 0, width, height);
        return dest;
     

【问题讨论】:

嗨,我遇到了同样的问题,因为我设法使用 ColorMatrix 更改了图像的亮度,但我不知道如何更改图像颜色。谢谢,AndroidVogue 【参考方案1】:

我尝试了 Josip 的答案,但不管偏移参数是 1 还是 0,我都无法使用 - 绘制的位图只是以原始颜色显示。

但是,这确实有效:

// You have to copy the bitmap as any bitmaps loaded as drawables are immutable
Bitmap bm = ImageLoader.getInstance().loadImageSync("drawable://" + drawableId, o)
            .copy(Bitmap.Config.ARGB_8888, true);

Paint paint = new Paint();
ColorFilter filter = new PorterDuffColorFilter(ContextCompat.getColor(this, R.color.COLOR_1_DARK), PorterDuff.Mode.SRC_IN);
paint.setColorFilter(filter);

Canvas canvas = new Canvas(bm);
canvas.drawBitmap(bm, 0, 0, paint);

更新 1

虽然上面的方法效果很好并且在很多情况下都很有用,但如果你只是想改变 op 所做的 ImageView 可绘制对象的主要颜色,你可以使用:

imgView.setColorFilter(ContextCompat.getColor(this, R.color.COLOR_1_DARK));

如果您需要更大的灵活性,或者这不能达到预期的效果,那么有一个重载允许您更改PorterDuff Mode,直到您得到您想要的:

imgView.setColorFilter(ContextCompat.getColor(this, R.color.COLOR_1_DARK), PorterDuff.Mode.SRC_ATOP);

更新 2

我最近遇到的另一个很好的用例是自定义 Google 地图 v2 标记图标的外观。为了使用 2 个图形来允许(例如)标记上的小/大图标,而且通过动态更改它们的颜色,还可以在这 2 个图形上使用一系列颜色。在我的情况下,我在 ClusterRenderer 内执行此操作,因为标记也被聚集在一起,但这可以以相同的方式与常规地图标记一起使用:

@Override
protected void onBeforeClusterItemRendered(MyClusterItem item, MarkerOptions markerOptions) 
    try 
        int markerColor = item.getColor();

        Bitmap icon;

        if (item.isFeatured()) 
            // We must copy the bitmap or we get an exception "Immutable bitmap passed to Canvas constructor"
            icon = BitmapFactory.decodeResource(context.getResources(),
                    R.drawable.icon_marker_large).copy(Bitmap.Config.ARGB_8888, true);
         else 
            // We must copy the bitmap or we get an exception "Immutable bitmap passed to Canvas constructor"
            icon = BitmapFactory.decodeResource(context.getResources(),
                    R.drawable.icon_marker_small).copy(Bitmap.Config.ARGB_8888, true);
        

        Paint paint = new Paint();
        ColorFilter filter = new PorterDuffColorFilter(ContextCompat.getColor(context, markerColor), PorterDuff.Mode.SRC_IN);
        paint.setColorFilter(filter);

        Canvas canvas = new Canvas(icon);
        canvas.drawBitmap(icon, 0, 0, paint);

        markerOptions.icon(BitmapDescriptorFactory.fromBitmap(icon));
     catch (Exception ex) 
        ex.printStackTrace();
    

【讨论】:

当我将图像着色为明亮的颜色时,这对我很有用,这恰好是我所需要的。 +1 我用它来改变我的文本视图的不规则形状背景图像,它工作正常。【参考方案2】:

我找到了解决办法。

    Bitmap sourceBitmap = BitmapFactory.decodeFile(imgPath);
    float[] colorTransform = 
            0, 1f, 0, 0, 0, 
            0, 0, 0f, 0, 0,
            0, 0, 0, 0f, 0, 
            0, 0, 0, 1f, 0;

    ColorMatrix colorMatrix = new ColorMatrix();
    colorMatrix.setSaturation(0f); //Remove Colour 
    colorMatrix.set(colorTransform); //Apply the Red

    ColorMatrixColorFilter colorFilter = new ColorMatrixColorFilter(colorMatrix);
    Paint paint = new Paint();
    paint.setColorFilter(colorFilter);   

    Display display = getWindowManager().getDefaultDisplay(); 

    Bitmap resultBitmap = Bitmap.createBitmap(sourceBitmap, 0, (int)(display.getHeight() * 0.15), display.getWidth(), (int)(display.getHeight() * 0.75));            

    image.setImageBitmap(resultBitmap);

    Canvas canvas = new Canvas(resultBitmap);
    canvas.drawBitmap(resultBitmap, 0, 0, paint);

【讨论】:

是否需要 setSaturation 后跟 .set 调用?【参考方案3】:
private void changeColor()
    ImageView image = (ImageView) findViewById(R.id.imageView1);
    Bitmap sourceBitmap = BitmapFactory.decodeResource(getResources(),
            R.drawable.ic_launcher);
    changeBitmapColor(sourceBitmap, image, Color.BLUE);



private void changeBitmapColor(Bitmap sourceBitmap, ImageView image, int color) 

    Bitmap resultBitmap = Bitmap.createBitmap(sourceBitmap, 0, 0,
            sourceBitmap.getWidth() - 1, sourceBitmap.getHeight() - 1);
    Paint p = new Paint();
    ColorFilter filter = new LightingColorFilter(color, 1);
    p.setColorFilter(filter);
    image.setImageBitmap(resultBitmap);

    Canvas canvas = new Canvas(resultBitmap);
    canvas.drawBitmap(resultBitmap, 0, 0, p);

【讨论】:

如果您只想更改颜色但我不太确定,我认为这应该比 user744881 建议的方式更快.. 为什么在LightingColorFilter(color, 1)中使用1作为第二个参数?根据***.com/a/7049965/1245231,这没有多大意义。这两个参数都是以 int 编码的 Android 颜色值。因此,值 1 等于添加到所有像素的 #00000001 颜色。这只会给所有像素添加一点蓝色,这是不打算的。使用 0 代替 1 更有意义:LightingColorFilter(color, 0)。另外,如果我理解得很好,则此答案仅适用于白色源图像。但对于纯黑色源图像则完全没有。 这并不完全相关,但 opengl 在保留颜色 0 的不透明度方面存在一些问题。因此,将其设置为 1 是一种很好的做法。如果有的话,它几乎不可见。跨度> 宽高为什么是-1? @AdamVarhegyi 宽度和高度的 -1 是强制 createBitmap 函数返回一个副本。文档中的相关引用:“如果指定的宽度和高度与源位图的当前宽度和高度相同,则返回源位图并且不创建新位图。”我认为调用该函数的唯一原因是如果 sourceBitmap 是不可变的,那么 Canvas 将失败。【参考方案4】:

最好通过拷贝获取可变位图,不改变大小:

public static Bitmap changeBitmapColor(Bitmap sourceBitmap, int color)

    Bitmap resultBitmap = sourceBitmap.copy(sourceBitmap.getConfig(),true);
    Paint paint = new Paint();
    ColorFilter filter = new LightingColorFilter(color, 1);
    paint.setColorFilter(filter);
    Canvas canvas = new Canvas(resultBitmap);
    canvas.drawBitmap(resultBitmap, 0, 0, paint);
    return resultBitmap;

【讨论】:

【参考方案5】:
public Bitmap replaceColor(Bitmap src,int fromColor, int targetColor) 
    if(src == null) 
        return null;
    
    // Source image size
    int width = src.getWidth();
    int height = src.getHeight();
    int[] pixels = new int[width * height];
    //get pixels
    src.getPixels(pixels, 0, width, 0, 0, width, height);

    for(int x = 0; x < pixels.length; ++x) 
        pixels[x] = (pixels[x] == fromColor) ? targetColor : pixels[x];
    
    // create result bitmap output
    Bitmap result = Bitmap.createBitmap(width, height, src.getConfig());
    //set pixels
    result.setPixels(pixels, 0, width, 0, 0, width, height);

    return result;

【讨论】:

也可以查看这个链接shaikhhamadali.blogspot.com/2013/08/… 谢谢,也为了把颜色改成白色,我把代码改成了 `pixels[x] = (pixels[x] != Color.TRANSPARENT) ? Color.WHITE : 像素[x];`【参考方案6】:

更改位图颜色的最简单方法是使用以下方法:

bitmap.eraseColor(ContextCompat.getColor(this, R.color.your_color));

如果你想用颜色覆盖 ImageView:

imageView.setColorFilter(ContextCompat.getColor(this, R.color.your_color));

【讨论】:

java.lang.IllegalStateException: cannot erase immutable bitmaps【参考方案7】:

有点离题,但考虑到您只想在此处更改颜色显示,这是我的解决方案。即,最简单快速的方法是通过 在 Canvas 上使用 drawColor() 方法来应用过滤器,就在 drawBitmap() 之后:

 m_canvas.drawColor(Color.RED, PorterDuff.Mode.ADD);

来源:https://developer.android.com/reference/android/graphics/PorterDuff.Mode.html

【讨论】:

【参考方案8】:

我已经使用下面的代码解决了这个问题

public void changeColor(Bitmap srcImage) 

    Bitmap bmpRedscale = Bitmap.createBitmap(srcImage.getWidth(), 
    srcImage.getHeight(), Bitmap.Config.ARGB_8888);

    Canvas canvas = new Canvas(bmpRedscale);
    Paint paint = new Paint();

    ColorMatrix cm = new ColorMatrix();
    cm.setRGB2YUV();
    paint.setColorFilter(new ColorMatrixColorFilter(cm));
    canvas.drawBitmap(srcImage, 0, 0, paint);

    mImgEdited.setImageBitmap(bmpRedscale);

【讨论】:

【参考方案9】:

即使位图是不可变的,它也会起作用。

 Paint paint = new Paint();
 ColorFilter filter = new PorterDuffColorFilter(ContextCompat.getColor(context, R.color.whatColorNeed), PorterDuff.Mode.SRC_IN);

 paint.setColorFilter(filter);

 canvas.drawBitmap(bitmapToModify, some_x, some_y, paint);

【讨论】:

以上是关于如何在android中更改位图图像颜色?的主要内容,如果未能解决你的问题,请参考以下文章

如何在不更改实时数据库中的 downloadUrl 的情况下更新 android 中 Firebase 存储中的位图图像

.net 位图改变图像的颜色

我想了解位图、像素等相关基础知识

如何在android中结合覆盖位图和捕获的图像?

如何在android中使用imageloader释放位图内存?

如何从 android 中的 sdcard 图像创建位图?