diff --git a/app/src/main/java/eu/faircode/email/ImageHelper.java b/app/src/main/java/eu/faircode/email/ImageHelper.java index 1d049ec916..3678c51620 100644 --- a/app/src/main/java/eu/faircode/email/ImageHelper.java +++ b/app/src/main/java/eu/faircode/email/ImageHelper.java @@ -34,6 +34,7 @@ import android.graphics.PorterDuffXfermode; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.Typeface; +import android.graphics.drawable.AnimatedImageDrawable; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.LevelListDrawable; @@ -51,6 +52,7 @@ import android.view.ViewParent; import android.widget.TextView; import androidx.annotation.NonNull; +import androidx.annotation.RequiresApi; import androidx.core.graphics.ColorUtils; import androidx.exifinterface.media.ExifInterface; import androidx.preference.PreferenceManager; @@ -264,37 +266,17 @@ class ImageHelper { return d; } else { int scaleToPixels = res.getDisplayMetrics().widthPixels; - if ("image/gif".equals(attachment.type) && - Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { - ImageDecoder.Source isource = ImageDecoder.createSource(attachment.getFile(context)); - Drawable gif; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { try { - gif = ImageDecoder.decodeDrawable(isource, new ImageDecoder.OnHeaderDecodedListener() { - @Override - public void onHeaderDecoded( - @NonNull ImageDecoder decoder, - @NonNull ImageDecoder.ImageInfo info, - @NonNull ImageDecoder.Source source) { - int factor = 1; - while (info.getSize().getWidth() / factor > scaleToPixels) - factor *= 2; - - decoder.setTargetSampleSize(factor); - } - }); + Drawable d = getScaledDrawable(attachment.getFile(context), scaleToPixels); + if (view != null) + fitDrawable(d, a, view); + return d; } catch (IOException ex) { Log.w(ex); - gif = null; - } - if (gif == null) { - Log.i("GIF not decodable CID=" + cid); Drawable d = res.getDrawable(R.drawable.baseline_broken_image_24, theme); d.setBounds(0, 0, px, px); return d; - } else { - if (view != null) - fitDrawable(gif, a, view); - return gif; } } else { Bitmap bm = decodeImage(attachment.getFile(context), scaleToPixels); @@ -476,6 +458,11 @@ class ImageHelper { lld.setBounds(0, 0, bounds.width(), bounds.height()); lld.setLevel(0); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + if (d instanceof AnimatedImageDrawable) + ((AnimatedImageDrawable) d).start(); + } + view.requestLayout(); } }); @@ -545,22 +532,25 @@ class ImageHelper { return BitmapFactory.decodeByteArray(bytes, 0, bytes.length); } - private static Drawable getCachedImage(Context context, long id, String source) { + private static Drawable getCachedImage(Context context, long id, String source) throws IOException { if (id < 0) return null; - File file = getCacheFile(context, id, source, ".png"); + File file = getCacheFile(context, id, source, + Build.VERSION.SDK_INT < Build.VERSION_CODES.P ? ".png" : ".blob"); if (file.exists()) { Log.i("Using cached " + file); file.setLastModified(new Date().getTime()); + DisplayMetrics dm = context.getResources().getDisplayMetrics(); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) + return getScaledDrawable(file, dm.widthPixels); + Bitmap bm = BitmapFactory.decodeFile(file.getAbsolutePath()); if (bm != null) { Drawable d = new BitmapDrawable(context.getResources(), bm); - - DisplayMetrics dm = context.getResources().getDisplayMetrics(); d.setBounds(0, 0, Math.round(bm.getWidth() * dm.density), Math.round(bm.getHeight() * dm.density)); - return d; } } @@ -623,6 +613,14 @@ class ImageHelper { break; } + if (id > 0 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + File file = getCacheFile(context, id, source, ".blob"); + try (FileOutputStream fos = new FileOutputStream(file)) { + Helper.copy(urlConnection.getInputStream(), fos); + } + return getScaledDrawable(file, dm.widthPixels); + } + bm = getScaledBitmap(urlConnection.getInputStream(), source, dm.widthPixels); } finally { if (urlConnection != null) @@ -646,6 +644,26 @@ class ImageHelper { return d; } + @RequiresApi(api = Build.VERSION_CODES.P) + static Drawable getScaledDrawable(File file, int scaleToPixels) throws IOException { + ImageDecoder.Source isource = ImageDecoder.createSource(file); + Drawable d = ImageDecoder.decodeDrawable(isource, new ImageDecoder.OnHeaderDecodedListener() { + @Override + public void onHeaderDecoded( + @NonNull ImageDecoder decoder, + @NonNull ImageDecoder.ImageInfo info, + @NonNull ImageDecoder.Source source) { + int factor = 1; + while (info.getSize().getWidth() / factor > scaleToPixels) + factor *= 2; + + decoder.setTargetSampleSize(factor); + } + }); + d.setBounds(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight()); + return d; + } + static Bitmap getScaledBitmap(InputStream is, String source, int scaleToPixels) throws IOException { BufferedInputStream bis = new BufferedInputStream(is);