/** * Returns the resource id that this {@code BitmapDrawable} was loaded from. This lets * your tests assert that the bitmap is correct without having to actually load the bitmap. * * @return resource id from which this {@code BitmapDrawable} was loaded * @deprecated use ShadowBitmap#getCreatedFromResId() instead. */ @Deprecated @Override public int getCreatedFromResId() { ShadowBitmap shadowBitmap = Shadow.extract(realBitmapDrawable.getBitmap()); return shadowBitmap.getCreatedFromResId(); }
@Implementation protected static Bitmap createScaledBitmap( Bitmap src, int dstWidth, int dstHeight, boolean filter) { if (dstWidth == src.getWidth() && dstHeight == src.getHeight() && !filter) { return src; // Return the original. } Bitmap scaledBitmap = ReflectionHelpers.callConstructor(Bitmap.class); ShadowBitmap shadowBitmap = Shadow.extract(scaledBitmap); ShadowBitmap shadowSrcBitmap = Shadow.extract(src); shadowBitmap.appendDescription(shadowSrcBitmap.getDescription()); shadowBitmap.appendDescription(" scaled to " + dstWidth + " x " + dstHeight); if (filter) { shadowBitmap.appendDescription(" with filter " + filter); } shadowBitmap.createdFromBitmap = src; shadowBitmap.createdFromFilter = filter; shadowBitmap.width = dstWidth; shadowBitmap.height = dstHeight; shadowBitmap.setPixels(new int[shadowBitmap.getHeight() * shadowBitmap.getWidth()], 0, 0, 0, 0, shadowBitmap.getWidth(), shadowBitmap.getHeight()); return scaledBitmap; }
@Implementation(minSdk = JELLY_BEAN_MR1) protected static Bitmap createBitmap( DisplayMetrics displayMetrics, int width, int height, Bitmap.Config config) { if (width <= 0 || height <= 0) { throw new IllegalArgumentException("width and height must be > 0"); } Bitmap scaledBitmap = ReflectionHelpers.callConstructor(Bitmap.class); ShadowBitmap shadowBitmap = Shadow.extract(scaledBitmap); shadowBitmap.setDescription("Bitmap (" + width + " x " + height + ")"); shadowBitmap.width = width; shadowBitmap.height = height; shadowBitmap.config = config; shadowBitmap.setMutable(true); if (displayMetrics != null) { shadowBitmap.density = displayMetrics.densityDpi; } shadowBitmap.setPixels(new int[shadowBitmap.getHeight() * shadowBitmap.getWidth()], 0, shadowBitmap.getWidth(), 0, 0, shadowBitmap.getWidth(), shadowBitmap.getHeight()); return scaledBitmap; }
@Implementation protected void setPixel(int x, int y, int color) { if (isRecycled()) { throw new IllegalStateException("Can't call setPixel() on a recycled bitmap"); } else if (!isMutable()) { throw new IllegalStateException("Bitmap is immutable"); } internalCheckPixelAccess(x, y); if (colors == null) { colors = new int[getWidth() * getHeight()]; } colors[y * getWidth() + x] = color; }
@Implementation protected Bitmap extractAlpha() { int[] alphaPixels = new int[colors.length]; for (int i = 0; i < alphaPixels.length; i++) { alphaPixels[i] = Color.alpha(colors[i]); } return createBitmap(alphaPixels, getWidth(), getHeight(), Bitmap.Config.ALPHA_8); }
@Implementation protected int getRowBytes() { return getBytesPerPixel(config) * getWidth(); }
public static Bitmap create(final String name, final BitmapFactory.Options options, final Point widthAndHeight) { Bitmap bitmap = Shadow.newInstanceOf(Bitmap.class); ShadowBitmap shadowBitmap = Shadow.extract(bitmap); shadowBitmap.appendDescription(name == null ? "Bitmap" : "Bitmap for " + name); config = Bitmap.Config.ARGB_8888; shadowBitmap.setConfig(config); shadowBitmap.appendDescription(" with options "); shadowBitmap.appendDescription(optionsString); shadowBitmap.setWidth(p.x); shadowBitmap.setHeight(p.y); shadowBitmap.setPixels(new int[p.x * p.y], 0, 0, 0, 0, p.x, p.y); if (options != null) { options.outWidth = p.x;
@Test public void shouldCreateBitmapWithMatrix() { Bitmap originalBitmap = create("Original bitmap"); shadowOf(originalBitmap).setWidth(200); shadowOf(originalBitmap).setHeight(200); Matrix m = new Matrix(); m.postRotate(90); Bitmap newBitmap = Bitmap.createBitmap(originalBitmap, 0, 0, 100, 50, m, true); ShadowBitmap shadowBitmap = shadowOf(newBitmap); assertThat(shadowBitmap.getDescription()) .isEqualTo("Original bitmap at (0,0) with width 100 and height 50" + " using matrix Matrix[pre=[], set={}, post=[rotate 90.0]] with filter"); assertThat(shadowBitmap.getCreatedFromBitmap()).isEqualTo(originalBitmap); assertThat(shadowBitmap.getCreatedFromX()).isEqualTo(0); assertThat(shadowBitmap.getCreatedFromY()).isEqualTo(0); assertThat(shadowBitmap.getCreatedFromWidth()).isEqualTo(100); assertThat(shadowBitmap.getCreatedFromHeight()).isEqualTo(50); assertThat(shadowBitmap.getCreatedFromMatrix()).isEqualTo(m); assertThat(shadowBitmap.getCreatedFromFilter()).isEqualTo(true); assertThat(shadowBitmap.getWidth()).isEqualTo(50); assertThat(shadowBitmap.getHeight()).isEqualTo(100); }
static void assertBitmapsEqual(Bitmap a, Bitmap b) { if (a.getHeight() != b.getHeight()) { fail(); } if (a.getWidth() != b.getWidth()) { fail(); } ShadowBitmap shadowA = shadowOf(a); ShadowBitmap shadowB = shadowOf(b); if (!Objects.equals(shadowA.getDescription(), shadowB.getDescription())) { fail(); } } }
private static Bitmap createHardwareBitmap(int width, int height) { Bitmap bitmap = Bitmap.createBitmap(width, height, Config.HARDWARE); ShadowBitmap shadowBitmap = Shadow.extract(bitmap); shadowBitmap.setMutable(false); return bitmap; } }
public void setCreatedFromResId(int resId, String description) { this.createdFromResId = resId; appendDescription(" for resource:" + description); }
@Implementation protected static Bitmap createBitmap(Bitmap src, int x, int y, int width, int height) { if (x == 0 && y == 0 && width == src.getWidth() && height == src.getHeight()) { return src; // Return the original. } Bitmap newBitmap = ReflectionHelpers.callConstructor(Bitmap.class); ShadowBitmap shadowBitmap = Shadow.extract(newBitmap); ShadowBitmap shadowSrcBitmap = Shadow.extract(src); shadowBitmap.appendDescription(shadowSrcBitmap.getDescription()); shadowBitmap.appendDescription(" at (" + x + "," + y); shadowBitmap.appendDescription(" with width " + width + " and height " + height); shadowBitmap.createdFromBitmap = src; shadowBitmap.createdFromX = x; shadowBitmap.createdFromY = y; shadowBitmap.createdFromWidth = width; shadowBitmap.createdFromHeight = height; shadowBitmap.width = width; shadowBitmap.height = height; return newBitmap; }
private void internalCheckPixelAccess(int x, int y) { if (x < 0) { throw new IllegalArgumentException("x must be >= 0"); } if (y < 0) { throw new IllegalArgumentException("y must be >= 0"); } if (x >= getWidth()) { throw new IllegalArgumentException("x must be < bitmap.width()"); } if (y >= getHeight()) { throw new IllegalArgumentException("y must be < bitmap.height()"); } } }
@Implementation(minSdk = JELLY_BEAN_MR1) protected static Bitmap createBitmap( DisplayMetrics displayMetrics, int width, int height, Bitmap.Config config, boolean hasAlpha) { return createBitmap((DisplayMetrics) null, width, height, config); }
@Test public void decodeResource_shouldSetDescriptionAndCreatedFrom() { Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.an_image); ShadowBitmap shadowBitmap = shadowOf(bitmap); assertEquals("Bitmap for resource:org.robolectric:drawable/an_image", shadowBitmap.getDescription()); assertEquals(R.drawable.an_image, shadowBitmap.getCreatedFromResId()); assertEquals(64, bitmap.getWidth()); assertEquals(53, bitmap.getHeight()); }
@Implementation public static Bitmap createBitmap(int width, int height, Bitmap.Config config) { Bitmap bitmap = ShadowBitmap.createBitmap(width, height, config); Shadows.shadowOf(bitmap).setMutable(true); return bitmap; } }
@Implementation protected void copyPixelsToBuffer(Buffer dst) { // Ensure that the Bitmap uses 4 bytes per pixel, since we always use 4 bytes per pixels // internally. Clients of this API probably expect that the buffer size must be >= // getByteCount(), but if we don't enforce this restriction then for RGB_4444 and other // configs that value would be smaller then the buffer size we actually need. if (getBytesPerPixel(config) != INTERNAL_BYTES_PER_PIXEL) { throw new RuntimeException("Not implemented: only Bitmaps with " + INTERNAL_BYTES_PER_PIXEL + " bytes per pixel are supported"); } if (!(dst instanceof ByteBuffer)) { throw new RuntimeException("Not implemented: unsupported Buffer subclass"); } ByteBuffer byteBuffer = (ByteBuffer) dst; for (int color : colors) { byteBuffer.putInt(color); } }
@Implementation(minSdk = KITKAT) protected final int getAllocationByteCount() { return getRowBytes() * getHeight(); }
@Implementation protected void copyPixelsFromBuffer(Buffer dst) { if (isRecycled()) { throw new IllegalStateException("Can't call copyPixelsFromBuffer() on a recycled bitmap"); } // See the related comment in #copyPixelsToBuffer(Buffer). if (getBytesPerPixel(config) != INTERNAL_BYTES_PER_PIXEL) { throw new RuntimeException("Not implemented: only Bitmaps with " + INTERNAL_BYTES_PER_PIXEL + " bytes per pixel are supported"); } if (!(dst instanceof ByteBuffer)) { throw new RuntimeException("Not implemented: unsupported Buffer subclass"); } ByteBuffer byteBuffer = (ByteBuffer) dst; if (byteBuffer.remaining() < colors.length * INTERNAL_BYTES_PER_PIXEL) { throw new RuntimeException("Buffer not large enough for pixels"); } for (int i = 0; i < colors.length; i++) { colors[i] = byteBuffer.getInt(); } }
@Implementation protected int getPixel(int x, int y) { internalCheckPixelAccess(x, y); if (colors != null) { // Note that getPixel() returns a non-premultiplied ARGB value; if // config is RGB_565, our return value will likely be more precise than // on a physical device, since it needs to map each color component from // 5 or 6 bits to 8 bits. return colors[y * getWidth() + x]; } else { return 0; } }