7

Is there some way to compare two Bitmaps which are wrapped by the BitmapDrawable.

The comparison should not fail if the sizes doesn't match, but it should match pixels and the color of the Bitmap

I am not sure how the native part of Android draws the Bitmap, because sameAs returns true even though the tint color is different.

If the size is different, I can create scaled Bitmap from the other and the compare these to.

In my source code I use DrawableCompat.setTint with the ImageViews Drawable and in the test code I load Drawable from resources and tint it same way.

Any ideas? I would like to have test which validates the source Drawable of ImageView and the color as well based on if it's pressed or not.

NOTE 1: My drawables are white, and I use tint to set color. Looping pixels for Bitmapsdoesn't work because they are white at that point, most likely Android native side uses tint color when drawing.

NOTE 2: Using compile 'com.android.support:palette-v7:21.0.0' and Palette.from(bitmap).generate(); doesn't help either because the returned palette has 0 swatches so can't get any color information there.

This is my current matcher:

public static Matcher<View> withDrawable(final Drawable d) {
    return new BoundedMatcher<View, ImageView>(ImageView.class) {

        @Override
        public boolean matchesSafely(ImageView iv) {
            if (d == null) {
                return iv.getDrawable() == null;
            } else if (iv.getDrawable() == null) {
                return false;
            }

            if (d instanceof BitmapDrawable && iv.getDrawable() instanceof BitmapDrawable) {
                BitmapDrawable d1 = (BitmapDrawable) d;
                BitmapDrawable d2 = (BitmapDrawable) iv.getDrawable();

                Bitmap b1 = d1.getBitmap();
                Bitmap b2 = d2.getBitmap();

                return b1.sameAs(b2);
            }

            return iv.getDrawable().getConstantState().equals(d.getConstantState());
        }

        @Override
        public void describeTo(Description description) {
            description.appendText("with drawable: ");
        }
    };
}

Thanks.

Niko
  • 8,093
  • 5
  • 49
  • 85

2 Answers2

0

I use matchers written by Frankie Sardo for this purpose - https://gist.github.com/frankiesardo/7490059. There are a couple of matchers which must solve your issue. All credits to him.

denys
  • 6,834
  • 3
  • 37
  • 36
  • The comparison seems to be exactly same how I did it, using Bitmap.sameAs which I don't understand why it's true for two different color BitmapDrawables. – Niko Oct 02 '15 at 08:07
  • Take a look here http://stackoverflow.com/questions/6120439/comparing-bitmap-images-in-android. The first answer gives you a tip how to get the color. Maybe this is what you are looking for. – denys Oct 02 '15 at 08:11
  • My assets are white and I use tinting, so the native side of Android seems to keep the Bitmap pixels white as well and does colouring when drawing or something like that. Pixel comparison between the two Bitmaps doesn't work for that reason. – Niko Oct 02 '15 at 08:16
  • My last try :) - "You can retrieve the prominent colors from the image using the getter methods in the Palette class, such as Palette.getVibrantColor." from here https://developer.android.com/training/material/drawables.html#DrawableTint – denys Oct 02 '15 at 08:20
  • I tried that also, both Bitmap palettes have no swatches so cannot get any color information from there either – Niko Oct 02 '15 at 08:38
  • You can ask your question here - https://groups.google.com/forum/#!forum/android-testing-support-library – denys Oct 02 '15 at 08:43
0

I've had the opposite issue: matching a drawable when it's size and/or tint can change.

When I convert drawable to bitmap, I use it's default size and apply a black tint:

private fun getBitmapFromDrawable(drawable: Drawable): Bitmap {
    val bitmap: Bitmap = Bitmap.createBitmap(
        drawable.intrinsicWidth,
        drawable.intrinsicHeight,
        Bitmap.Config.ARGB_8888
    )

    val canvas = Canvas(bitmap)
    drawable.apply {
        setBounds(0, 0, canvas.width, canvas.height)
        setTint(Color.BLACK)
        draw(canvas)
    }

    return bitmap
}

Usage:

val bitmap = getBitmapFromDrawable(currentDrawable)
val otherBitmap = getBitmapFromDrawable(otherDrawable)

return bitmap.sameAs(otherBitmap)

You could use a new parameter for matching the drawable color...

private fun getBitmapFromDrawable(drawable: Drawable, color:Int): Bitmap {
    val bitmap: Bitmap = Bitmap.createBitmap(
        drawable.intrinsicWidth,
        drawable.intrinsicHeight,
        Bitmap.Config.ARGB_8888
    )

    val canvas = Canvas(bitmap)
    drawable.apply {
        setBounds(0, 0, canvas.width, canvas.height)
        setTint(color)
        draw(canvas)
    }

    return bitmap
}

Usage:

val bitmap = getBitmapFromDrawable(currentDrawable, color)
val otherBitmap = getBitmapFromDrawable(otherDrawable, color)

return bitmap.sameAs(otherBitmap)
Nikolas
  • 1
  • 2