From 015d2659a9ea7438ab72b94500a0921f8ff35aa3 Mon Sep 17 00:00:00 2001
From: Sam Judd <judds@google.com>
Date: Sun, 24 Dec 2017 18:01:43 -0800
Subject: [PATCH] Support transcoding Drawables to byte[]s.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

We do so by casting which isn’t great, but it makes the API work a bit
more as expected and it’s not super expensive in comparison to the
compression call.
---
 .../java/com/bumptech/glide/AsBytesTest.java  |  3 --
 .../main/java/com/bumptech/glide/Glide.java   | 13 ++++-
 .../transcode/DrawableBytesTranscoder.java    | 51 +++++++++++++++++++
 3 files changed, 62 insertions(+), 5 deletions(-)
 create mode 100644 library/src/main/java/com/bumptech/glide/load/resource/transcode/DrawableBytesTranscoder.java

diff --git a/instrumentation/src/androidTest/java/com/bumptech/glide/AsBytesTest.java b/instrumentation/src/androidTest/java/com/bumptech/glide/AsBytesTest.java
index 24a4951b16..920e9635b7 100644
--- a/instrumentation/src/androidTest/java/com/bumptech/glide/AsBytesTest.java
+++ b/instrumentation/src/androidTest/java/com/bumptech/glide/AsBytesTest.java
@@ -23,7 +23,6 @@
 import java.io.OutputStream;
 import java.util.concurrent.TimeUnit;
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -68,8 +67,6 @@ public void loadBitmap_asBytes_providesBytesOfBitmap() {
     assertThat(BitmapFactory.decodeByteArray(data, 0, data.length)).isNotNull();
   }
 
-  // TODO: Should this pass?
-  @Ignore
   @Test
   public void loadBitmapDrawable_asBytes_providesBytesOfBitmap() {
     Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), ResourceIds.raw.canonical);
diff --git a/library/src/main/java/com/bumptech/glide/Glide.java b/library/src/main/java/com/bumptech/glide/Glide.java
index 56db4b0248..5d2535aa06 100644
--- a/library/src/main/java/com/bumptech/glide/Glide.java
+++ b/library/src/main/java/com/bumptech/glide/Glide.java
@@ -69,6 +69,7 @@
 import com.bumptech.glide.load.resource.gif.StreamGifDecoder;
 import com.bumptech.glide.load.resource.transcode.BitmapBytesTranscoder;
 import com.bumptech.glide.load.resource.transcode.BitmapDrawableTranscoder;
+import com.bumptech.glide.load.resource.transcode.DrawableBytesTranscoder;
 import com.bumptech.glide.load.resource.transcode.GifDrawableBytesTranscoder;
 import com.bumptech.glide.manager.ConnectivityMonitorFactory;
 import com.bumptech.glide.manager.RequestManagerRetriever;
@@ -352,6 +353,9 @@ private static void throwIncorrectGlideModule(Exception e) {
         new ResourceLoader.AssetFileDescriptorFactory(resources);
     BitmapEncoder bitmapEncoder = new BitmapEncoder();
 
+    BitmapBytesTranscoder bitmapBytesTranscoder = new BitmapBytesTranscoder();
+    GifDrawableBytesTranscoder gifDrawableBytesTranscoder = new GifDrawableBytesTranscoder();
+
     ContentResolver contentResolver = context.getContentResolver();
 
     registry
@@ -481,8 +485,13 @@ Uri.class, Bitmap.class, new ResourceBitmapDecoder(resourceDrawableDecoder, bitm
             Bitmap.class,
             BitmapDrawable.class,
             new BitmapDrawableTranscoder(resources))
-        .register(Bitmap.class, byte[].class, new BitmapBytesTranscoder())
-        .register(GifDrawable.class, byte[].class, new GifDrawableBytesTranscoder());
+        .register(Bitmap.class, byte[].class, bitmapBytesTranscoder)
+        .register(
+            Drawable.class,
+            byte[].class,
+            new DrawableBytesTranscoder(
+                bitmapPool, bitmapBytesTranscoder, gifDrawableBytesTranscoder))
+        .register(GifDrawable.class, byte[].class, gifDrawableBytesTranscoder);
 
     ImageViewTargetFactory imageViewTargetFactory = new ImageViewTargetFactory();
     glideContext =
diff --git a/library/src/main/java/com/bumptech/glide/load/resource/transcode/DrawableBytesTranscoder.java b/library/src/main/java/com/bumptech/glide/load/resource/transcode/DrawableBytesTranscoder.java
new file mode 100644
index 0000000000..59be855f36
--- /dev/null
+++ b/library/src/main/java/com/bumptech/glide/load/resource/transcode/DrawableBytesTranscoder.java
@@ -0,0 +1,51 @@
+package com.bumptech.glide.load.resource.transcode;
+
+
+import android.graphics.Bitmap;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.support.annotation.Nullable;
+import com.bumptech.glide.load.Options;
+import com.bumptech.glide.load.engine.Resource;
+import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;
+import com.bumptech.glide.load.resource.bitmap.BitmapResource;
+import com.bumptech.glide.load.resource.gif.GifDrawable;
+
+/**
+ * Obtains {@code byte[]} from {@link BitmapDrawable}s by delegating to a
+ * {@link ResourceTranscoder} for {@link Bitmap}s to {@code byte[]}s.
+ */
+public final class DrawableBytesTranscoder
+    implements ResourceTranscoder<Drawable, byte[]> {
+
+  private final BitmapPool bitmapPool;
+  private final ResourceTranscoder<Bitmap, byte[]> bitmapBytesTranscoder;
+  private final ResourceTranscoder<GifDrawable, byte[]> gifDrawableBytesTranscoder;
+
+  public DrawableBytesTranscoder(
+      BitmapPool bitmapPool,
+      ResourceTranscoder<Bitmap, byte[]> bitmapBytesTranscoder,
+      ResourceTranscoder<GifDrawable, byte[]> gifDrawableBytesTranscoder) {
+    this.bitmapPool = bitmapPool;
+    this.bitmapBytesTranscoder = bitmapBytesTranscoder;
+    this.gifDrawableBytesTranscoder = gifDrawableBytesTranscoder;
+  }
+
+  @Nullable
+  @Override
+  public Resource<byte[]> transcode(Resource<Drawable> toTranscode, Options options) {
+    Drawable drawable = toTranscode.get();
+    if (drawable instanceof BitmapDrawable) {
+      return bitmapBytesTranscoder.transcode(
+          BitmapResource.obtain(((BitmapDrawable) drawable).getBitmap(), bitmapPool), options);
+    } else if (drawable instanceof GifDrawable) {
+      return gifDrawableBytesTranscoder.transcode(toGifDrawableResource(toTranscode), options);
+    }
+    return null;
+  }
+
+  @SuppressWarnings("unchecked")
+  private static Resource<GifDrawable> toGifDrawableResource(Resource<Drawable> resource) {
+    return (Resource<GifDrawable>) (Resource<?>) resource;
+  }
+}