diff --git a/transformations/build.gradle b/transformations/build.gradle index 9feb5f8..42eb616 100644 --- a/transformations/build.gradle +++ b/transformations/build.gradle @@ -11,6 +11,9 @@ android { versionCode "git rev-list origin/master --count".execute().text.toInteger() versionName VERSION_NAME + renderscriptTargetApi TARGET_SDK_VERSION as int + renderscriptSupportModeEnabled true + consumerProguardFiles 'proguard-rules.txt' } } diff --git a/transformations/src/main/java/jp/wasabeef/glide/transformations/SupportBlurTransformation.java b/transformations/src/main/java/jp/wasabeef/glide/transformations/SupportBlurTransformation.java new file mode 100644 index 0000000..240561e --- /dev/null +++ b/transformations/src/main/java/jp/wasabeef/glide/transformations/SupportBlurTransformation.java @@ -0,0 +1,101 @@ +package jp.wasabeef.glide.transformations; + +/** + * Copyright (C) 2018 Wasabeef + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.os.Build; +import android.support.v8.renderscript.RSRuntimeException; +import android.support.annotation.NonNull; +import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool; +import java.security.MessageDigest; +import jp.wasabeef.glide.transformations.internal.FastBlur; +import jp.wasabeef.glide.transformations.internal.SupportRSBlur; + +public class SupportBlurTransformation extends BitmapTransformation { + + private static final int VERSION = 1; + private static final String ID = + "jp.wasabeef.glide.transformations.SupportBlurTransformation." + VERSION; + private static final byte[] ID_BYTES = ID.getBytes(CHARSET); + + private static int MAX_RADIUS = 25; + private static int DEFAULT_DOWN_SAMPLING = 1; + + private int radius; + private int sampling; + + public SupportBlurTransformation() { + this(MAX_RADIUS, DEFAULT_DOWN_SAMPLING); + } + + public SupportBlurTransformation(int radius) { + this(radius, DEFAULT_DOWN_SAMPLING); + } + + public SupportBlurTransformation(int radius, int sampling) { + this.radius = radius; + this.sampling = sampling; + } + + @Override protected Bitmap transform(@NonNull Context context, @NonNull BitmapPool pool, + @NonNull Bitmap toTransform, int outWidth, int outHeight) { + + int width = toTransform.getWidth(); + int height = toTransform.getHeight(); + int scaledWidth = width / sampling; + int scaledHeight = height / sampling; + + Bitmap bitmap = pool.get(scaledWidth, scaledHeight, Bitmap.Config.ARGB_8888); + + Canvas canvas = new Canvas(bitmap); + canvas.scale(1 / (float) sampling, 1 / (float) sampling); + Paint paint = new Paint(); + paint.setFlags(Paint.FILTER_BITMAP_FLAG); + canvas.drawBitmap(toTransform, 0, 0, paint); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { + try { + bitmap = SupportRSBlur.blur(context, bitmap, radius); + } catch (RSRuntimeException e) { + bitmap = FastBlur.blur(bitmap, radius, true); + } + } else { + bitmap = FastBlur.blur(bitmap, radius, true); + } + + return bitmap; + } + + @Override public String toString() { + return "SupportBlurTransformation(radius=" + radius + ", sampling=" + sampling + ")"; + } + + @Override public boolean equals(Object o) { + return o instanceof SupportBlurTransformation; + } + + @Override public int hashCode() { + return ID.hashCode(); + } + + @Override public void updateDiskCacheKey(MessageDigest messageDigest) { + messageDigest.update(ID_BYTES); + } +} diff --git a/transformations/src/main/java/jp/wasabeef/glide/transformations/internal/SupportRSBlur.java b/transformations/src/main/java/jp/wasabeef/glide/transformations/internal/SupportRSBlur.java new file mode 100644 index 0000000..254366e --- /dev/null +++ b/transformations/src/main/java/jp/wasabeef/glide/transformations/internal/SupportRSBlur.java @@ -0,0 +1,70 @@ +package jp.wasabeef.glide.transformations.internal; + +import android.annotation.TargetApi; +import android.content.Context; +import android.graphics.Bitmap; +import android.os.Build; +import android.support.v8.renderscript.Allocation; +import android.support.v8.renderscript.Element; +import android.support.v8.renderscript.RSRuntimeException; +import android.support.v8.renderscript.RenderScript; +import android.support.v8.renderscript.ScriptIntrinsicBlur; + +/** + * Copyright (C) 2018 Wasabeef + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +public class SupportRSBlur { + + @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2) + public static Bitmap blur(Context context, Bitmap bitmap, int radius) throws RSRuntimeException { + RenderScript rs = null; + Allocation input = null; + Allocation output = null; + ScriptIntrinsicBlur blur = null; + try { + rs = RenderScript.create(context); + rs.setMessageHandler(new RenderScript.RSMessageHandler()); + input = Allocation.createFromBitmap(rs, bitmap, Allocation.MipmapControl.MIPMAP_NONE, + Allocation.USAGE_SCRIPT); + output = Allocation.createTyped(rs, input.getType()); + blur = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs)); + + blur.setInput(input); + blur.setRadius(radius); + blur.forEach(output); + output.copyTo(bitmap); + } finally { + if (rs != null) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + RenderScript.releaseAllContexts(); + } else { + rs.destroy(); + } + } + if (input != null) { + input.destroy(); + } + if (output != null) { + output.destroy(); + } + if (blur != null) { + blur.destroy(); + } + } + + return bitmap; + } +}