androidimagemaskclip

ImageView ColorFilter on non tranparent pixels. Clip


I have an ImageView with bitmap in it. This bitmap has alpha channel and transparent pixels. When i try to use ColorFiter with Mode.OVERLAY (since honeycomb) - provided color overlay the whole imageview (whole rect), but i want only to overlay non transparent pixels. How can i clip the imageview's canvas to perform filter where i want ?

UPDATED

I have grey image in png:

enter image description here

When i try to use MODE_ATOP i get:

enter image description here

When i use OVERLAY i get:

enter image description here

And what i want to get:

enter image description here


Solution

  • There's probably a more efficient way to do this (maybe by creating a ColorMatrixColorFilter to approximate it), but since Mode.OVERLAY appear to be hard to simplify otherwise, here's some sample code that should implement what you want:

    public class MyActivity extends Activity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            final ImageView imageView = new ImageView(this);
            setContentView(imageView);
    
            final Paint paint = new Paint();
            Canvas c;
    
            final Bitmap src = BitmapFactory.decodeResource(getResources(),
                    android.R.drawable.sym_def_app_icon);
            final int overlayColor = Color.RED;
    
            final Bitmap bm1 = Bitmap.createBitmap(src.getWidth(), src.getHeight(), Config.ARGB_8888);
            c = new Canvas(bm1);
            paint.setColorFilter(new PorterDuffColorFilter(overlayColor, PorterDuff.Mode.OVERLAY));
            c.drawBitmap(src, 0, 0, paint);
    
            final Bitmap bm2 = Bitmap.createBitmap(src.getWidth(), src.getHeight(), Config.ARGB_8888);
            c = new Canvas(bm2);
            paint.setColorFilter(new PorterDuffColorFilter(overlayColor, PorterDuff.Mode.SRC_ATOP));
            c.drawBitmap(src, 0, 0, paint);
    
            paint.setColorFilter(null);
            paint.setXfermode(new AvoidXfermode(overlayColor, 0, Mode.TARGET));
            c.drawBitmap(bm1, 0, 0, paint);
    
            imageView.setImageBitmap(bm2);
        }
    
    }
    

    In short, we draw the source bitmap and color using the OVERLAY mode, and then using a secondary bitmap (composited using SRC_ATOP mode), we combine it using AvoidXfermode to not draw over the transparent pixels.

    Original image:

    original image

    Result:

    result