Home | History | Annotate | Download | only in shadows
      1 package org.robolectric.shadows;
      2 
      3 import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1;
      4 import static android.os.Build.VERSION_CODES.KITKAT;
      5 import static com.google.common.truth.Truth.assertThat;
      6 import static org.robolectric.Shadows.shadowOf;
      7 
      8 import android.graphics.Bitmap;
      9 import android.graphics.Canvas;
     10 import android.graphics.Color;
     11 import android.graphics.ColorMatrix;
     12 import android.graphics.ColorMatrixColorFilter;
     13 import android.graphics.Matrix;
     14 import android.graphics.Paint;
     15 import android.os.Build;
     16 import android.os.Parcel;
     17 import android.util.DisplayMetrics;
     18 import androidx.test.ext.junit.runners.AndroidJUnit4;
     19 import java.nio.ByteBuffer;
     20 import java.nio.IntBuffer;
     21 import java.nio.LongBuffer;
     22 import java.nio.ShortBuffer;
     23 import java.util.Arrays;
     24 import org.junit.Test;
     25 import org.junit.runner.RunWith;
     26 import org.robolectric.annotation.Config;
     27 import org.robolectric.shadow.api.Shadow;
     28 
     29 @RunWith(AndroidJUnit4.class)
     30 public class ShadowBitmapTest {
     31   @Test
     32   public void shouldCreateScaledBitmap() throws Exception {
     33     Bitmap originalBitmap = create("Original bitmap");
     34     Bitmap scaledBitmap = Bitmap.createScaledBitmap(originalBitmap, 100, 200, false);
     35     assertThat(shadowOf(scaledBitmap).getDescription())
     36         .isEqualTo("Original bitmap scaled to 100 x 200");
     37     assertThat(scaledBitmap.getWidth()).isEqualTo(100);
     38     assertThat(scaledBitmap.getHeight()).isEqualTo(200);
     39     scaledBitmap.getPixels(new int[20000], 0, 0, 0, 0, 100, 200);
     40   }
     41 
     42   @Test
     43   public void shouldCreateActiveBitmap() throws Exception {
     44     Bitmap bitmap = Bitmap.createBitmap(100, 200, Bitmap.Config.ARGB_8888);
     45     assertThat(bitmap.isRecycled()).isFalse();
     46     assertThat(bitmap.getPixel(0, 0)).isEqualTo(0);
     47     assertThat(bitmap.getWidth()).isEqualTo(100);
     48     assertThat(bitmap.getHeight()).isEqualTo(200);
     49     assertThat(bitmap.getConfig()).isEqualTo(Bitmap.Config.ARGB_8888);
     50   }
     51 
     52   @Test
     53   public void hasAlpha() {
     54     Bitmap bitmap = Bitmap.createBitmap(100, 200, Bitmap.Config.ARGB_8888);
     55     assertThat(bitmap.hasAlpha()).isFalse();
     56     bitmap.setHasAlpha(true);
     57     assertThat(bitmap.hasAlpha()).isTrue();
     58   }
     59 
     60   @Test
     61   @Config(minSdk = JELLY_BEAN_MR1)
     62   public void hasMipmap() {
     63     Bitmap bitmap = Bitmap.createBitmap(100, 200, Bitmap.Config.ARGB_8888);
     64     assertThat(bitmap.hasMipMap()).isFalse();
     65     bitmap.setHasMipMap(true);
     66     assertThat(bitmap.hasMipMap()).isTrue();
     67   }
     68 
     69   @Test
     70   @Config(minSdk = KITKAT)
     71   public void getAllocationByteCount() {
     72     Bitmap bitmap = Bitmap.createBitmap(100, 200, Bitmap.Config.ARGB_8888);
     73     assertThat(bitmap.getAllocationByteCount()).isGreaterThan(0);
     74   }
     75 
     76   @Test
     77   public void shouldCreateBitmapWithColors() throws Exception {
     78     int[] colors = new int[] {
     79         Color.parseColor("#ff0000"), Color.parseColor("#00ff00"), Color.parseColor("#0000ff"),
     80         Color.parseColor("#990000"), Color.parseColor("#009900"), Color.parseColor("#000099")
     81     };
     82     Bitmap bitmap = Bitmap.createBitmap(colors, 3, 2, Bitmap.Config.ARGB_8888);
     83     assertThat(bitmap.getWidth()).isEqualTo(3);
     84     assertThat(bitmap.getHeight()).isEqualTo(2);
     85     assertThat(bitmap.getConfig()).isEqualTo(Bitmap.Config.ARGB_8888);
     86     assertThat(bitmap.getPixel(0, 0)).isEqualTo(Color.parseColor("#ff0000"));
     87     assertThat(bitmap.getPixel(0, 1)).isEqualTo(Color.parseColor("#990000"));
     88     assertThat(bitmap.getPixel(1, 0)).isEqualTo(Color.parseColor("#00ff00"));
     89     assertThat(bitmap.getPixel(1, 1)).isEqualTo(Color.parseColor("#009900"));
     90     assertThat(bitmap.getPixel(2, 0)).isEqualTo(Color.parseColor("#0000ff"));
     91     assertThat(bitmap.getPixel(2, 1)).isEqualTo(Color.parseColor("#000099"));
     92   }
     93 
     94   @Test
     95   public void shouldCreateBitmapFromAnotherBitmap() {
     96     Bitmap originalBitmap = create("Original bitmap");
     97     Bitmap newBitmap = Bitmap.createBitmap(originalBitmap);
     98     assertThat(shadowOf(newBitmap).getDescription())
     99         .isEqualTo("Original bitmap created from Bitmap object");
    100   }
    101 
    102   @Test
    103   public void shouldCreateBitmapWithMatrix() {
    104     Bitmap originalBitmap = create("Original bitmap");
    105     shadowOf(originalBitmap).setWidth(200);
    106     shadowOf(originalBitmap).setHeight(200);
    107     Matrix m = new Matrix();
    108     m.postRotate(90);
    109     Bitmap newBitmap = Bitmap.createBitmap(originalBitmap, 0, 0, 100, 50, m, true);
    110 
    111     ShadowBitmap shadowBitmap = shadowOf(newBitmap);
    112     assertThat(shadowBitmap.getDescription())
    113         .isEqualTo("Original bitmap at (0,0) with width 100 and height 50" +
    114             " using matrix Matrix[pre=[], set={}, post=[rotate 90.0]] with filter");
    115     assertThat(shadowBitmap.getCreatedFromBitmap()).isEqualTo(originalBitmap);
    116     assertThat(shadowBitmap.getCreatedFromX()).isEqualTo(0);
    117     assertThat(shadowBitmap.getCreatedFromY()).isEqualTo(0);
    118     assertThat(shadowBitmap.getCreatedFromWidth()).isEqualTo(100);
    119     assertThat(shadowBitmap.getCreatedFromHeight()).isEqualTo(50);
    120     assertThat(shadowBitmap.getCreatedFromMatrix()).isEqualTo(m);
    121     assertThat(shadowBitmap.getCreatedFromFilter()).isEqualTo(true);
    122     assertThat(shadowBitmap.getWidth()).isEqualTo(50);
    123     assertThat(shadowBitmap.getHeight()).isEqualTo(100);
    124   }
    125 
    126   @Test
    127   public void shouldCreateMutableBitmap() throws Exception {
    128     Bitmap mutableBitmap = Bitmap.createBitmap(100, 200, Bitmap.Config.ARGB_8888);
    129     assertThat(mutableBitmap.isMutable()).isTrue();
    130   }
    131 
    132   @Test
    133   @Config(minSdk = JELLY_BEAN_MR1)
    134   public void shouldCreateMutableBitmapWithDisplayMetrics() throws Exception {
    135     final DisplayMetrics metrics = new DisplayMetrics();
    136     metrics.densityDpi = 1000;
    137 
    138     final Bitmap bitmap = Bitmap.createBitmap(metrics, 100, 100, Bitmap.Config.ARGB_8888);
    139     assertThat(bitmap.isMutable()).isTrue();
    140     assertThat(bitmap.getDensity()).isEqualTo(1000);
    141   }
    142 
    143   @Test
    144   public void shouldRecycleBitmap() throws Exception {
    145     Bitmap bitmap = Bitmap.createBitmap(100, 200, Bitmap.Config.ARGB_8888);
    146     bitmap.recycle();
    147     assertThat(bitmap.isRecycled()).isTrue();
    148   }
    149 
    150   @Test
    151   public void shouldReceiveDescriptionWhenDrawingToCanvas() throws Exception {
    152     Bitmap bitmap1 = create("Bitmap One");
    153     Bitmap bitmap2 = create("Bitmap Two");
    154 
    155     Canvas canvas = new Canvas(bitmap1);
    156     canvas.drawBitmap(bitmap2, 0, 0, null);
    157 
    158     assertThat(shadowOf(bitmap1).getDescription()).isEqualTo("Bitmap One\nBitmap Two");
    159   }
    160 
    161   @Test
    162   public void shouldReceiveDescriptionWhenDrawingToCanvasWithBitmapAndMatrixAndPaint() throws Exception {
    163     Bitmap bitmap1 = create("Bitmap One");
    164     Bitmap bitmap2 = create("Bitmap Two");
    165 
    166     Canvas canvas = new Canvas(bitmap1);
    167     canvas.drawBitmap(bitmap2, new Matrix(), null);
    168 
    169     assertThat(shadowOf(bitmap1).getDescription())
    170         .isEqualTo("Bitmap One\nBitmap Two transformed by Matrix[pre=[], set={}, post=[]]");
    171   }
    172 
    173   @Test
    174   public void shouldReceiveDescriptionWhenDrawABitmapToCanvasWithAPaintEffect() throws Exception {
    175     Bitmap bitmap1 = create("Bitmap One");
    176     Bitmap bitmap2 = create("Bitmap Two");
    177 
    178     Canvas canvas = new Canvas(bitmap1);
    179     Paint paint = new Paint();
    180     paint.setColorFilter(new ColorMatrixColorFilter(new ColorMatrix()));
    181     canvas.drawBitmap(bitmap2, new Matrix(), paint);
    182 
    183     assertThat(shadowOf(bitmap1).getDescription())
    184         .isEqualTo("Bitmap One\n" +
    185             "Bitmap Two with ColorMatrixColorFilter<1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0>" +
    186             " transformed by Matrix[pre=[], set={}, post=[]]");
    187   }
    188 
    189   @Test
    190   public void visualize_shouldReturnDescription() throws Exception {
    191     Bitmap bitmap = create("Bitmap One");
    192     assertThat(ShadowBitmap.visualize(bitmap))
    193         .isEqualTo("Bitmap One");
    194   }
    195 
    196   @Test
    197   public void shouldCopyBitmap() {
    198     Bitmap bitmap = Shadow.newInstanceOf(Bitmap.class);
    199     Bitmap bitmapCopy = bitmap.copy(Bitmap.Config.ARGB_8888, true);
    200     assertThat(shadowOf(bitmapCopy).getConfig()).isEqualTo(Bitmap.Config.ARGB_8888);
    201     assertThat(shadowOf(bitmapCopy).isMutable()).isTrue();
    202   }
    203 
    204   @Test(expected = NullPointerException.class)
    205   public void rowBytesIsAccurate() {
    206     Bitmap b1 = Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888);
    207     assertThat(b1.getRowBytes()).isEqualTo(40);
    208     Bitmap b2 = Bitmap.createBitmap(10, 10, Bitmap.Config.RGB_565);
    209     assertThat(b2.getRowBytes()).isEqualTo(20);
    210 
    211     // Null Bitmap.Config is not allowed.
    212     Bitmap b3 = Bitmap.createBitmap(10, 10, null);
    213     b3.getRowBytes();
    214   }
    215 
    216   @Test(expected = NullPointerException.class)
    217   @Config(minSdk = JELLY_BEAN_MR1)
    218   public void byteCountIsAccurate() {
    219     Bitmap b1 = Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888);
    220     assertThat(b1.getByteCount()).isEqualTo(400);
    221     Bitmap b2 = Bitmap.createBitmap(10, 10, Bitmap.Config.RGB_565);
    222     assertThat(b2.getByteCount()).isEqualTo(200);
    223 
    224     // Null Bitmap.Config is not allowed.
    225     Bitmap b3 = Bitmap.createBitmap(10, 10, null);
    226     b3.getByteCount();
    227   }
    228 
    229   @Test
    230   @Config(minSdk = JELLY_BEAN_MR1)
    231   public void shouldSetDensity() {
    232     final Bitmap bitmap = Bitmap.createBitmap(new DisplayMetrics(), 100, 100, Bitmap.Config.ARGB_8888);
    233     bitmap.setDensity(1000);
    234     assertThat(bitmap.getDensity()).isEqualTo(1000);
    235   }
    236 
    237   @Test
    238   public void shouldSetPixel() {
    239     Bitmap bitmap = Bitmap.createBitmap(new int[] { 1 }, 1, 1, Bitmap.Config.ARGB_8888);
    240     shadowOf(bitmap).setMutable(true);
    241     bitmap.setPixel(0, 0, 2);
    242     assertThat(bitmap.getPixel(0, 0)).isEqualTo(2);
    243     assertThat(shadowOf(bitmap).getCreatedFromColors()).isEqualTo(new int[] { 1 });
    244   }
    245 
    246   @Test
    247   public void shouldSetPixel_allocateOnTheFly() {
    248     Bitmap bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
    249     shadowOf(bitmap).setMutable(true);
    250     bitmap.setPixel(0, 0, 2);
    251     assertThat(bitmap.getPixel(0, 0)).isEqualTo(2);
    252     assertThat(shadowOf(bitmap).getCreatedFromColors()).isNull();
    253   }
    254 
    255   @Test
    256   public void testGetPixels() {
    257     // Create a dummy bitmap.
    258     Bitmap bmp = Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888);
    259     for (int y = 0; y < bmp.getHeight(); ++y) {
    260       for (int x = 0; x < bmp.getWidth(); ++x) {
    261         bmp.setPixel(x, y, packRGB(x, y, 0));
    262       }
    263     }
    264 
    265     // Use getPixels to get pixels as an array (getPixels was the missing Shadowed Function).
    266     int[] pixels = new int[bmp.getWidth() * bmp.getHeight()];
    267     bmp.getPixels(pixels, 0, bmp.getWidth(), 0, 0, bmp.getWidth(), bmp.getHeight());
    268 
    269     // Every entry should match regardless of accessing it by getPixel vs getPixels.
    270     for (int y = 0; y < bmp.getHeight(); ++y) {
    271       for (int x = 0; x < bmp.getWidth(); ++x) {
    272         assertThat(bmp.getPixel(x, y)).isEqualTo(pixels[y * bmp.getWidth() + x]);
    273       }
    274     }
    275   }
    276 
    277   @Test(expected = IllegalStateException.class)
    278   public void shouldThrowExceptionForSetPixelOnImmutableBitmap() {
    279     Bitmap bitmap = Bitmap.createBitmap(new int[] { 1 }, 1, 1, Bitmap.Config.ARGB_8888);
    280     bitmap.setPixel(0, 0, 2);
    281   }
    282 
    283   @Test
    284   public void bitmapsAreReused() {
    285     Bitmap b = Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888);
    286     Bitmap b1 = Bitmap.createBitmap(b, 0, 0, 10, 10);
    287     assertThat(b1).isSameAs(b);
    288     Bitmap b2 = Bitmap.createBitmap(b, 0, 0, 10, 10, null, false);
    289     assertThat(b2).isSameAs(b);
    290     Bitmap b3 = Bitmap.createScaledBitmap(b, 10, 10, false);
    291     assertThat(b3).isSameAs(b);
    292   }
    293 
    294   @Test
    295   public void equalsSizeTransformReturnsOriginal() {
    296     Bitmap b1 = Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888);
    297     Bitmap b2 = Bitmap.createBitmap(b1, 0, 0, 10, 10, null, false);
    298     assertThat(b1).isSameAs(b2);
    299     Bitmap b3 = Bitmap.createBitmap(b1, 0, 0, 10, 10, null, true);
    300     assertThat(b1).isSameAs(b3);
    301   }
    302 
    303   @Test(expected = IllegalArgumentException.class)
    304   public void throwsExceptionForInvalidDimensions() {
    305     Bitmap b = Bitmap.createBitmap(10, 20, Bitmap.Config.ARGB_8888);
    306     Bitmap.createBitmap(b, 0, 0, 20, 10, null, false);
    307   }
    308 
    309   @Test(expected = IllegalArgumentException.class)
    310   public void throwsExceptionForNegativeWidth() {
    311     Bitmap.createBitmap(-100, 10, Bitmap.Config.ARGB_8888);
    312   }
    313 
    314   @Test(expected = IllegalArgumentException.class)
    315   public void throwsExceptionForZeroHeight() {
    316     Bitmap.createBitmap(100, 0, Bitmap.Config.ARGB_8888);
    317   }
    318 
    319   @Test
    320   public void shouldGetPixelsFromAnyNonNullableCreatedBitmap() {
    321     Bitmap bitmap;
    322     int width = 10;
    323     int height = 10;
    324 
    325     int[] pixels = new int[width * height];
    326     bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
    327     bitmap.getPixels(pixels, 0, width, 0, 0, width, height);
    328 
    329     bitmap = Bitmap.createBitmap(bitmap);
    330     bitmap.getPixels(pixels, 0, width, 0, 0, width, height);
    331 
    332     bitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height);
    333     bitmap.getPixels(pixels, 0, width, 0, 0, width, height);
    334 
    335     bitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, new Matrix(), false);
    336     bitmap.getPixels(pixels, 0, width, 0, 0, width, height);
    337 
    338     bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
    339     bitmap.getPixels(pixels, 0, width, 0, 0, width, height);
    340 
    341     bitmap = Bitmap.createBitmap(pixels, width, height, Bitmap.Config.ARGB_8888);
    342     bitmap.getPixels(pixels, 0, width, 0, 0, width, height);
    343   }
    344 
    345   @Test
    346   public void shouldGetPixelsFromSubsetOfBitmap() {
    347     int width = 10;
    348     int height = 10;
    349     Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
    350     int offset = 7;
    351     int subWidth = 3;
    352     int subHeight = 4;
    353     int x = 2;
    354     int y = 5;
    355 
    356     // Fill a region of the bitmap with increasing redness.
    357     int r = 0;
    358     for (int y0 = y; y0 < y + subHeight; y0++) {
    359       for (int x0 = x; x0 < x + subWidth; x0++) {
    360         bitmap.setPixel(x0, y0, packRGB(r++, 0, 0));
    361       }
    362     }
    363 
    364     // Get the pixels from that region.
    365     int[] pixels = new int[offset + subWidth * subHeight];
    366     bitmap.getPixels(pixels, offset, subWidth, x, y, subWidth, subHeight);
    367 
    368     // Verify that pixels contains the expected colors.
    369     r = 0;
    370     int index = offset;
    371     for (int y0 = 0; y0 < subHeight; y0++) {
    372       for (int x0 = 0; x0 < subWidth; x0++) {
    373         assertThat(pixels[index++]).isEqualTo(packRGB(r++, 0, 0));
    374       }
    375     }
    376   }
    377 
    378   @Test
    379   public void shouldAdjustDimensionsForMatrix() {
    380     Bitmap transformedBitmap;
    381     int width = 10;
    382     int height = 20;
    383 
    384     Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
    385     Matrix matrix = new Matrix();
    386     transformedBitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, false);
    387     assertThat(transformedBitmap.getWidth())
    388         .isEqualTo(width);
    389     assertThat(transformedBitmap.getHeight())
    390         .isEqualTo(height);
    391 
    392     matrix.setRotate(90);
    393     transformedBitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, false);
    394     assertThat(transformedBitmap.getWidth())
    395         .isEqualTo(height);
    396     assertThat(transformedBitmap.getHeight())
    397         .isEqualTo(width);
    398 
    399     matrix.setScale(2, 3);
    400     transformedBitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, false);
    401     assertThat(transformedBitmap.getWidth())
    402         .isEqualTo(width * 2);
    403     assertThat(transformedBitmap.getHeight())
    404         .isEqualTo(height * 3);
    405   }
    406 
    407   @Test
    408   public void shouldWriteToParcelAndReconstruct() {
    409     Bitmap bitmapOriginal;
    410     int originalWidth = 10;
    411     int originalHeight = 10;
    412 
    413     bitmapOriginal = Bitmap.createBitmap(originalWidth, originalHeight, Bitmap.Config.ARGB_8888);
    414 
    415     Parcel parcel = Parcel.obtain();
    416     bitmapOriginal.writeToParcel(parcel, 0);
    417 
    418     parcel.setDataPosition(0);
    419 
    420     Bitmap bitmapReconstructed = Bitmap.CREATOR.createFromParcel(parcel);
    421 
    422     // get reconstructed properties
    423     int reconstructedHeight = bitmapReconstructed.getHeight();
    424     int reconstructedWidth = bitmapReconstructed.getWidth();
    425 
    426     //compare bitmap properties
    427     assertThat(originalHeight).isEqualTo(reconstructedHeight);
    428     assertThat(originalWidth).isEqualTo(reconstructedWidth);
    429     assertThat(bitmapOriginal.getConfig()).isEqualTo(bitmapReconstructed.getConfig());
    430 
    431     int[] pixelsOriginal = new int[originalWidth * originalHeight];
    432     bitmapOriginal.getPixels(pixelsOriginal, 0, originalWidth, 0, 0, originalWidth, originalHeight);
    433 
    434     int[] pixelsReconstructed = new int[reconstructedWidth * reconstructedHeight];
    435     bitmapReconstructed.getPixels(pixelsReconstructed, 0, reconstructedWidth, 0, 0,
    436         reconstructedWidth, reconstructedHeight);
    437 
    438     assertThat(Arrays.equals(pixelsOriginal, pixelsReconstructed)).isTrue();
    439   }
    440 
    441   @Test
    442   public void shouldCopyPixelsToBufferAndReconstruct() {
    443     int width = 10;
    444     int height = 10;
    445 
    446     Bitmap bitmapOriginal = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
    447     bitmapOriginal.setPixel(0, 0, 123);
    448     bitmapOriginal.setPixel(1, 1, 456);
    449     bitmapOriginal.setPixel(2, 2, 789);
    450     int[] pixelsOriginal = new int[width * height];
    451     bitmapOriginal.getPixels(pixelsOriginal, 0, width, 0, 0, width, height);
    452 
    453     ByteBuffer buffer = ByteBuffer.allocate(bitmapOriginal.getByteCount());
    454     bitmapOriginal.copyPixelsToBuffer(buffer);
    455     assertThat(buffer.position()).isEqualTo(bitmapOriginal.getByteCount());
    456 
    457     buffer.rewind();
    458     Bitmap bitmapReconstructed = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
    459     // Set some random pixels to ensure that they're properly overwritten.
    460     bitmapReconstructed.setPixel(1,1, 999);
    461     bitmapReconstructed.setPixel(4,4, 999);
    462     bitmapReconstructed.copyPixelsFromBuffer(buffer);
    463     assertThat(buffer.position()).isEqualTo(bitmapOriginal.getByteCount());
    464 
    465     assertThat(bitmapReconstructed.getPixel(0, 0)).isEqualTo(123);
    466     assertThat(bitmapReconstructed.getPixel(1, 1)).isEqualTo(456);
    467     assertThat(bitmapReconstructed.getPixel(2, 2)).isEqualTo(789);
    468 
    469     int[] pixelsReconstructed = new int[width * height];
    470     bitmapReconstructed.getPixels(pixelsReconstructed, 0, width, 0, 0, width, height);
    471     assertThat(Arrays.equals(pixelsOriginal, pixelsReconstructed)).isTrue();
    472   }
    473 
    474   @Config(sdk = Build.VERSION_CODES.O)
    475   @Test
    476   public void getBytesPerPixel_O() {
    477     assertThat(ShadowBitmap.getBytesPerPixel(Bitmap.Config.RGBA_F16)).isEqualTo(8);
    478   }
    479 
    480   @Test
    481   public void getBytesPerPixel_preO() {
    482     assertThat(ShadowBitmap.getBytesPerPixel(Bitmap.Config.ARGB_8888)).isEqualTo(4);
    483     assertThat(ShadowBitmap.getBytesPerPixel(Bitmap.Config.RGB_565)).isEqualTo(2);
    484     assertThat(ShadowBitmap.getBytesPerPixel(Bitmap.Config.ARGB_4444)).isEqualTo(2);
    485     assertThat(ShadowBitmap.getBytesPerPixel(Bitmap.Config.ALPHA_8)).isEqualTo(1);
    486   }
    487 
    488   @Test(expected = RuntimeException.class)
    489   public void throwsExceptionCopyPixelsToShortBuffer() {
    490     Bitmap bitmapOriginal = Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888);
    491     ShortBuffer buffer = ShortBuffer.allocate(bitmapOriginal.getByteCount());
    492     bitmapOriginal.copyPixelsToBuffer(buffer);
    493   }
    494 
    495   @Test(expected = RuntimeException.class)
    496   public void throwsExceptionCopyPixelsToIntBuffer() {
    497     Bitmap bitmapOriginal = Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888);
    498     IntBuffer buffer = IntBuffer.allocate(bitmapOriginal.getByteCount());
    499     bitmapOriginal.copyPixelsToBuffer(buffer);
    500   }
    501 
    502   @Test(expected = RuntimeException.class)
    503   public void throwsExceptionCopyPixelsToLongBuffer() {
    504     Bitmap bitmapOriginal = Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888);
    505     LongBuffer buffer = LongBuffer.allocate(bitmapOriginal.getByteCount());
    506     bitmapOriginal.copyPixelsToBuffer(buffer);
    507   }
    508 
    509   @Test(expected = RuntimeException.class)
    510   public void throwsExceptionCopyPixelsToBufferTooSmall() {
    511     Bitmap bitmapOriginal = Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888);
    512     ByteBuffer buffer = ByteBuffer.allocate(bitmapOriginal.getByteCount() - 1);
    513     bitmapOriginal.copyPixelsToBuffer(buffer);
    514   }
    515 
    516   @Test(expected = RuntimeException.class)
    517   public void throwsExceptionCopyPixelsToBufferNonArgb8888() {
    518     Bitmap bitmapOriginal = Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_4444);
    519     ByteBuffer buffer = ByteBuffer.allocate(bitmapOriginal.getByteCount());
    520     bitmapOriginal.copyPixelsToBuffer(buffer);
    521   }
    522 
    523   @Test(expected = RuntimeException.class)
    524   public void throwsExceptionCopyPixelsFromShortBuffer() {
    525     Bitmap bitmapOriginal = Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888);
    526     ShortBuffer buffer = ShortBuffer.allocate(bitmapOriginal.getByteCount());
    527     bitmapOriginal.copyPixelsFromBuffer(buffer);
    528   }
    529 
    530   @Test(expected = RuntimeException.class)
    531   public void throwsExceptionCopyPixelsFromIntBuffer() {
    532     Bitmap bitmapOriginal = Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888);
    533     IntBuffer buffer = IntBuffer.allocate(bitmapOriginal.getByteCount());
    534     bitmapOriginal.copyPixelsFromBuffer(buffer);
    535   }
    536 
    537   @Test(expected = RuntimeException.class)
    538   public void throwsExceptionCopyPixelsFromLongBuffer() {
    539     Bitmap bitmapOriginal = Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888);
    540     LongBuffer buffer = LongBuffer.allocate(bitmapOriginal.getByteCount());
    541     bitmapOriginal.copyPixelsFromBuffer(buffer);
    542   }
    543 
    544   @Test(expected = RuntimeException.class)
    545   public void throwsExceptionCopyPixelsFromBufferTooSmall() {
    546     Bitmap bitmapOriginal = Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888);
    547     ByteBuffer buffer = ByteBuffer.allocate(bitmapOriginal.getByteCount() - 1);
    548     bitmapOriginal.copyPixelsFromBuffer(buffer);
    549   }
    550 
    551   @Test(expected = RuntimeException.class)
    552   public void throwsExceptionCopyPixelsFromBufferNonArgb8888() {
    553     Bitmap bitmapOriginal = Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_4444);
    554     ByteBuffer buffer = ByteBuffer.allocate(bitmapOriginal.getByteCount());
    555     bitmapOriginal.copyPixelsFromBuffer(buffer);
    556   }
    557 
    558   @Test(expected = IllegalStateException.class)
    559   public void throwsExceptionCopyPixelsFromBufferRecycled() {
    560     Bitmap bitmapOriginal = Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888);
    561     ByteBuffer buffer = ByteBuffer.allocate(bitmapOriginal.getByteCount());
    562     bitmapOriginal.recycle();
    563     bitmapOriginal.copyPixelsFromBuffer(buffer);
    564   }
    565 
    566   @Config(sdk = Build.VERSION_CODES.KITKAT)
    567   @Test
    568   public void reconfigure_withArgb8888Bitmap_validDimensionsAndConfig_doesNotThrow() {
    569     Bitmap original = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
    570     original.reconfigure(100, 100, Bitmap.Config.ARGB_8888);
    571   }
    572 
    573   @Config(sdk = Build.VERSION_CODES.O)
    574   @Test(expected = IllegalStateException.class)
    575   public void reconfigure_withHardwareBitmap_validDimensionsAndConfig_throws() {
    576     Bitmap original = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
    577     ShadowBitmap shadowBitmap = Shadow.extract(original);
    578     shadowBitmap.setConfig(Bitmap.Config.HARDWARE);
    579 
    580     original.reconfigure(100, 100, Bitmap.Config.ARGB_8888);
    581   }
    582 
    583   @Config(sdk = Build.VERSION_CODES.KITKAT)
    584   @Test
    585   public void setPremultiplied() {
    586     Bitmap original = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
    587     assertThat(original.isPremultiplied()).isFalse();
    588     original.setPremultiplied(true);
    589     assertThat(original.isPremultiplied()).isTrue();
    590     original.setPremultiplied(false);
    591     assertThat(original.isPremultiplied()).isFalse();
    592   }
    593 
    594   @Test
    595   public void sameAs_bitmapsDifferentWidth() {
    596     Bitmap original1 = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
    597     Bitmap original2 = Bitmap.createBitmap(101, 100, Bitmap.Config.ARGB_8888);
    598     assertThat(original1.sameAs(original2)).isFalse();
    599   }
    600 
    601   @Test
    602   public void sameAs_bitmapsDifferentHeight() {
    603     Bitmap original1 = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
    604     Bitmap original2 = Bitmap.createBitmap(100, 101, Bitmap.Config.ARGB_8888);
    605     assertThat(original1.sameAs(original2)).isFalse();
    606   }
    607 
    608   @Test
    609   public void sameAs_bitmapsDifferentConfig() {
    610     Bitmap original1 = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
    611     Bitmap original2 = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_4444);
    612     assertThat(original1.sameAs(original2)).isFalse();
    613   }
    614 
    615   @Test
    616   public void sameAs_bitmapsDifferentPixels() {
    617     int[] pixels1 = new int[] {0, 1, 2, 3};
    618     Bitmap original1 = Bitmap.createBitmap(2, 2, Bitmap.Config.ARGB_8888);
    619     original1.setPixels(pixels1, 0, 1, 0, 0, 2, 2);
    620 
    621     int[] pixels2 = new int[] {3, 2, 1, 0};
    622     Bitmap original2 = Bitmap.createBitmap(2, 2, Bitmap.Config.ARGB_8888);
    623     original2.setPixels(pixels2, 0, 1, 0, 0, 2, 2);
    624     assertThat(original1.sameAs(original2)).isFalse();
    625   }
    626 
    627   @Test
    628   public void sameAs_bitmapsSamePixels() {
    629     int[] pixels = new int[] {0, 1, 2, 3};
    630     Bitmap original1 = Bitmap.createBitmap(2, 2, Bitmap.Config.ARGB_8888);
    631     original1.setPixels(pixels, 0, 1, 0, 0, 2, 2);
    632 
    633     Bitmap original2 = Bitmap.createBitmap(2, 2, Bitmap.Config.ARGB_8888);
    634     original2.setPixels(pixels, 0, 1, 0, 0, 2, 2);
    635     assertThat(original1.sameAs(original2)).isTrue();
    636   }
    637 
    638   private static Bitmap create(String name) {
    639     Bitmap bitmap = Shadow.newInstanceOf(Bitmap.class);
    640     shadowOf(bitmap).appendDescription(name);
    641     return bitmap;
    642   }
    643 
    644   private static int packRGB(int r, int g, int b) {
    645     return 0xff000000 | r << 16 | g << 8 | b;
    646   }
    647 }
    648