From 0592587b67e6a964e7c543ab46e2c9cbc798aeaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Barth=C3=A9l=C3=A9my?= Date: Wed, 27 Apr 2016 08:42:06 +0200 Subject: [PATCH 1/3] [FastBlur] remove un needed buffer and decrease allocation by 3. Thanks to sh1 feedback on Disqus https://disqus.com/home/discussion/trickyandroid/advanced_blurring_techniques_22 --- .../blurdialogfragment/FastBlurHelper.java | 37 ++++++++++--------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/lib/src/main/java/fr/tvbarthel/lib/blurdialogfragment/FastBlurHelper.java b/lib/src/main/java/fr/tvbarthel/lib/blurdialogfragment/FastBlurHelper.java index 973874b..d845f92 100644 --- a/lib/src/main/java/fr/tvbarthel/lib/blurdialogfragment/FastBlurHelper.java +++ b/lib/src/main/java/fr/tvbarthel/lib/blurdialogfragment/FastBlurHelper.java @@ -48,7 +48,10 @@ public static Bitmap doBlur(Bitmap sentBitmap, int radius, boolean canReuseInBit // created Feburary 29, 2004 // Android port : Yahel Bouaziz // http://www.kayenko.com - // ported april 5th, 2012 + // ported April 5th, 2012 + // Single buffer tweak by Thomas Barthelemy + // http://tvbarthel.fr/ + // modified April 27th, 2016 // This is a compromise between Gaussian Blur and Box blur // It creates much better looking blurs than Box Blur, but is @@ -76,12 +79,9 @@ public static Bitmap doBlur(Bitmap sentBitmap, int radius, boolean canReuseInBit int wm = w - 1; int hm = h - 1; - int wh = w * h; int div = radius + radius + 1; - int r[] = new int[wh]; - int g[] = new int[wh]; - int b[] = new int[wh]; + int px = 0; int rsum, gsum, bsum, x, y, i, p, yp, yi, yw; int vmin[] = new int[Math.max(w, h)]; @@ -129,9 +129,7 @@ public static Bitmap doBlur(Bitmap sentBitmap, int radius, boolean canReuseInBit for (x = 0; x < w; x++) { - r[yi] = dv[rsum]; - g[yi] = dv[gsum]; - b[yi] = dv[bsum]; + pix[yi] = (0xff000000 & pix[yi]) | (dv[rsum] << 16) | (dv[gsum] << 8) | dv[bsum]; rsum -= routsum; gsum -= goutsum; @@ -147,6 +145,7 @@ public static Bitmap doBlur(Bitmap sentBitmap, int radius, boolean canReuseInBit if (y == 0) { vmin[x] = Math.min(x + radius + 1, wm); } + p = pix[yw + vmin[x]]; sir[0] = (p & 0xff0000) >> 16; @@ -184,15 +183,17 @@ public static Bitmap doBlur(Bitmap sentBitmap, int radius, boolean canReuseInBit sir = stack[i + radius]; - sir[0] = r[yi]; - sir[1] = g[yi]; - sir[2] = b[yi]; + px = pix[yi]; + + sir[0] = (px & 0xff0000) >> 16; + sir[1] = (px & 0x00ff00) >> 8; + sir[2] = (px & 0x0000ff); rbs = r1 - Math.abs(i); - rsum += r[yi] * rbs; - gsum += g[yi] * rbs; - bsum += b[yi] * rbs; + rsum += sir[0] * rbs; + gsum += sir[1] * rbs; + bsum += sir[2] * rbs; if (i > 0) { rinsum += sir[0]; @@ -230,9 +231,11 @@ public static Bitmap doBlur(Bitmap sentBitmap, int radius, boolean canReuseInBit } p = x + vmin[y]; - sir[0] = r[p]; - sir[1] = g[p]; - sir[2] = b[p]; + px = pix[p]; + + sir[0] = (px & 0xff0000) >> 16; + sir[1] = (px & 0x00ff00) >> 8; + sir[2] = (px & 0x0000ff); rinsum += sir[0]; ginsum += sir[1]; From b67920a360ab41f3be29351a1d3dfeac04bfac7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Barth=C3=A9l=C3=A9my?= Date: Tue, 3 May 2016 08:22:11 +0200 Subject: [PATCH 2/3] [OrientationChange] fix behavior during orientation change. Blur the background even if the dialog is retained. IskuhiSargsyan feedback. --- config/quality/checkstyle/suppressions.xml | 2 ++ .../blurdialogfragment/BlurDialogEngine.java | 31 +++++++++++++++---- .../BlurDialogFragment.java | 17 +++++++--- .../SupportBlurDialogFragment.java | 17 +++++++--- .../sample/SampleActionBarActivity.java | 15 +++++---- 5 files changed, 60 insertions(+), 22 deletions(-) diff --git a/config/quality/checkstyle/suppressions.xml b/config/quality/checkstyle/suppressions.xml index 9170a3a..45fd808 100644 --- a/config/quality/checkstyle/suppressions.xml +++ b/config/quality/checkstyle/suppressions.xml @@ -13,4 +13,6 @@ + + \ No newline at end of file diff --git a/lib/src/main/java/fr/tvbarthel/lib/blurdialogfragment/BlurDialogEngine.java b/lib/src/main/java/fr/tvbarthel/lib/blurdialogfragment/BlurDialogEngine.java index 637d8b9..c64b92e 100644 --- a/lib/src/main/java/fr/tvbarthel/lib/blurdialogfragment/BlurDialogEngine.java +++ b/lib/src/main/java/fr/tvbarthel/lib/blurdialogfragment/BlurDialogEngine.java @@ -25,6 +25,7 @@ import android.view.Gravity; import android.view.View; import android.view.ViewGroup; +import android.view.ViewTreeObserver; import android.view.WindowManager; import android.view.animation.AccelerateInterpolator; import android.view.animation.LinearInterpolator; @@ -145,6 +146,16 @@ public BlurDialogEngine(Activity holdingActivity) { mAnimationDuration = holdingActivity.getResources().getInteger(R.integer.blur_dialog_animation_duration); } + /** + * Must be linked to the original lifecycle. + * + * @param activity holding activity. + */ + public void onAttach(Activity activity) { + mHoldingActivity = activity; + } + + /** * Resume the engine. * @@ -152,8 +163,16 @@ public BlurDialogEngine(Activity holdingActivity) { */ public void onResume(boolean retainedInstance) { if (mBlurredBackgroundView == null || retainedInstance) { - mBluringTask = new BlurAsyncTask(); - mBluringTask.execute(); + mHoldingActivity.getWindow().getDecorView().getViewTreeObserver().addOnPreDrawListener( + new ViewTreeObserver.OnPreDrawListener() { + @Override + public boolean onPreDraw() { + mHoldingActivity.getWindow().getDecorView().getViewTreeObserver().removeOnPreDrawListener(this); + mBluringTask = new BlurAsyncTask(); + mBluringTask.execute(); + return false; + } + }); } } @@ -197,7 +216,7 @@ public void onAnimationCancel(Animator animation) { /** * Must be linked to the original lifecycle. */ - public void onDestroy() { + public void onDetach() { if (mBluringTask != null) { mBluringTask.cancel(true); } @@ -268,7 +287,6 @@ public void setBlurRadius(int radius) { * * @param useRenderScript use of RenderScript */ - public void setUseRenderScript(boolean useRenderScript) { mUseRenderScript = useRenderScript; } @@ -570,8 +588,6 @@ protected Void doInBackground(Void... params) { } //clear memory mBackground.recycle(); - mBackgroundView.destroyDrawingCache(); - mBackgroundView.setDrawingCacheEnabled(false); return null; } @@ -580,6 +596,9 @@ protected Void doInBackground(Void... params) { protected void onPostExecute(Void aVoid) { super.onPostExecute(aVoid); + mBackgroundView.destroyDrawingCache(); + mBackgroundView.setDrawingCacheEnabled(false); + mHoldingActivity.getWindow().addContentView( mBlurredBackgroundView, mBlurredBackgroundLayoutParams diff --git a/lib/src/main/java/fr/tvbarthel/lib/blurdialogfragment/BlurDialogFragment.java b/lib/src/main/java/fr/tvbarthel/lib/blurdialogfragment/BlurDialogFragment.java index a34c44d..57c7c94 100644 --- a/lib/src/main/java/fr/tvbarthel/lib/blurdialogfragment/BlurDialogFragment.java +++ b/lib/src/main/java/fr/tvbarthel/lib/blurdialogfragment/BlurDialogFragment.java @@ -1,6 +1,7 @@ package fr.tvbarthel.lib.blurdialogfragment; import android.annotation.TargetApi; +import android.app.Activity; import android.app.Dialog; import android.app.DialogFragment; import android.content.DialogInterface; @@ -32,6 +33,14 @@ public abstract class BlurDialogFragment extends DialogFragment { */ private boolean mDimmingEffect; + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + if (mBlurEngine != null) { + mBlurEngine.onAttach(activity); // re attached + } + } + @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -77,7 +86,7 @@ public void onStart() { int currentAnimation = dialog.getWindow().getAttributes().windowAnimations; if (currentAnimation == 0) { dialog.getWindow().getAttributes().windowAnimations - = R.style.BlurDialogFragment_Default_Animation; + = R.style.BlurDialogFragment_Default_Animation; } } super.onStart(); @@ -97,9 +106,9 @@ public void onDismiss(DialogInterface dialog) { } @Override - public void onDestroy() { - super.onDestroy(); - mBlurEngine.onDestroy(); + public void onDetach() { + super.onDetach(); + mBlurEngine.onDetach(); } @Override diff --git a/lib/src/main/java/fr/tvbarthel/lib/blurdialogfragment/SupportBlurDialogFragment.java b/lib/src/main/java/fr/tvbarthel/lib/blurdialogfragment/SupportBlurDialogFragment.java index dc46b87..cd9712d 100644 --- a/lib/src/main/java/fr/tvbarthel/lib/blurdialogfragment/SupportBlurDialogFragment.java +++ b/lib/src/main/java/fr/tvbarthel/lib/blurdialogfragment/SupportBlurDialogFragment.java @@ -1,5 +1,6 @@ package fr.tvbarthel.lib.blurdialogfragment; +import android.app.Activity; import android.app.Dialog; import android.content.DialogInterface; import android.os.Bundle; @@ -30,6 +31,14 @@ public abstract class SupportBlurDialogFragment extends DialogFragment { */ private boolean mDimmingEffect; + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + if (mBlurEngine != null) { + mBlurEngine.onAttach(activity); // re attached + } + } + @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -75,7 +84,7 @@ public void onStart() { int currentAnimation = dialog.getWindow().getAttributes().windowAnimations; if (currentAnimation == 0) { dialog.getWindow().getAttributes().windowAnimations - = R.style.BlurDialogFragment_Default_Animation; + = R.style.BlurDialogFragment_Default_Animation; } } super.onStart(); @@ -94,9 +103,9 @@ public void onDismiss(DialogInterface dialog) { } @Override - public void onDestroy() { - super.onDestroy(); - mBlurEngine.onDestroy(); + public void onDetach() { + super.onDetach(); + mBlurEngine.onDetach(); } @Override diff --git a/sample/src/main/java/fr/tvbarthel/lib/blurdialogfragment/sample/SampleActionBarActivity.java b/sample/src/main/java/fr/tvbarthel/lib/blurdialogfragment/sample/SampleActionBarActivity.java index 3e943d0..26cd6ac 100644 --- a/sample/src/main/java/fr/tvbarthel/lib/blurdialogfragment/sample/SampleActionBarActivity.java +++ b/sample/src/main/java/fr/tvbarthel/lib/blurdialogfragment/sample/SampleActionBarActivity.java @@ -2,7 +2,6 @@ import android.content.Intent; import android.os.Bundle; -import android.support.v7.app.ActionBarActivity; import android.support.v7.app.AppCompatActivity; import android.view.Menu; import android.view.MenuItem; @@ -107,13 +106,13 @@ public void onClick(View v) { switch (v.getId()) { case R.id.button: SampleSupportDialogFragment fragment - = SampleSupportDialogFragment.newInstance( - mBlurRadiusSeekbar.getProgress() + 1, - (mDownScaleFactorSeekbar.getProgress() / 10f) + 2, - mDimmingEnable.isChecked(), - mDebugMode.isChecked(), - mBlurredActionBar.isChecked(), - mUseRenderScript.isChecked() + = SampleSupportDialogFragment.newInstance( + mBlurRadiusSeekbar.getProgress() + 1, + (mDownScaleFactorSeekbar.getProgress() / 10f) + 2, + mDimmingEnable.isChecked(), + mDebugMode.isChecked(), + mBlurredActionBar.isChecked(), + mUseRenderScript.isChecked() ); fragment.show(getSupportFragmentManager(), "blur_sample"); break; From 46ebbd09481a1ba084a95192d7c1326812492885 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Barth=C3=A9l=C3=A9my?= Date: Thu, 12 May 2016 08:46:26 +0200 Subject: [PATCH 3/3] [Release] v2.1.6 of the library. Fix orientation change as well as retainInstance thanks to [IskuhiSargsyan](https://github.com/IskuhiSargsyan) report Tweak FastBlur implementation to avoid the allocation of 3 additional arrays for RGB channels thanks to [sh1](https://disqus.com/by/sh1sh1sh1/) feedback. --- README.md | 5 ++++- lib/build.gradle | 11 ++++++----- sample/build.gradle | 14 +++++++------- 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index a30544a..1e3032b 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ Gradle dependency Since the library is promoted on maven central, just add a new gradle dependency : ```groovy -compile 'fr.tvbarthel.blurdialogfragment:lib:2.1.5' + compile 'fr.tvbarthel.blurdialogfragment:lib:2.1.6' ``` Don't forget to check the [Use RenderScript in Your Project] (#use-renderscript-in-your-project) if you're planning to use it. @@ -242,6 +242,8 @@ public class SampleDialogFragment extends MyCustomDialogFragment { Benchmark ======= +# Benchmark outdated. Please refer to the debug option of the sample in order to compare FastBlur and RenderScript. + We used a Nexus 5 running a 4.4.4 stock rom for this bench. Down scale factor 8.0 & Blur Radius 8 : [Screenshot](/static/blur_8.0_8.png) @@ -285,6 +287,7 @@ Find more information on the [memory trace](http://tvbarthel.github.io/blur-dial Change logs ======= +* 2.1.6 : Fix orientation change as well as retainInstance thanks to [IskuhiSargsyan](https://github.com/IskuhiSargsyan) report and tweak FastBlur implementation to avoid the allocation of 3 additional arrays for RGB channels thanks to [sh1](https://disqus.com/by/sh1sh1sh1/) feedback. * 2.1.5 : Minor fixes thanks to [Edward S](https://github.com/edward-s) and [Tommy Chan](https://github.com/tommytcchan). * 2.1.4 : Fix NPE during the blurring process thanks to [Anth06ny](https://github.com/Anth06ny), [jacobtabak](https://github.com/jacobtabak) and [serega2593](https://github.com/serega2593) reports. * 2.1.3 : Remove unused resources thanks to [ligol](https://github.com/ligol) report. diff --git a/lib/build.gradle b/lib/build.gradle index b86a88e..f6cb6a0 100644 --- a/lib/build.gradle +++ b/lib/build.gradle @@ -4,15 +4,16 @@ apply plugin: 'com.jfrog.bintray' apply from: '../config/quality.gradle' group ='fr.tvbarthel.blurdialogfragment' -version = '2.1.5' +version = '2.1.6' + android { - compileSdkVersion 22 - buildToolsVersion "22.0.1" + compileSdkVersion 23 + buildToolsVersion "23.0.2" defaultConfig { minSdkVersion 9 - targetSdkVersion 22 + targetSdkVersion 23 renderscriptTargetApi 22 renderscriptSupportModeEnabled true } @@ -92,7 +93,7 @@ install { dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) - compile 'com.android.support:appcompat-v7:22.2.1' + compile 'com.android.support:appcompat-v7:23.1.1' } task sourcesJar(type: Jar) { diff --git a/sample/build.gradle b/sample/build.gradle index 33c07d9..8e989da 100644 --- a/sample/build.gradle +++ b/sample/build.gradle @@ -1,15 +1,15 @@ apply plugin: 'com.android.application' android { - compileSdkVersion 22 - buildToolsVersion "22.0.1" + compileSdkVersion 23 + buildToolsVersion "23.0.2" defaultConfig { applicationId "fr.tvbarthel.lib.blurdialogfragment.sample" minSdkVersion 9 - targetSdkVersion 22 - versionCode 6 - versionName "1.5" + targetSdkVersion 23 + versionCode 8 + versionName "1.7" renderscriptTargetApi 22 renderscriptSupportModeEnabled true } @@ -23,7 +23,7 @@ android { dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) - compile 'com.android.support:appcompat-v7:22.2.1' - compile 'com.android.support:cardview-v7:22.2.1' + compile 'com.android.support:appcompat-v7:23.1.1' + compile 'com.android.support:cardview-v7:23.1.1' compile project (":lib") }