提交 fc4a4560 编写于 作者: S Sam Judd

Add a decoder that can retrieve Bitmaps from most types of Drawables.

上级 706a681e
......@@ -22,13 +22,18 @@ import java.util.Set;
import java.util.concurrent.ExecutionException;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class)
public class NonBitmapDrawableResourcesTest {
private Context context;
@Rule
public ExpectedException expectedException = ExpectedException.none();
@Before
public void setUp() {
context = InstrumentationRegistry.getTargetContext();
......@@ -70,6 +75,17 @@ public class NonBitmapDrawableResourcesTest {
assertThat(drawable).isNotNull();
}
@Test
public void load_withBitmapAliasResourceId_asBitmap_producesNonNullBitmap()
throws ExecutionException, InterruptedException {
Bitmap bitmap = Glide.with(context)
.asBitmap()
.load(ResourceIds.drawable.bitmap_alias)
.submit()
.get();
assertThat(bitmap).isNotNull();
}
@Test
public void load_withShapeDrawableResourceId_asDrawable_producesNonNullDrawable()
throws ExecutionException, InterruptedException {
......@@ -80,6 +96,30 @@ public class NonBitmapDrawableResourcesTest {
assertThat(drawable).isNotNull();
}
@Test
public void load_withShapeDrawableResourceId_asBitmap_withSizeOriginal_fails()
throws ExecutionException, InterruptedException {
expectedException.expect(ExecutionException.class);
Glide.with(context)
.asBitmap()
.load(ResourceIds.drawable.shape_drawable)
.submit()
.get();
}
@Test
public void load_withShapeDrawableResourceId_asBitmap_withValidSize_returnsNonNullBitmap()
throws ExecutionException, InterruptedException {
Bitmap bitmap = Glide.with(context)
.asBitmap()
.load(ResourceIds.drawable.shape_drawable)
.submit(100, 200)
.get();
assertThat(bitmap).isNotNull();
assertThat(bitmap.getWidth()).isEqualTo(100);
assertThat(bitmap.getHeight()).isEqualTo(200);
}
@Test
public void load_withStateListDrawableResourceId_asDrawable_producesNonNullDrawable()
throws ExecutionException, InterruptedException {
......@@ -90,6 +130,17 @@ public class NonBitmapDrawableResourcesTest {
assertThat(drawable).isNotNull();
}
@Test
public void load_withStateListDrawableResourceId_asBitmap_producesNonNullBitmap()
throws ExecutionException, InterruptedException {
Bitmap bitmap = Glide.with(context)
.asBitmap()
.load(ResourceIds.drawable.state_list_drawable)
.submit()
.get();
assertThat(bitmap).isNotNull();
}
@Test
public void load_withVectorDrawableResourceId_asDrawable_producesNonNullDrawable()
throws ExecutionException, InterruptedException {
......@@ -100,6 +151,17 @@ public class NonBitmapDrawableResourcesTest {
assertThat(drawable).isNotNull();
}
@Test
public void load_withVectorDrawableResourceId_asBitmap_producesNonNullBitmap()
throws ExecutionException, InterruptedException {
Bitmap bitmap = Glide.with(context)
.asBitmap()
.load(ResourceIds.drawable.vector_drawable)
.submit()
.get();
assertThat(bitmap).isNotNull();
}
@Test
public void load_withNinePatchResourceId_asDrawable_producesNonNullDrawable()
throws ExecutionException, InterruptedException {
......@@ -111,6 +173,19 @@ public class NonBitmapDrawableResourcesTest {
assertThat(drawable).isNotNull();
}
@Test
public void load_withNinePatchResourceId_asBitmap_producesNonNullBitmap()
throws ExecutionException, InterruptedException {
Bitmap bitmap = Glide.with(context)
.asBitmap()
.load(ResourceIds.drawable.googlelogo_color_120x44dp)
.submit()
.get();
assertThat(bitmap).isNotNull();
}
@Test
public void load_withApplicationIconResourceIdUri_asDrawable_producesNonNullDrawable()
throws NameNotFoundException, ExecutionException, InterruptedException {
......@@ -131,6 +206,27 @@ public class NonBitmapDrawableResourcesTest {
}
}
@Test
public void load_withApplicationIconResourceIdUri_asBitmap_producesNonNullBitmap()
throws NameNotFoundException, ExecutionException, InterruptedException {
for (String packageName : getInstalledPackages()) {
int iconResourceId = getResourceId(packageName);
Uri uri = new Uri.Builder()
.scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
.authority(packageName)
.path(String.valueOf(iconResourceId))
.build();
Bitmap bitmap = Glide.with(context)
.asBitmap()
.load(uri)
.submit()
.get();
assertThat(bitmap).isNotNull();
}
}
@Test
public void load_withApplicationIconResourceNameUri_asDrawable_producesNonNullDrawable()
throws ExecutionException, InterruptedException, NameNotFoundException {
......@@ -155,6 +251,31 @@ public class NonBitmapDrawableResourcesTest {
}
}
@Test
public void load_withApplicationIconResourceNameUri_asBitmap_producesNonNullBitmap()
throws ExecutionException, InterruptedException, NameNotFoundException {
for (String packageName : getInstalledPackages()) {
int iconResourceId = getResourceId(packageName);
Context toUse = context.createPackageContext(packageName, /*flags=*/ 0);
Resources resources = toUse.getResources();
Uri uri = new Uri.Builder()
.scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
.authority(packageName)
.path(resources.getResourceTypeName(iconResourceId))
.path(resources.getResourceEntryName(iconResourceId))
.path(String.valueOf(iconResourceId))
.build();
Bitmap bitmap = Glide.with(context)
.asBitmap()
.load(uri)
.submit()
.get();
assertThat(bitmap).isNotNull();
}
}
private Set<String> getInstalledPackages() {
Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
......
......@@ -52,6 +52,7 @@ import com.bumptech.glide.load.resource.bitmap.BitmapEncoder;
import com.bumptech.glide.load.resource.bitmap.ByteBufferBitmapDecoder;
import com.bumptech.glide.load.resource.bitmap.DefaultImageHeaderParser;
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.VideoBitmapDecoder;
import com.bumptech.glide.load.resource.bytes.ByteBufferRewinder;
......@@ -333,6 +334,8 @@ public class Glide implements ComponentCallbacks2 {
new GifFrameResourceDecoder(bitmapPool))
/* Drawables */
.append(Uri.class, Drawable.class, new ResourceDrawableDecoder(context))
.append(Uri.class, Bitmap.class,
new ResourceBitmapDecoder(new ResourceDrawableDecoder(context), bitmapPool))
/* Files */
.register(new ByteBufferRewinder.Factory())
.append(File.class, ByteBuffer.class, new ByteBufferFileLoader.Factory())
......
package com.bumptech.glide.load.resource.bitmap;
import android.content.ContentResolver;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.drawable.Animatable;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
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 com.bumptech.glide.load.resource.drawable.ResourceDrawableDecoder;
import com.bumptech.glide.request.target.Target;
import java.io.IOException;
/**
* Decodes {@link Bitmap}s from resource ids.
*
* <p>The framework will decode some resources as {@link Drawable}s that do not wrap
* {@link Bitmap}s. This decoder will attempt to return a {@link Bitmap} for those
* {@link Drawable}s anyway by drawing the {@link Drawable} to a {@link Canvas}s using
* the {@link Drawable}'s intrinsic bounds or the dimensions provided to
* {@link #decode(Object, int, int, Options)}.
*
* <p>For non-{@link Bitmap} {@link Drawable}s that return <= 0 for
* {@link Drawable#getIntrinsicWidth()} and/or {@link Drawable#getIntrinsicHeight()}, this
* decoder will fail if the width and height provided to {@link #decode(Object, int, int, Options)}
* are {@link Target#SIZE_ORIGINAL}.
*/
public class ResourceBitmapDecoder implements ResourceDecoder<Uri, Bitmap> {
private final ResourceDrawableDecoder drawableDecoder;
private final BitmapPool bitmapPool;
public ResourceBitmapDecoder(ResourceDrawableDecoder drawableDecoder, BitmapPool bitmapPool) {
this.drawableDecoder = drawableDecoder;
this.bitmapPool = bitmapPool;
}
@Override
public boolean handles(Uri source, Options options) throws IOException {
return ContentResolver.SCHEME_ANDROID_RESOURCE.equals(source.getScheme());
}
@Nullable
@Override
public Resource<Bitmap> decode(Uri source, int width, int height, Options options)
throws IOException {
Resource<Drawable> drawableResource = drawableDecoder.decode(source, width, height, options);
if (drawableResource == null) {
return null;
}
// Handle DrawableContainer or StateListDrawables that may contain one or more BitmapDrawables.
Drawable drawable = drawableResource.get().getCurrent();
Bitmap result = null;
if (drawable instanceof BitmapDrawable) {
result = ((BitmapDrawable) drawable).getBitmap();
} else if (!(drawable instanceof Animatable)) {
result = drawToBitmap(drawable, width, height);
}
if (result == null) {
return null;
}
return new BitmapResource(result, bitmapPool);
}
private Bitmap drawToBitmap(Drawable drawable, int width, int height) {
if (width == Target.SIZE_ORIGINAL && drawable.getIntrinsicWidth() <= 0) {
throw new IllegalArgumentException("Unable to draw " + drawable + " to Bitmap with "
+ "Target.SIZE_ORIGINAL because the Drawable has no intrinsic width");
}
if (height == Target.SIZE_ORIGINAL && drawable.getIntrinsicHeight() <= 0) {
throw new IllegalArgumentException("Unable to draw " + drawable + " to Bitmap with "
+ "Target.SIZE_ORIGINAL because the Drawable has no intrinsic height");
}
int targetWidth = drawable.getIntrinsicWidth() > 0 ? drawable.getIntrinsicWidth() : width;
int targetHeight = drawable.getIntrinsicHeight() > 0 ? drawable.getIntrinsicHeight() : height;
Bitmap result = Bitmap.createBitmap(targetWidth, targetHeight, Config.ARGB_8888);
Canvas canvas = new Canvas(result);
drawable.setBounds(0, 0, targetWidth, targetHeight);
drawable.draw(canvas);
canvas.setBitmap(null);
return result;
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册