Skip to content

Commit

Permalink
Add support for passing through Bitmaps and Drawables.
Browse files Browse the repository at this point in the history
  • Loading branch information
sjudd committed Oct 23, 2017
1 parent f7a939e commit 7663c21
Show file tree
Hide file tree
Showing 7 changed files with 207 additions and 39 deletions.
7 changes: 7 additions & 0 deletions library/src/main/java/com/bumptech/glide/Glide.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,11 @@
import com.bumptech.glide.load.resource.bitmap.Downsampler;
import com.bumptech.glide.load.resource.bitmap.ResourceBitmapDecoder;
import com.bumptech.glide.load.resource.bitmap.StreamBitmapDecoder;
import com.bumptech.glide.load.resource.bitmap.UnitBitmapDecoder;
import com.bumptech.glide.load.resource.bitmap.VideoBitmapDecoder;
import com.bumptech.glide.load.resource.bytes.ByteBufferRewinder;
import com.bumptech.glide.load.resource.drawable.ResourceDrawableDecoder;
import com.bumptech.glide.load.resource.drawable.UnitDrawableDecoder;
import com.bumptech.glide.load.resource.file.FileDecoder;
import com.bumptech.glide.load.resource.gif.ByteBufferGifDecoder;
import com.bumptech.glide.load.resource.gif.GifDrawable;
Expand Down Expand Up @@ -321,6 +323,9 @@ private static GeneratedAppGlideModule getAnnotationGeneratedGlideModules() {
.append(Registry.BUCKET_BITMAP, InputStream.class, Bitmap.class, streamBitmapDecoder)
.append(
Registry.BUCKET_BITMAP, ParcelFileDescriptor.class, Bitmap.class, videoBitmapDecoder)
.append(
Registry.BUCKET_BITMAP, Bitmap.class, Bitmap.class, new UnitBitmapDecoder(bitmapPool))
.append(Bitmap.class, Bitmap.class, UnitModelLoader.Factory.<Bitmap>getInstance())
.append(Bitmap.class, bitmapEncoder)
/* BitmapDrawables */
.append(
Expand Down Expand Up @@ -406,6 +411,8 @@ Uri.class, Bitmap.class, new ResourceBitmapDecoder(resourceDrawableDecoder, bitm
.append(byte[].class, ByteBuffer.class, new ByteArrayLoader.ByteBufferFactory())
.append(byte[].class, InputStream.class, new ByteArrayLoader.StreamFactory())
.append(Uri.class, Uri.class, UnitModelLoader.Factory.<Uri>getInstance())
.append(Drawable.class, Drawable.class, UnitModelLoader.Factory.<Drawable>getInstance())
.append(Drawable.class, Drawable.class, new UnitDrawableDecoder(bitmapPool))
/* Transcoders */
.register(
Bitmap.class,
Expand Down
56 changes: 55 additions & 1 deletion library/src/main/java/com/bumptech/glide/RequestBuilder.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package com.bumptech.glide;

import static com.bumptech.glide.request.RequestOptions.diskCacheStrategyOf;
import static com.bumptech.glide.request.RequestOptions.signatureOf;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.support.annotation.CheckResult;
import android.support.annotation.DrawableRes;
Expand Down Expand Up @@ -317,7 +320,58 @@ private RequestBuilder<TranscodeType> loadGeneric(@Nullable Object model) {
}

/**
* Returns a request builder to load the given {@link java.lang.String}. signature.
* Returns a request builder to load the given {@link Bitmap}.
*
* <p>{@link Bitmap}s provided to this method become owned by Glide. The {@link Bitmap} may be
* recycled or re-used at any time. If you do not own the Bitmap or you need to continue to use
* the {@link Bitmap} after passing it in to Glide, consider passing a copy of the {@link Bitmap}
* to Glide instead. It's almost always better to allow Glide to load {@link Bitmap}s than
* pass {@link Bitmap}s into Glide. If you have a custom way to obtain {@link Bitmap}s that is
* not supported by Glide, consider registering a custom
* {@link com.bumptech.glide.load.model.ModelLoader} or
* {@link com.bumptech.glide.load.ResourceDecoder} instead.
*
* <p>The {@link DiskCacheStrategy} is set to {@link DiskCacheStrategy#NONE}. Using other
* strategies may result in undefined behavior.
*
* <p>In memory caching relies on Object equality. The contents of the {@link Bitmap}s are not
* compared.
*
* @see #load(Object)
*/
@CheckResult
public RequestBuilder<TranscodeType> load(@Nullable Bitmap bitmap) {
return loadGeneric(bitmap)
.apply(diskCacheStrategyOf(DiskCacheStrategy.NONE));
}

/**
* Returns a request builder to load the given {@link Drawable}.
*
* <p>{@link Drawable}s provided to this method become owned by Glide. They or {@link Bitmap}s
* they contain may be recycled or re-used at any time. If you do not own the {@link Drawable},
* do not pass it in to Glide. It's almost always better to allow Glide to load {@link Bitmap}s
* than pass {@link Bitmap}s into Glide. If you have a custom way to obtain {@link Bitmap}s that
* is not supported by Glide, consider registering a custom
* {@link com.bumptech.glide.load.model.ModelLoader} or
* {@link com.bumptech.glide.load.ResourceDecoder} instead.
*
* <p>The {@link DiskCacheStrategy} is set to {@link DiskCacheStrategy#NONE}. Using other
* strategies may result in undefined behavior.
*
* <p>In memory caching relies on Object equality. The contents of the {@link Drawable}s are not
* compared.
*
* @see #load(Object)
*/
@CheckResult
public RequestBuilder<TranscodeType> load(@Nullable Drawable drawable) {
return loadGeneric(drawable)
.apply(diskCacheStrategyOf(DiskCacheStrategy.NONE));
}

/**
* Returns a request builder to load the given {@link java.lang.String}.
*
* <p> Note - this method caches data using only the given String as the cache key. If the data is
* a Uri outside of your control, or you otherwise expect the data represented by the given String
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.bumptech.glide.load.resource.bitmap;

import android.graphics.Bitmap;
import android.support.annotation.Nullable;
import com.bumptech.glide.load.Options;
import com.bumptech.glide.load.ResourceDecoder;
import com.bumptech.glide.load.engine.Resource;
import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;
import java.io.IOException;

public final class UnitBitmapDecoder implements ResourceDecoder<Bitmap, Bitmap> {

private final BitmapPool bitmapPool;

public UnitBitmapDecoder(BitmapPool bitmapPool) {
this.bitmapPool = bitmapPool;
}

@Override
public boolean handles(Bitmap source, Options options) throws IOException {
return true;
}

@Nullable
@Override
public Resource<Bitmap> decode(Bitmap source, int width, int height, Options options)
throws IOException {
return new BitmapResource(source, bitmapPool);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package com.bumptech.glide.load.resource.drawable;

import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import com.bumptech.glide.load.engine.Resource;
import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;
import com.bumptech.glide.load.resource.bitmap.BitmapDrawableResource;

/**
* Handles generic {@link Drawable} types where we may be uncertain of their size or type.
*/
final class DrawableResourceImpl extends DrawableResource<Drawable> {

@SuppressWarnings("unchecked")
public static Resource<Drawable> newInstance(Drawable drawable, BitmapPool bitmapPool) {
if (drawable instanceof BitmapDrawable) {
BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
return (Resource<Drawable>) (Resource<? extends Drawable>)
new BitmapDrawableResource(bitmapDrawable, bitmapPool);
}
return new DrawableResourceImpl(drawable);
}

private DrawableResourceImpl(Drawable drawable) {
super(drawable);
}

@SuppressWarnings("unchecked")
@Override
public Class<Drawable> getResourceClass() {
return (Class<Drawable>) drawable.getClass();
}

@Override
public int getSize() {
// 4 bytes per pixel for ARGB_8888 Bitmaps is something of a reasonable approximation. If
// there are no intrinsic bounds, we can fall back just to 1.
return Math.max(1, drawable.getIntrinsicWidth() * drawable.getIntrinsicHeight() * 4);
}

@Override
public void recycle() {
// Do nothing.
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.support.annotation.DrawableRes;
Expand All @@ -12,7 +11,6 @@
import com.bumptech.glide.load.ResourceDecoder;
import com.bumptech.glide.load.engine.Resource;
import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;
import com.bumptech.glide.load.resource.bitmap.BitmapDrawableResource;
import java.io.IOException;
import java.util.List;

Expand Down Expand Up @@ -56,17 +54,7 @@ public Resource<Drawable> decode(Uri source, int width, int height, Options opti
? context : getContextForPackage(source, packageName);
// We can't get a theme from another application.
Drawable drawable = DrawableDecoderCompat.getDrawable(toUse, resId);
return getDrawableResource(drawable);
}

@SuppressWarnings("unchecked")
private Resource<Drawable> getDrawableResource(Drawable drawable) {
if (drawable instanceof BitmapDrawable) {
BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
return (Resource<Drawable>) (Resource<? extends Drawable>)
new BitmapDrawableResource(bitmapDrawable, bitmapPool);
}
return new InternalDrawableResource(drawable);
return DrawableResourceImpl.newInstance(drawable, bitmapPool);
}

@NonNull
Expand Down Expand Up @@ -103,29 +91,4 @@ private int loadResourceIdFromUri(Uri source) {
}
return result;
}

private static final class InternalDrawableResource extends DrawableResource<Drawable> {

InternalDrawableResource(Drawable drawable) {
super(drawable);
}

@SuppressWarnings("unchecked")
@Override
public Class<Drawable> getResourceClass() {
return (Class<Drawable>) drawable.getClass();
}

@Override
public int getSize() {
// 4 bytes per pixel for ARGB_8888 Bitmaps is something of a reasonable approximation. If
// there are no intrinsic bounds, we can fall back just to 1.
return Math.max(1, drawable.getIntrinsicWidth() * drawable.getIntrinsicHeight() * 4);
}

@Override
public void recycle() {
// Do nothing.
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.bumptech.glide.load.resource.drawable;

import android.graphics.drawable.Drawable;
import android.support.annotation.Nullable;
import com.bumptech.glide.load.Options;
import com.bumptech.glide.load.ResourceDecoder;
import com.bumptech.glide.load.engine.Resource;
import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;
import java.io.IOException;

/**
* Passes through a {@link Drawable} as a {@link Drawable} based {@link Resource}.
*/
public class UnitDrawableDecoder implements ResourceDecoder<Drawable, Drawable> {
private final BitmapPool bitmapPool;

public UnitDrawableDecoder(BitmapPool bitmapPool) {
this.bitmapPool = bitmapPool;
}

@Override
public boolean handles(Drawable source, Options options) throws IOException {
return true;
}

@Nullable
@Override
public Resource<Drawable> decode(Drawable source, int width, int height, Options options)
throws IOException {
return DrawableResourceImpl.newInstance(source, bitmapPool);
}
}
37 changes: 37 additions & 0 deletions library/src/test/java/com/bumptech/glide/GlideTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
import static com.bumptech.glide.request.RequestOptions.decodeTypeOf;
import static com.bumptech.glide.request.RequestOptions.errorOf;
import static com.bumptech.glide.request.RequestOptions.placeholderOf;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.eq;
import static org.mockito.Matchers.isA;
Expand Down Expand Up @@ -70,6 +72,7 @@
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.robolectric.RobolectricTestRunner;
Expand Down Expand Up @@ -554,6 +557,40 @@ public void testNullModelPrefersErrorDrawable() {
verify(target).onLoadFailed(eq(error));
}

@Test
public void testLoadBitmap_asBitmap() {
Bitmap bitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
requestManager
.asBitmap()
.load(bitmap)
.into(target);

verify(target).onResourceReady(eq(bitmap), any(Transition.class));
}

@Test
public void testLoadBitmap_asDrawable() {
Bitmap bitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
requestManager
.load(bitmap)
.into(target);

ArgumentCaptor<Object> captor = ArgumentCaptor.forClass(Object.class);
verify(target).onResourceReady(captor.capture(), any(Transition.class));
BitmapDrawable drawable = (BitmapDrawable) captor.getValue();
assertThat(drawable.getBitmap()).isEqualTo(bitmap);
}

@Test
public void testLoadDrawable() {
Drawable drawable = new ColorDrawable(Color.RED);
requestManager
.load(drawable)
.into(target);

verify(target).onResourceReady(eq(drawable), any(Transition.class));
}

@Test
public void testNullModelPrefersFallbackDrawable() {
Drawable placeholder = new ColorDrawable(Color.GREEN);
Expand Down

0 comments on commit 7663c21

Please sign in to comment.