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

时间:2022-11-21 15:04:55

I am developing an android application in which I set an image to imageview. Now programmatic I want to change the bitmap image color. Suppose my image have red color initially and now I need to change it to orange color. How can I do that? Please help.

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

Here is my code. I managed to change the opacity but I do not know how to change the color.

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

  @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;
    } 

7 个解决方案

#1


48  

I tried Josip's answer but wouldn't work for me, regardless of whether the offset parameter was 1 or 0 - the drawn bitmap just appeared in original colour.

我尝试了Josip的答案但不适用于我,无论偏移参数是1还是0 - 绘制的位图只是以原始颜色出现。

However, this did work:

但是,这确实有效:

// 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);

Update 1

更新1

Whilst the above works well and is useful in a lot of cases, if you just want to change the main colour of an ImageView drawable, which the op did, you can just use:

虽然上述方法效果很好并且在很多情况下很有用,但如果您只想更改操作的ImageView drawable的主色,您可以使用:

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

If you need more flexibility or this doesn't give the desired effect, there's an overload that allows you to change the PorterDuff Mode until you get what you're after:

如果你需要更大的灵活性或者这不能产生预期的效果,那么你可以通过一个过载来改变PorterDuff模式,直到得到你想要的东西:

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

Update 2

更新2

Another good use case I've had for this lately is customizing the appearance of a Google map v2 marker icon. In order to use 2 graphics to allow (for example) small/large icons on a marker, but also a range of colours on those 2 graphics by changing the colour of them dynamically. In my case I was doing this inside a ClusterRenderer as the markers were also clustered, but this can be used with a regular map marker the same way:

我最近使用的另一个好用例是自定义Google map 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();
    }
}

#2


37  

I got kind of solution.

我有点解决方案。

    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);

#3


30  

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);
}

#4


7  

It's better obtain mutable bitmap by copy, without changing size:

最好通过复制获取可变位图,而不改变大小:

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


4  

The simplest way to change the bitmaps color is with this method:

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

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

If you want to overlay the ImageView with color use:

如果要使用颜色覆盖ImageView:

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

#6


1  

A little off topic, but considering you only want to display in changed color here is my solution. Namely, the easiest and fast way is just applying a filter by using drawColor() method on Canvas, right after drawBitmap():

有点偏离主题,但考虑到你只想在这里改变颜色显示我的解决方案。也就是说,最简单快捷的方法就是在Canvas上使用drawColor()方法应用过滤器,就在drawBitmap()之后:

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

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

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

#7


0  

I have solved problem by using this,

我用这个解决了问题,

public void changeColor(Bitmap srcImage) {

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);
}

#1


48  

I tried Josip's answer but wouldn't work for me, regardless of whether the offset parameter was 1 or 0 - the drawn bitmap just appeared in original colour.

我尝试了Josip的答案但不适用于我,无论偏移参数是1还是0 - 绘制的位图只是以原始颜色出现。

However, this did work:

但是,这确实有效:

// 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);

Update 1

更新1

Whilst the above works well and is useful in a lot of cases, if you just want to change the main colour of an ImageView drawable, which the op did, you can just use:

虽然上述方法效果很好并且在很多情况下很有用,但如果您只想更改操作的ImageView drawable的主色,您可以使用:

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

If you need more flexibility or this doesn't give the desired effect, there's an overload that allows you to change the PorterDuff Mode until you get what you're after:

如果你需要更大的灵活性或者这不能产生预期的效果,那么你可以通过一个过载来改变PorterDuff模式,直到得到你想要的东西:

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

Update 2

更新2

Another good use case I've had for this lately is customizing the appearance of a Google map v2 marker icon. In order to use 2 graphics to allow (for example) small/large icons on a marker, but also a range of colours on those 2 graphics by changing the colour of them dynamically. In my case I was doing this inside a ClusterRenderer as the markers were also clustered, but this can be used with a regular map marker the same way:

我最近使用的另一个好用例是自定义Google map 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();
    }
}

#2


37  

I got kind of solution.

我有点解决方案。

    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);

#3


30  

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);
}

#4


7  

It's better obtain mutable bitmap by copy, without changing size:

最好通过复制获取可变位图,而不改变大小:

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


4  

The simplest way to change the bitmaps color is with this method:

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

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

If you want to overlay the ImageView with color use:

如果要使用颜色覆盖ImageView:

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

#6


1  

A little off topic, but considering you only want to display in changed color here is my solution. Namely, the easiest and fast way is just applying a filter by using drawColor() method on Canvas, right after drawBitmap():

有点偏离主题,但考虑到你只想在这里改变颜色显示我的解决方案。也就是说,最简单快捷的方法就是在Canvas上使用drawColor()方法应用过滤器,就在drawBitmap()之后:

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

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

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

#7


0  

I have solved problem by using this,

我用这个解决了问题,

public void changeColor(Bitmap srcImage) {

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);
}