From 4f185600e25b47bda7c355efe0434bddf589a19a Mon Sep 17 00:00:00 2001 From: Pierre Date: Tue, 2 Jan 2018 08:52:22 +0100 Subject: [PATCH] Fixed big image rendering issue --- .../data/ImageLoad/ImageDownloadRunnable.java | 35 ++++++++++-- .../data/ImageLoad/ImageLoadRunnable.java | 10 +++- .../client/data/utils/BitmapUtils.java | 56 ++++++++++++++++++- .../comunic/client/data/utils/Utilities.java | 19 ++----- 4 files changed, 99 insertions(+), 21 deletions(-) diff --git a/app/src/main/java/org/communiquons/android/comunic/client/data/ImageLoad/ImageDownloadRunnable.java b/app/src/main/java/org/communiquons/android/comunic/client/data/ImageLoad/ImageDownloadRunnable.java index 103857f..8a7ca2a 100644 --- a/app/src/main/java/org/communiquons/android/comunic/client/data/ImageLoad/ImageDownloadRunnable.java +++ b/app/src/main/java/org/communiquons/android/comunic/client/data/ImageLoad/ImageDownloadRunnable.java @@ -1,7 +1,10 @@ package org.communiquons.android.comunic.client.data.ImageLoad; import android.graphics.Bitmap; -import android.graphics.BitmapFactory; +import android.util.Log; + +import org.communiquons.android.comunic.client.data.utils.BitmapUtils; +import org.communiquons.android.comunic.client.data.utils.Utilities; import java.io.File; import java.io.FileOutputStream; @@ -19,6 +22,11 @@ import java.net.URL; class ImageDownloadRunnable implements Runnable { + /** + * Debug tag + */ + private static final String TAG = "ImageDownloadRunnable"; + private String url; private File dest; @@ -55,17 +63,34 @@ class ImageDownloadRunnable implements Runnable { conn.connect(); + //Get image size + long img_size = Long.decode(conn.getHeaderField("Content-Length")); + //Get input stream InputStream is = conn.getInputStream(); - //Process image - Bitmap image = BitmapFactory.decodeStream(is); - image.compress(Bitmap.CompressFormat.PNG, 100, os); + //Log action + Log.v(TAG, "Downloading image (size: "+img_size+") at " + url); - os.close(); + //Big images have to written byte per byte + Utilities.InputToOutputStream(is, os); + + //Close streams and disconnect is.close(); + os.close(); conn.disconnect(); + //Reduce image size + Bitmap bitmap = BitmapUtils.openResized(dest, 500, 500); + + //Write the new bitmap to the file + os = new FileOutputStream(dest, false); + bitmap.compress(Bitmap.CompressFormat.PNG, 100, os); + os.close(); + + //Free memory + bitmap.recycle(); + } catch (Exception e) { e.printStackTrace(); } diff --git a/app/src/main/java/org/communiquons/android/comunic/client/data/ImageLoad/ImageLoadRunnable.java b/app/src/main/java/org/communiquons/android/comunic/client/data/ImageLoad/ImageLoadRunnable.java index b754d89..023a2eb 100644 --- a/app/src/main/java/org/communiquons/android/comunic/client/data/ImageLoad/ImageLoadRunnable.java +++ b/app/src/main/java/org/communiquons/android/comunic/client/data/ImageLoad/ImageLoadRunnable.java @@ -22,6 +22,11 @@ import java.io.FileInputStream; class ImageLoadRunnable implements Runnable { + /** + * Debug tag + */ + private static final String TAG = "ImageLoadRunnable"; + /** * An array map with all the pending images associated with their URLs */ @@ -136,6 +141,9 @@ class ImageLoadRunnable implements Runnable { return; } + //Log action + Log.v(TAG, "Load image downloaded from " + url); + try { //Load the image FileInputStream is = new FileInputStream(file); @@ -146,7 +154,7 @@ class ImageLoadRunnable implements Runnable { if(bitmap == null){ //Return error Log.e("ImageLoadManagerRunnabl", "Image file could not be read, therefore it was" + - "deleted"); + " deleted"); //Delete file file.delete(); diff --git a/app/src/main/java/org/communiquons/android/comunic/client/data/utils/BitmapUtils.java b/app/src/main/java/org/communiquons/android/comunic/client/data/utils/BitmapUtils.java index dbdd5de..a02d3aa 100644 --- a/app/src/main/java/org/communiquons/android/comunic/client/data/utils/BitmapUtils.java +++ b/app/src/main/java/org/communiquons/android/comunic/client/data/utils/BitmapUtils.java @@ -1,11 +1,12 @@ package org.communiquons.android.comunic.client.data.utils; import android.graphics.Bitmap; +import android.graphics.BitmapFactory; import android.support.annotation.NonNull; -import android.support.annotation.Nullable; import android.util.Base64; import java.io.ByteArrayOutputStream; +import java.io.File; /** * Bitmap utilities @@ -58,4 +59,57 @@ public class BitmapUtils { //Scale and return bitmap return Bitmap.createScaledBitmap(bitmap, newW, newH, true); } + + /** + * Open a resized format of an image to avoid OOM Fatal error + * + * @param file The file to open + * @param reqWidth The required width + * @param reqHeight The required height + */ + public static Bitmap openResized(@NonNull File file, int reqWidth, int reqHeight){ + + //Get the size of the image + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inJustDecodeBounds = true; + BitmapFactory.decodeFile(file.getAbsolutePath(), options); + + //Calculate the reduction ratio + options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); + + //Decode Bitmap with new parametres + options.inJustDecodeBounds = false; + return BitmapFactory.decodeFile(file.getAbsolutePath(), options); + } + + /** + * Calculate the in sample size + * + * @param options The Options of the Bitmap Factory that already contains the with and the + * height of the image + * @param reqW The required width + * @param reqH The required Height + * @return The reduction ratio required for the image + */ + private static int calculateInSampleSize(BitmapFactory.Options options, int reqW, int reqH){ + + //Raw the width and the height of the image + int width = options.outWidth; + int height = options.outHeight; + int inSampleSize = 1; + + //Check if the image has to be resized + if(height > reqH || width > reqW){ + + int halfHeight = height / 2; + int halfWidth = width / 2; + + while((halfHeight / inSampleSize) >= reqH && (halfWidth / inSampleSize) >= reqW) + inSampleSize *= 2; + + } + + return inSampleSize; + + } } diff --git a/app/src/main/java/org/communiquons/android/comunic/client/data/utils/Utilities.java b/app/src/main/java/org/communiquons/android/comunic/client/data/utils/Utilities.java index f31e426..041768f 100644 --- a/app/src/main/java/org/communiquons/android/comunic/client/data/utils/Utilities.java +++ b/app/src/main/java/org/communiquons/android/comunic/client/data/utils/Utilities.java @@ -2,19 +2,15 @@ package org.communiquons.android.comunic.client.data.utils; import android.content.Context; import android.content.res.Resources; -import android.graphics.Bitmap; import android.os.Build; -import android.support.annotation.NonNull; import android.text.Html; import android.text.TextUtils; -import android.util.Base64; import android.util.Log; import android.util.Patterns; import org.communiquons.android.comunic.client.R; import java.io.BufferedReader; -import java.io.ByteArrayOutputStream; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; @@ -176,25 +172,20 @@ public class Utilities { * * @param is The Input stream * @param os The output stream - * @return The number of byte transfered */ - public static int InputToOutputStream(InputStream is, OutputStream os){ + public static void InputToOutputStream(InputStream is, OutputStream os){ - int count = 0; + int read = 0; + byte[] bytes = new byte[2048]; try { - int b = is.read(); - while (b != -1){ - os.write(b); - count++; - b = is.read(); + while ((read = is.read(bytes)) != -1){ + os.write(bytes, 0, read); } } catch (IOException e){ e.printStackTrace(); } - - return count; } /**