From 5f9f2455dceb06147af64f6ec5631cb3ae3a7355 Mon Sep 17 00:00:00 2001 From: Karim Abou Zeid Date: Tue, 15 Sep 2015 18:56:14 +0200 Subject: [PATCH] Replaced the Stackblur algorithm with RenderScripts native blur for better performance. Only issue yet is, that it seems to cause a memory leak. --- .../helper/bitmapblur/BlurProcess.java | 15 - .../helper/bitmapblur/JavaBlurProcess.java | 330 ------------------ .../helper/bitmapblur/StackBlurManager.java | 91 ----- .../gramophone/imageloader/BlurProcessor.java | 102 +++++- .../ui/activities/AlbumDetailActivity.java | 2 +- .../ui/activities/ArtistDetailActivity.java | 2 +- .../base/AbsSlidingMusicPanelActivity.java | 4 +- .../kabouzeid/gramophone/util/ImageUtil.java | 25 ++ 8 files changed, 121 insertions(+), 450 deletions(-) delete mode 100755 app/src/main/java/com/kabouzeid/gramophone/helper/bitmapblur/BlurProcess.java delete mode 100755 app/src/main/java/com/kabouzeid/gramophone/helper/bitmapblur/JavaBlurProcess.java delete mode 100644 app/src/main/java/com/kabouzeid/gramophone/helper/bitmapblur/StackBlurManager.java diff --git a/app/src/main/java/com/kabouzeid/gramophone/helper/bitmapblur/BlurProcess.java b/app/src/main/java/com/kabouzeid/gramophone/helper/bitmapblur/BlurProcess.java deleted file mode 100755 index cce072b3..00000000 --- a/app/src/main/java/com/kabouzeid/gramophone/helper/bitmapblur/BlurProcess.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.kabouzeid.gramophone.helper.bitmapblur; - -import android.graphics.Bitmap; - -interface BlurProcess { - /** - * Process the given image, blurring by the supplied radius. - * If radius is 0, this will return original - * - * @param original the bitmap to be blurred - * @param radius the radius in pixels to blur the image - * @return the blurred version of the image. - */ - Bitmap blur(Bitmap original, float radius); -} diff --git a/app/src/main/java/com/kabouzeid/gramophone/helper/bitmapblur/JavaBlurProcess.java b/app/src/main/java/com/kabouzeid/gramophone/helper/bitmapblur/JavaBlurProcess.java deleted file mode 100755 index a1a2976e..00000000 --- a/app/src/main/java/com/kabouzeid/gramophone/helper/bitmapblur/JavaBlurProcess.java +++ /dev/null @@ -1,330 +0,0 @@ -package com.kabouzeid.gramophone.helper.bitmapblur; - -import android.graphics.Bitmap; - -import java.util.ArrayList; -import java.util.concurrent.Callable; - -/** - * Blur using Java code. - * - * This is a compromise between Gaussian Blur and Box blur - * It creates much better looking blurs than Box Blur, but is - * 7x faster than my Gaussian Blur implementation. - - * I called it Stack Blur because this describes best how this - * filter works internally: it creates a kind of moving stack - * of colors whilst scanning through the image. Thereby it - * just has to add one new block of color to the right side - * of the stack and remove the leftmost color. The remaining - * colors on the topmost layer of the stack are either added on - * or reduced by one, depending on if they are on the right or - * on the left side of the stack. - * - * @author Enrique López Mañas - * http://www.neo-tech.es - * - * Author of the original algorithm: Mario Klingemann - * - * Based heavily on http://vitiy.info/Code/stackblur.cpp - * See http://vitiy.info/stackblur-algorithm-multi-threaded-blur-for-cpp/ - * - * @copyright: Enrique López Mañas - * @license: Apache License 2.0 - */ -class JavaBlurProcess implements BlurProcess { - - private static final short[] stackblur_mul = { - 512, 512, 456, 512, 328, 456, 335, 512, 405, 328, 271, 456, 388, 335, 292, 512, - 454, 405, 364, 328, 298, 271, 496, 456, 420, 388, 360, 335, 312, 292, 273, 512, - 482, 454, 428, 405, 383, 364, 345, 328, 312, 298, 284, 271, 259, 496, 475, 456, - 437, 420, 404, 388, 374, 360, 347, 335, 323, 312, 302, 292, 282, 273, 265, 512, - 497, 482, 468, 454, 441, 428, 417, 405, 394, 383, 373, 364, 354, 345, 337, 328, - 320, 312, 305, 298, 291, 284, 278, 271, 265, 259, 507, 496, 485, 475, 465, 456, - 446, 437, 428, 420, 412, 404, 396, 388, 381, 374, 367, 360, 354, 347, 341, 335, - 329, 323, 318, 312, 307, 302, 297, 292, 287, 282, 278, 273, 269, 265, 261, 512, - 505, 497, 489, 482, 475, 468, 461, 454, 447, 441, 435, 428, 422, 417, 411, 405, - 399, 394, 389, 383, 378, 373, 368, 364, 359, 354, 350, 345, 341, 337, 332, 328, - 324, 320, 316, 312, 309, 305, 301, 298, 294, 291, 287, 284, 281, 278, 274, 271, - 268, 265, 262, 259, 257, 507, 501, 496, 491, 485, 480, 475, 470, 465, 460, 456, - 451, 446, 442, 437, 433, 428, 424, 420, 416, 412, 408, 404, 400, 396, 392, 388, - 385, 381, 377, 374, 370, 367, 363, 360, 357, 354, 350, 347, 344, 341, 338, 335, - 332, 329, 326, 323, 320, 318, 315, 312, 310, 307, 304, 302, 299, 297, 294, 292, - 289, 287, 285, 282, 280, 278, 275, 273, 271, 269, 267, 265, 263, 261, 259 - }; - - private static final byte[] stackblur_shr = { - 9, 11, 12, 13, 13, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 17, - 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19, - 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, - 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, - 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, - 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, - 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, - 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, - 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, - 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, - 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, - 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24 - }; - - @Override - public Bitmap blur(Bitmap original, float radius) { - int w = original.getWidth(); - int h = original.getHeight(); - int[] currentPixels = new int[w * h]; - original.getPixels(currentPixels, 0, w, 0, 0, w, h); - int cores = StackBlurManager.EXECUTOR_THREADS; - - ArrayList horizontal = new ArrayList(cores); - ArrayList vertical = new ArrayList(cores); - for (int i = 0; i < cores; i++) { - horizontal.add(new BlurTask(currentPixels, w, h, (int) radius, cores, i, 1)); - vertical.add(new BlurTask(currentPixels, w, h, (int) radius, cores, i, 2)); - } - - try { - StackBlurManager.EXECUTOR.invokeAll(horizontal); - } catch (InterruptedException e) { - return null; - } - - try { - StackBlurManager.EXECUTOR.invokeAll(vertical); - } catch (InterruptedException e) { - return null; - } - - return Bitmap.createBitmap(currentPixels, w, h, Bitmap.Config.ARGB_8888); - } - - private static void blurIteration(int[] src, int w, int h, int radius, int cores, int core, int step) { - int x, y, xp, yp, i; - int sp; - int stack_start; - int stack_i; - - int src_i; - int dst_i; - - long sum_r, sum_g, sum_b, - sum_in_r, sum_in_g, sum_in_b, - sum_out_r, sum_out_g, sum_out_b; - - int wm = w - 1; - int hm = h - 1; - int div = (radius * 2) + 1; - int mul_sum = stackblur_mul[radius]; - byte shr_sum = stackblur_shr[radius]; - int[] stack = new int[div]; - - if (step == 1) { - int minY = core * h / cores; - int maxY = (core + 1) * h / cores; - - for (y = minY; y < maxY; y++) { - sum_r = sum_g = sum_b = - sum_in_r = sum_in_g = sum_in_b = - sum_out_r = sum_out_g = sum_out_b = 0; - - src_i = w * y; // start of line (0,y) - - for (i = 0; i <= radius; i++) { - stack_i = i; - stack[stack_i] = src[src_i]; - sum_r += ((src[src_i] >>> 16) & 0xff) * (i + 1); - sum_g += ((src[src_i] >>> 8) & 0xff) * (i + 1); - sum_b += (src[src_i] & 0xff) * (i + 1); - sum_out_r += ((src[src_i] >>> 16) & 0xff); - sum_out_g += ((src[src_i] >>> 8) & 0xff); - sum_out_b += (src[src_i] & 0xff); - } - - - for (i = 1; i <= radius; i++) { - if (i <= wm) src_i += 1; - stack_i = i + radius; - stack[stack_i] = src[src_i]; - sum_r += ((src[src_i] >>> 16) & 0xff) * (radius + 1 - i); - sum_g += ((src[src_i] >>> 8) & 0xff) * (radius + 1 - i); - sum_b += (src[src_i] & 0xff) * (radius + 1 - i); - sum_in_r += ((src[src_i] >>> 16) & 0xff); - sum_in_g += ((src[src_i] >>> 8) & 0xff); - sum_in_b += (src[src_i] & 0xff); - } - - - sp = radius; - xp = radius; - if (xp > wm) xp = wm; - src_i = xp + y * w; // img.pix_ptr(xp, y); - dst_i = y * w; // img.pix_ptr(0, y); - for (x = 0; x < w; x++) { - src[dst_i] = (int) - ((src[dst_i] & 0xff000000) | - ((((sum_r * mul_sum) >>> shr_sum) & 0xff) << 16) | - ((((sum_g * mul_sum) >>> shr_sum) & 0xff) << 8) | - ((((sum_b * mul_sum) >>> shr_sum) & 0xff))); - dst_i += 1; - - sum_r -= sum_out_r; - sum_g -= sum_out_g; - sum_b -= sum_out_b; - - stack_start = sp + div - radius; - if (stack_start >= div) stack_start -= div; - stack_i = stack_start; - - sum_out_r -= ((stack[stack_i] >>> 16) & 0xff); - sum_out_g -= ((stack[stack_i] >>> 8) & 0xff); - sum_out_b -= (stack[stack_i] & 0xff); - - if (xp < wm) { - src_i += 1; - ++xp; - } - - stack[stack_i] = src[src_i]; - - sum_in_r += ((src[src_i] >>> 16) & 0xff); - sum_in_g += ((src[src_i] >>> 8) & 0xff); - sum_in_b += (src[src_i] & 0xff); - sum_r += sum_in_r; - sum_g += sum_in_g; - sum_b += sum_in_b; - - ++sp; - if (sp >= div) sp = 0; - stack_i = sp; - - sum_out_r += ((stack[stack_i] >>> 16) & 0xff); - sum_out_g += ((stack[stack_i] >>> 8) & 0xff); - sum_out_b += (stack[stack_i] & 0xff); - sum_in_r -= ((stack[stack_i] >>> 16) & 0xff); - sum_in_g -= ((stack[stack_i] >>> 8) & 0xff); - sum_in_b -= (stack[stack_i] & 0xff); - } - - } - } - - // step 2 - else if (step == 2) { - int minX = core * w / cores; - int maxX = (core + 1) * w / cores; - - for (x = minX; x < maxX; x++) { - sum_r = sum_g = sum_b = - sum_in_r = sum_in_g = sum_in_b = - sum_out_r = sum_out_g = sum_out_b = 0; - - src_i = x; // x,0 - for (i = 0; i <= radius; i++) { - stack_i = i; - stack[stack_i] = src[src_i]; - sum_r += ((src[src_i] >>> 16) & 0xff) * (i + 1); - sum_g += ((src[src_i] >>> 8) & 0xff) * (i + 1); - sum_b += (src[src_i] & 0xff) * (i + 1); - sum_out_r += ((src[src_i] >>> 16) & 0xff); - sum_out_g += ((src[src_i] >>> 8) & 0xff); - sum_out_b += (src[src_i] & 0xff); - } - for (i = 1; i <= radius; i++) { - if (i <= hm) src_i += w; // +stride - - stack_i = i + radius; - stack[stack_i] = src[src_i]; - sum_r += ((src[src_i] >>> 16) & 0xff) * (radius + 1 - i); - sum_g += ((src[src_i] >>> 8) & 0xff) * (radius + 1 - i); - sum_b += (src[src_i] & 0xff) * (radius + 1 - i); - sum_in_r += ((src[src_i] >>> 16) & 0xff); - sum_in_g += ((src[src_i] >>> 8) & 0xff); - sum_in_b += (src[src_i] & 0xff); - } - - sp = radius; - yp = radius; - if (yp > hm) yp = hm; - src_i = x + yp * w; // img.pix_ptr(x, yp); - dst_i = x; // img.pix_ptr(x, 0); - for (y = 0; y < h; y++) { - src[dst_i] = (int) - ((src[dst_i] & 0xff000000) | - ((((sum_r * mul_sum) >>> shr_sum) & 0xff) << 16) | - ((((sum_g * mul_sum) >>> shr_sum) & 0xff) << 8) | - ((((sum_b * mul_sum) >>> shr_sum) & 0xff))); - dst_i += w; - - sum_r -= sum_out_r; - sum_g -= sum_out_g; - sum_b -= sum_out_b; - - stack_start = sp + div - radius; - if (stack_start >= div) stack_start -= div; - stack_i = stack_start; - - sum_out_r -= ((stack[stack_i] >>> 16) & 0xff); - sum_out_g -= ((stack[stack_i] >>> 8) & 0xff); - sum_out_b -= (stack[stack_i] & 0xff); - - if (yp < hm) { - src_i += w; // stride - ++yp; - } - - stack[stack_i] = src[src_i]; - - sum_in_r += ((src[src_i] >>> 16) & 0xff); - sum_in_g += ((src[src_i] >>> 8) & 0xff); - sum_in_b += (src[src_i] & 0xff); - sum_r += sum_in_r; - sum_g += sum_in_g; - sum_b += sum_in_b; - - ++sp; - if (sp >= div) sp = 0; - stack_i = sp; - - sum_out_r += ((stack[stack_i] >>> 16) & 0xff); - sum_out_g += ((stack[stack_i] >>> 8) & 0xff); - sum_out_b += (stack[stack_i] & 0xff); - sum_in_r -= ((stack[stack_i] >>> 16) & 0xff); - sum_in_g -= ((stack[stack_i] >>> 8) & 0xff); - sum_in_b -= (stack[stack_i] & 0xff); - } - } - } - - } - - private static class BlurTask implements Callable { - private final int[] _src; - private final int _w; - private final int _h; - private final int _radius; - private final int _totalCores; - private final int _coreIndex; - private final int _round; - - public BlurTask(int[] src, int w, int h, int radius, int totalCores, int coreIndex, int round) { - _src = src; - _w = w; - _h = h; - _radius = radius; - _totalCores = totalCores; - _coreIndex = coreIndex; - _round = round; - } - - @Override - public Void call() throws Exception { - blurIteration(_src, _w, _h, _radius, _totalCores, _coreIndex, _round); - return null; - } - - } -} diff --git a/app/src/main/java/com/kabouzeid/gramophone/helper/bitmapblur/StackBlurManager.java b/app/src/main/java/com/kabouzeid/gramophone/helper/bitmapblur/StackBlurManager.java deleted file mode 100644 index 66eebb0c..00000000 --- a/app/src/main/java/com/kabouzeid/gramophone/helper/bitmapblur/StackBlurManager.java +++ /dev/null @@ -1,91 +0,0 @@ -/** - * StackBlur v1.0 for Android - * - * @Author: Enrique López Mañas - * http://www.lopez-manas.com - *

- * Author of the original algorithm: Mario Klingemann - *

- * This is a compromise between Gaussian Blur and Box blur - * It creates much better looking blurs than Box Blur, but is - * 7x faster than my Gaussian Blur implementation. - *

- * I called it Stack Blur because this describes best how this - * filter works internally: it creates a kind of moving stack - * of colors whilst scanning through the image. Thereby it - * just has to add one new block of color to the right side - * of the stack and remove the leftmost color. The remaining - * colors on the topmost layer of the stack are either added on - * or reduced by one, depending on if they are on the right or - * on the left side of the stack. - * @copyright: Enrique López Mañas - * @license: Apache License 2.0 - */ - - -package com.kabouzeid.gramophone.helper.bitmapblur; - -import android.graphics.Bitmap; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; - -import com.kabouzeid.gramophone.util.ImageUtil; - -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -// class modified by Karim Abou Zeid (kabouzeid) - -public class StackBlurManager { - static final int EXECUTOR_THREADS = Runtime.getRuntime().availableProcessors(); - static final ExecutorService EXECUTOR = Executors.newFixedThreadPool(EXECUTOR_THREADS); - - /** - * Resized original image - */ - private final Bitmap image; - - /** - * Most recent result of blurring - */ - @Nullable - private Bitmap result; - - /** - * Method of blurring - */ - @NonNull - private final BlurProcess blurProcess; - - /** - * Constructor method (basic initialization and construction of the pixel array) - * - * @param image The image that will be analysed - */ - public StackBlurManager(@NonNull Bitmap image) { - // resize Bitmap to prevent OOM and OOB exceptions and increase the performance - this.image = ImageUtil.getResizedBitmap(image, 500, 500, false); - blurProcess = new JavaBlurProcess(); - } - - /** - * Process the image on the given radius. Radius must be at least 1 - * - * @param radius the blur radius - */ - @Nullable - public Bitmap process(int radius) { - result = blurProcess.blur(image, radius); - return result; - } - - /** - * Returns the blurred image as a bitmap - * - * @return blurred image - */ - @Nullable - public Bitmap returnBlurredImage() { - return result; - } -} diff --git a/app/src/main/java/com/kabouzeid/gramophone/imageloader/BlurProcessor.java b/app/src/main/java/com/kabouzeid/gramophone/imageloader/BlurProcessor.java index 84573a14..40c4ee6e 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/imageloader/BlurProcessor.java +++ b/app/src/main/java/com/kabouzeid/gramophone/imageloader/BlurProcessor.java @@ -1,28 +1,110 @@ package com.kabouzeid.gramophone.imageloader; +import android.content.Context; import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.support.annotation.FloatRange; +import android.support.annotation.NonNull; +import android.support.v8.renderscript.Allocation; +import android.support.v8.renderscript.Element; +import android.support.v8.renderscript.RenderScript; +import android.support.v8.renderscript.ScriptIntrinsicBlur; -import com.kabouzeid.gramophone.helper.bitmapblur.StackBlurManager; +import com.kabouzeid.gramophone.util.ImageUtil; import com.nostra13.universalimageloader.core.process.BitmapProcessor; /** * @author Karim Abou Zeid (kabouzeid) */ public class BlurProcessor implements BitmapProcessor { - public static final int DEFAULT_BLUR_RADIUS = 10; + public static final float DEFAULT_BLUR_RADIUS = 5f; - final int blurRadius; + private Context context; + private final float blurRadius; + private final int sampling; - public BlurProcessor() { - this.blurRadius = DEFAULT_BLUR_RADIUS; - } - - public BlurProcessor(int blurRadius) { - this.blurRadius = blurRadius; + private BlurProcessor(Builder builder) { + this.context = builder.context; + this.blurRadius = builder.blurRadius; + this.sampling = builder.sampling; } + // Something here seems to cause a memory leak... Go into LeakCanary for more details. @Override public Bitmap process(Bitmap bitmap) { - return new StackBlurManager(bitmap).process(blurRadius); + int sampling; + if (this.sampling == 0) { + sampling = ImageUtil.calculateInSampleSize(bitmap.getWidth(), bitmap.getHeight(), 100); + } else { + sampling = this.sampling; + } + + int width = bitmap.getWidth(); + int height = bitmap.getHeight(); + int scaledWidth = width / sampling; + int scaledHeight = height / sampling; + + Bitmap out = Bitmap.createBitmap(scaledWidth, scaledHeight, Bitmap.Config.ARGB_8888); + + Canvas canvas = new Canvas(out); + canvas.scale(1 / (float) sampling, 1 / (float) sampling); + Paint paint = new Paint(); + paint.setFlags(Paint.FILTER_BITMAP_FLAG); + canvas.drawBitmap(bitmap, 0, 0, paint); + + final RenderScript rs = RenderScript.create(context.getApplicationContext()); + final Allocation input = Allocation.createFromBitmap(rs, out, Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT); + final Allocation output = Allocation.createTyped(rs, input.getType()); + final ScriptIntrinsicBlur script = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs)); + + script.setRadius(blurRadius); + script.setInput(input); + script.forEach(output); + + output.copyTo(out); + + rs.destroy(); + + return out; + } + + public static class Builder { + private Context context; + private float blurRadius = DEFAULT_BLUR_RADIUS; + private int sampling; + + public Builder(@NonNull Context context) { + this.context = context; + } + + /** + * @param blurRadius The radius to use. Must be between 0 and 25. Default is 5. + * @return the same Builder + */ + public Builder blurRadius(@FloatRange(from = 0.0f, to = 25.0f) float blurRadius) { + this.blurRadius = blurRadius; + return this; + } + + /** + * @param sampling The inSampleSize to use. Must be a power of 2, or 1 for no down sampling or 0 for auto detect sampling. Default is 0. + * @return the same Builder + */ + public Builder sampling(int sampling) { + this.sampling = sampling; + return this; + } + + public Builder fromPrototype(BlurProcessor prototype) { + context = prototype.context; + blurRadius = prototype.blurRadius; + sampling = prototype.sampling; + return this; + } + + public BlurProcessor build() { + return new BlurProcessor(this); + } } } diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/AlbumDetailActivity.java b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/AlbumDetailActivity.java index c8b6d99e..dbffaeb4 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/AlbumDetailActivity.java +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/AlbumDetailActivity.java @@ -245,7 +245,7 @@ public class AlbumDetailActivity extends AbsSlidingMusicPanelActivity implements ImageLoader.getInstance().displayImage( imageUri, albumArtBackground, - new DisplayImageOptions.Builder().postProcessor(new BlurProcessor()).build() + new DisplayImageOptions.Builder().postProcessor(new BlurProcessor.Builder(this).build()).build() ); } diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/ArtistDetailActivity.java b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/ArtistDetailActivity.java index e1d092c7..d9e99bdf 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/ArtistDetailActivity.java +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/ArtistDetailActivity.java @@ -358,7 +358,7 @@ public class ArtistDetailActivity extends AbsSlidingMusicPanelActivity implement ImageLoader.getInstance().displayImage( imageUri, artistImageBackground, - new DisplayImageOptions.Builder().postProcessor(new BlurProcessor()).build() + new DisplayImageOptions.Builder().postProcessor(new BlurProcessor.Builder(this).build()).build() ); } diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/base/AbsSlidingMusicPanelActivity.java b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/base/AbsSlidingMusicPanelActivity.java index 442e7ce1..211e9496 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/base/AbsSlidingMusicPanelActivity.java +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/base/AbsSlidingMusicPanelActivity.java @@ -892,7 +892,7 @@ public abstract class AbsSlidingMusicPanelActivity extends AbsMusicServiceActivi ImageLoader.getInstance().displayImage( "drawable://" + R.drawable.default_album_art, albumArtBackground, - new DisplayImageOptions.Builder().postProcessor(new BlurProcessor()).build() + new DisplayImageOptions.Builder().postProcessor(new BlurProcessor.Builder(AbsSlidingMusicPanelActivity.this).build()).build() ); } @@ -906,7 +906,7 @@ public abstract class AbsSlidingMusicPanelActivity extends AbsMusicServiceActivi ImageLoader.getInstance().displayImage( imageUri, albumArtBackground, - new DisplayImageOptions.Builder().postProcessor(new BlurProcessor()).build() + new DisplayImageOptions.Builder().postProcessor(new BlurProcessor.Builder(AbsSlidingMusicPanelActivity.this).build()).build() ); } } diff --git a/app/src/main/java/com/kabouzeid/gramophone/util/ImageUtil.java b/app/src/main/java/com/kabouzeid/gramophone/util/ImageUtil.java index 02e974df..26ef284f 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/util/ImageUtil.java +++ b/app/src/main/java/com/kabouzeid/gramophone/util/ImageUtil.java @@ -22,4 +22,29 @@ public class ImageUtil { } return resizedBitmap; } + + public static int calculateInSampleSize(int width, int height, int reqWidth) { + // setting reqWidth matching to desired 1:1 ratio and screen-size + if (width < height) { + reqWidth = (height / width) * reqWidth; + } else { + reqWidth = (width / height) * reqWidth; + } + + int inSampleSize = 1; + + if (height > reqWidth || width > reqWidth) { + final int halfHeight = height / 2; + final int halfWidth = width / 2; + + // Calculate the largest inSampleSize value that is a power of 2 and keeps both + // height and width larger than the requested height and width. + while ((halfHeight / inSampleSize) > reqWidth + && (halfWidth / inSampleSize) > reqWidth) { + inSampleSize *= 2; + } + } + + return inSampleSize; + } }