diff --git a/app/src/main/java/eu/faircode/email/FragmentCompose.java b/app/src/main/java/eu/faircode/email/FragmentCompose.java index 64e8650a93..7f3643af5f 100644 --- a/app/src/main/java/eu/faircode/email/FragmentCompose.java +++ b/app/src/main/java/eu/faircode/email/FragmentCompose.java @@ -45,6 +45,7 @@ import android.database.MatrixCursor; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Color; +import android.graphics.ImageDecoder; import android.graphics.Matrix; import android.graphics.Typeface; import android.graphics.drawable.Drawable; @@ -2677,6 +2678,7 @@ public class FragmentCompose extends FragmentBase { args.putParcelableArrayList("uris", new ArrayList<>(uris)); args.putBoolean("image", image); args.putInt("resize", resize); + args.putInt("zoom", zoom); args.putBoolean("privacy", privacy); args.putCharSequence("body", etBody.getText()); args.putInt("start", etBody.getSelectionStart()); @@ -2688,6 +2690,7 @@ public class FragmentCompose extends FragmentBase { List uris = args.getParcelableArrayList("uris"); boolean image = args.getBoolean("image"); int resize = args.getInt("resize"); + int zoom = args.getInt("zoom"); boolean privacy = args.getBoolean("privacy"); CharSequence body = args.getCharSequence("body"); int start = args.getInt("start"); @@ -2708,9 +2711,23 @@ public class FragmentCompose extends FragmentBase { File file = attachment.getFile(context); Uri cid = Uri.parse("cid:" + BuildConfig.APPLICATION_ID + "." + attachment.id); - Drawable d = Drawable.createFromPath(file.getAbsolutePath()); - if (d == null) - throw new IllegalArgumentException(context.getString(R.string.title_no_image)); + Drawable d; + try { + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.P) { + ImageDecoder.Source source = ImageDecoder.createSource(file.getAbsoluteFile()); + d = ImageDecoder.decodeDrawable(source); + } else + d = Drawable.createFromPath(file.getAbsolutePath()); + } catch (Throwable ex) { + Log.w(ex); + d = Drawable.createFromPath(file.getAbsolutePath()); + } + + if (d == null) { + int px = Helper.dp2pixels(context, (zoom + 1) * 24); + d = context.getDrawable(R.drawable.twotone_broken_image_24); + d.setBounds(0, 0, px, px); + } s.insert(start, "\n\uFFFC\n"); // Object replacement character ImageSpan is = new ImageSpan(context, cid); diff --git a/app/src/main/java/eu/faircode/email/ImageHelper.java b/app/src/main/java/eu/faircode/email/ImageHelper.java index 8b3ec59ec3..d9b9a92a3c 100644 --- a/app/src/main/java/eu/faircode/email/ImageHelper.java +++ b/app/src/main/java/eu/faircode/email/ImageHelper.java @@ -760,9 +760,12 @@ class ImageHelper { static Bitmap getScaledBitmap(InputStream is, String source, String mimeType, int scaleToPixels) throws IOException { if (TextUtils.isEmpty(mimeType)) mimeType = Helper.guessMimeType(source); + if ("image/svg+xml".equals(mimeType)) return ImageHelper.renderSvg(is, Color.WHITE, scaleToPixels); + // ImageDecoder cannot decode streams + BufferedInputStream bis = new BufferedInputStream(is); Log.i("Probe " + source); @@ -805,36 +808,63 @@ class ImageHelper { private static Bitmap _decodeImage(File file, String mimeType, int scaleToPixels) throws IOException { if (mimeType == null) mimeType = Helper.guessMimeType(file.getName()); + if ("image/svg+xml".equals(mimeType)) try (FileInputStream fis = new FileInputStream(file)) { return ImageHelper.renderSvg(fis, Color.WHITE, scaleToPixels); } - BitmapFactory.Options options = new BitmapFactory.Options(); - options.inJustDecodeBounds = true; - BitmapFactory.decodeFile(file.getAbsolutePath(), options); + Bitmap bm = null; - int factor = 1; - while (options.outWidth / factor > scaleToPixels) - factor *= 2; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) + try { + ImageDecoder.Source isource = ImageDecoder.createSource(file); + bm = ImageDecoder.decodeBitmap(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; - Matrix rotation = getImageRotation(file); - if (factor > 1 || rotation != null) { - Log.i("Decode image factor=" + factor); - options.inJustDecodeBounds = false; - options.inSampleSize = factor; - Bitmap scaled = BitmapFactory.decodeFile(file.getAbsolutePath(), options); - - if (scaled != null && rotation != null) { - Bitmap rotated = Bitmap.createBitmap(scaled, 0, 0, scaled.getWidth(), scaled.getHeight(), rotation, true); - scaled.recycle(); - scaled = rotated; + Log.i("Decode image (decoder) factor=" + factor); + decoder.setTargetSampleSize(factor); + } + }); + } catch (Throwable ex) { + Log.i(ex); } - return scaled; + if (bm == null) { + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inJustDecodeBounds = true; + BitmapFactory.decodeFile(file.getAbsolutePath(), options); + + int factor = 1; + while (options.outWidth / factor > scaleToPixels) + factor *= 2; + + if (factor > 1) { + Log.i("Decode image (factory) factor=" + factor); + options.inJustDecodeBounds = false; + options.inSampleSize = factor; + bm = BitmapFactory.decodeFile(file.getAbsolutePath(), options); + } else + bm = BitmapFactory.decodeFile(file.getAbsolutePath()); } - return BitmapFactory.decodeFile(file.getAbsolutePath()); + if (bm != null) { + Matrix rotation = getImageRotation(file); + if (rotation != null) { + Bitmap rotated = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), rotation, true); + bm.recycle(); + bm = rotated; + } + } + + return bm; } static Matrix getImageRotation(File file) { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index db45a55b3d..0ae92a5fd0 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1055,7 +1055,6 @@ Connecting to one or more accounts … Folder does not exist The originally received message will be included - Image could not be decoded Search on server is not available for this account Message too large to completely reformat Message too large to display completely