From 75088d8414c43e00b379eee313c47fae226520a0 Mon Sep 17 00:00:00 2001 From: Dimitry Ivanov Date: Sat, 25 Aug 2018 13:29:55 +0300 Subject: [PATCH] image-loader add support for inline data uri image references --- .../markwon/il/AsyncDrawableLoader.java | 39 +++++++++++++++++- .../ru/noties/markwon/il/DataUriDecoder.java | 41 +++++++++++++++++++ 2 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 markwon-image-loader/src/main/java/ru/noties/markwon/il/DataUriDecoder.java diff --git a/markwon-image-loader/src/main/java/ru/noties/markwon/il/AsyncDrawableLoader.java b/markwon-image-loader/src/main/java/ru/noties/markwon/il/AsyncDrawableLoader.java index 7eade398..75b61087 100644 --- a/markwon-image-loader/src/main/java/ru/noties/markwon/il/AsyncDrawableLoader.java +++ b/markwon-image-loader/src/main/java/ru/noties/markwon/il/AsyncDrawableLoader.java @@ -7,8 +7,10 @@ import android.os.Handler; import android.os.Looper; import android.support.annotation.NonNull; import android.support.annotation.Nullable; +import android.text.TextUtils; import java.io.BufferedInputStream; +import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; @@ -46,6 +48,12 @@ public class AsyncDrawableLoader implements AsyncDrawable.Loader { private static final String FILE_ANDROID_ASSETS = "android_asset"; + private static final String SCHEME_FILE = "file"; + private static final String SCHEME_DATA = "data"; + + private static final DataUriParser DATA_URI_PARSER = DataUriParser.create(); + private static final DataUriDecoder DATA_URI_DECODER = DataUriDecoder.create(); + private final OkHttpClient client; private final Resources resources; private final ExecutorService executorService; @@ -103,9 +111,14 @@ public class AsyncDrawableLoader implements AsyncDrawable.Loader { final boolean isFromFile; final Uri uri = Uri.parse(destination); - if ("file".equals(uri.getScheme())) { + final String scheme = uri.getScheme(); + + if (SCHEME_FILE.equals(scheme)) { item = fromFile(uri); isFromFile = true; + } else if (SCHEME_DATA.equals(scheme)) { + item = fromData(uri.getSchemeSpecificPart()); + isFromFile = false; } else { item = fromNetwork(destination); isFromFile = false; @@ -208,6 +221,30 @@ public class AsyncDrawableLoader implements AsyncDrawable.Loader { return out; } + @Nullable + private Item fromData(@Nullable String part) { + + if (TextUtils.isEmpty(part)) { + return null; + } + + final DataUri dataUri = DATA_URI_PARSER.parse(part); + if (dataUri == null) { + return null; + } + + final byte[] bytes = DATA_URI_DECODER.decode(dataUri); + if (bytes == null) { + return null; + } + + return new Item( + null, + dataUri.contentType(), + new ByteArrayInputStream(bytes) + ); + } + @Nullable private Item fromNetwork(@NonNull String destination) { diff --git a/markwon-image-loader/src/main/java/ru/noties/markwon/il/DataUriDecoder.java b/markwon-image-loader/src/main/java/ru/noties/markwon/il/DataUriDecoder.java new file mode 100644 index 00000000..ffb0d840 --- /dev/null +++ b/markwon-image-loader/src/main/java/ru/noties/markwon/il/DataUriDecoder.java @@ -0,0 +1,41 @@ +package ru.noties.markwon.il; + +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.text.TextUtils; +import android.util.Base64; + +public abstract class DataUriDecoder { + + @Nullable + public abstract byte[] decode(@NonNull DataUri dataUri); + + @NonNull + public static DataUriDecoder create() { + return new Impl(); + } + + static class Impl extends DataUriDecoder { + + @Nullable + @Override + public byte[] decode(@NonNull DataUri dataUri) { + + final String data = dataUri.data(); + + if (!TextUtils.isEmpty(data)) { + try { + if (dataUri.base64()) { + return Base64.decode(data.getBytes("UTF-8"), Base64.DEFAULT); + } else { + return data.getBytes("UTF-8"); + } + } catch (Throwable t) { + return null; + } + } else { + return null; + } + } + } +}