diff --git a/app/src/main/java/eu/faircode/email/AdapterImage.java b/app/src/main/java/eu/faircode/email/AdapterImage.java index b82d60afe4..02230bdd5b 100644 --- a/app/src/main/java/eu/faircode/email/AdapterImage.java +++ b/app/src/main/java/eu/faircode/email/AdapterImage.java @@ -85,7 +85,7 @@ public class AdapterImage extends RecyclerView.Adapter private void bindTo(EntityAttachment attachment) { if (attachment.available) { - Bitmap bm = Helper.decodeImage(attachment.getFile(context), + Bitmap bm = ImageHelper.decodeImage(attachment.getFile(context), context.getResources().getDisplayMetrics().widthPixels); if (bm == null) ivImage.setImageResource(R.drawable.baseline_broken_image_24); diff --git a/app/src/main/java/eu/faircode/email/FragmentCompose.java b/app/src/main/java/eu/faircode/email/FragmentCompose.java index cae8b1d23b..3d0a8df063 100644 --- a/app/src/main/java/eu/faircode/email/FragmentCompose.java +++ b/app/src/main/java/eu/faircode/email/FragmentCompose.java @@ -2043,7 +2043,7 @@ public class FragmentCompose extends FragmentBase { options.outHeight / factor > resize) factor *= 2; - Matrix rotation = ("image/jpeg".equals(attachment.type) ? Helper.getImageRotation(file) : null); + Matrix rotation = ("image/jpeg".equals(attachment.type) ? ImageHelper.getImageRotation(file) : null); Log.i("Image type=" + attachment.type + " rotation=" + rotation); if (factor > 1 || rotation != null) { diff --git a/app/src/main/java/eu/faircode/email/Helper.java b/app/src/main/java/eu/faircode/email/Helper.java index f3a5e7156b..920bcdcbb0 100644 --- a/app/src/main/java/eu/faircode/email/Helper.java +++ b/app/src/main/java/eu/faircode/email/Helper.java @@ -31,10 +31,7 @@ import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.res.TypedArray; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; import android.graphics.Color; -import android.graphics.Matrix; import android.hardware.biometrics.BiometricManager; import android.hardware.fingerprint.FingerprintManager; import android.net.Uri; @@ -75,7 +72,6 @@ import androidx.browser.customtabs.CustomTabsIntent; import androidx.constraintlayout.widget.ConstraintLayout; import androidx.core.content.ContextCompat; import androidx.core.graphics.ColorUtils; -import androidx.exifinterface.media.ExifInterface; import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentManager; import androidx.preference.PreferenceManager; @@ -687,77 +683,6 @@ public class Helper { return stats.getAvailableBlocksLong() * stats.getBlockSizeLong(); } - static Bitmap decodeImage(File file, int scaleToPixels) { - BitmapFactory.Options options = new BitmapFactory.Options(); - options.inJustDecodeBounds = true; - BitmapFactory.decodeFile(file.getAbsolutePath(), options); - - int factor = 1; - while (options.outWidth / factor > scaleToPixels) - factor *= 2; - - Matrix rotation = null; - try { - rotation = Helper.getImageRotation(file); - } catch (IOException ex) { - Log.w(ex); - } - - 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; - } - - return scaled; - } - - return BitmapFactory.decodeFile(file.getAbsolutePath()); - } - - static Matrix getImageRotation(File file) throws IOException { - ExifInterface exif = new ExifInterface(file.getAbsolutePath()); - int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED); - - Matrix matrix = new Matrix(); - switch (orientation) { - case ExifInterface.ORIENTATION_NORMAL: - return null; - case ExifInterface.ORIENTATION_FLIP_HORIZONTAL: - matrix.setScale(-1, 1); - return matrix; - case ExifInterface.ORIENTATION_FLIP_VERTICAL: - matrix.setRotate(180); - matrix.postScale(-1, 1); - return matrix; - case ExifInterface.ORIENTATION_TRANSPOSE: - matrix.setRotate(90); - matrix.postScale(-1, 1); - return matrix; - case ExifInterface.ORIENTATION_TRANSVERSE: - matrix.setRotate(-90); - matrix.postScale(-1, 1); - return matrix; - case ExifInterface.ORIENTATION_ROTATE_90: - matrix.setRotate(90); - return matrix; - case ExifInterface.ORIENTATION_ROTATE_180: - matrix.setRotate(180); - return matrix; - case ExifInterface.ORIENTATION_ROTATE_270: - matrix.setRotate(-90); - return matrix; - default: - return null; - } - } - // Cryptography static String sha256(String data) throws NoSuchAlgorithmException { diff --git a/app/src/main/java/eu/faircode/email/ImageHelper.java b/app/src/main/java/eu/faircode/email/ImageHelper.java index 37dc80e1ba..ddf9d7d384 100644 --- a/app/src/main/java/eu/faircode/email/ImageHelper.java +++ b/app/src/main/java/eu/faircode/email/ImageHelper.java @@ -27,6 +27,7 @@ import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.ImageDecoder; +import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.PorterDuff; import android.graphics.PorterDuffXfermode; @@ -46,6 +47,7 @@ import android.widget.TextView; import androidx.annotation.NonNull; import androidx.core.graphics.ColorUtils; +import androidx.exifinterface.media.ExifInterface; import androidx.preference.PreferenceManager; import java.io.BufferedOutputStream; @@ -266,7 +268,7 @@ class ImageHelper { return gif; } } else { - Bitmap bm = Helper.decodeImage(attachment.getFile(context), scaleToPixels); + Bitmap bm = ImageHelper.decodeImage(attachment.getFile(context), scaleToPixels); if (bm == null) { Log.i("Image not decodable CID=" + cid); Drawable d = res.getDrawable(R.drawable.baseline_broken_image_24, theme); @@ -501,6 +503,77 @@ class ImageHelper { return null; } + static Bitmap decodeImage(File file, int scaleToPixels) { + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inJustDecodeBounds = true; + BitmapFactory.decodeFile(file.getAbsolutePath(), options); + + int factor = 1; + while (options.outWidth / factor > scaleToPixels) + factor *= 2; + + Matrix rotation = null; + try { + rotation = getImageRotation(file); + } catch (IOException ex) { + Log.w(ex); + } + + 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; + } + + return scaled; + } + + return BitmapFactory.decodeFile(file.getAbsolutePath()); + } + + static Matrix getImageRotation(File file) throws IOException { + ExifInterface exif = new ExifInterface(file.getAbsolutePath()); + int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED); + + Matrix matrix = new Matrix(); + switch (orientation) { + case ExifInterface.ORIENTATION_NORMAL: + return null; + case ExifInterface.ORIENTATION_FLIP_HORIZONTAL: + matrix.setScale(-1, 1); + return matrix; + case ExifInterface.ORIENTATION_FLIP_VERTICAL: + matrix.setRotate(180); + matrix.postScale(-1, 1); + return matrix; + case ExifInterface.ORIENTATION_TRANSPOSE: + matrix.setRotate(90); + matrix.postScale(-1, 1); + return matrix; + case ExifInterface.ORIENTATION_TRANSVERSE: + matrix.setRotate(-90); + matrix.postScale(-1, 1); + return matrix; + case ExifInterface.ORIENTATION_ROTATE_90: + matrix.setRotate(90); + return matrix; + case ExifInterface.ORIENTATION_ROTATE_180: + matrix.setRotate(180); + return matrix; + case ExifInterface.ORIENTATION_ROTATE_270: + matrix.setRotate(-90); + return matrix; + default: + return null; + } + } + static class AnnotatedSource { private String source; private int width = 0;