2 * Copyright (C) 2014 The CyanogenMod Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package org.lineageos.eleven.cache;
18 import android.content.Context;
19 import android.graphics.Bitmap;
20 import android.graphics.drawable.Drawable;
21 import android.graphics.drawable.TransitionDrawable;
22 import android.support.v8.renderscript.Allocation;
23 import android.support.v8.renderscript.Element;
24 import android.support.v8.renderscript.RenderScript;
25 import android.support.v8.renderscript.ScriptIntrinsicBlur;
26 import android.util.Log;
27 import android.widget.ImageView;
29 import org.lineageos.eleven.cache.ImageWorker.ImageType;
30 import org.lineageos.eleven.widgets.BlurScrimImage;
32 import java.lang.ref.WeakReference;
35 * This will download the image (if needed) and create a blur and set the scrim as well on the
38 public class BlurBitmapWorkerTask extends BitmapWorkerTask<String, Void, BlurBitmapWorkerTask.ResultContainer> {
40 private static final String TAG = BlurBitmapWorkerTask.class.getSimpleName();
42 // if the image is too small, the blur will look bad post scale up so we use the min size
43 // to scale up before bluring
44 private static final int MIN_BITMAP_SIZE = 500;
45 // number of times to run the blur
46 private static final int NUM_BLUR_RUNS = 8;
47 // 25f is the max blur radius possible
48 private static final float BLUR_RADIUS = 25f;
50 // container for the result
51 public static class ResultContainer {
52 public TransitionDrawable mImageViewBitmapDrawable;
53 public int mPaletteColor;
57 * The {@link org.lineageos.eleven.widgets.BlurScrimImage} used to set the result
59 private final WeakReference<BlurScrimImage> mBlurScrimImage;
62 * RenderScript used to blur the image
64 protected final RenderScript mRenderScript;
67 * Constructor of <code>BlurBitmapWorkerTask</code>
68 * @param key used for caching the image
69 * @param blurScrimImage The {@link BlurScrimImage} to use.
70 * @param imageType The type of image URL to fetch for.
71 * @param fromDrawable what drawable to transition from
73 public BlurBitmapWorkerTask(final String key, final BlurScrimImage blurScrimImage,
74 final ImageType imageType, final Drawable fromDrawable,
75 final Context context, final RenderScript renderScript) {
76 super(key, blurScrimImage.getImageView(), imageType, fromDrawable, context);
77 mBlurScrimImage = new WeakReference<BlurScrimImage>(blurScrimImage);
78 mRenderScript = renderScript;
80 // use the existing image as the drawable and if it doesn't exist fallback to transparent
81 mFromDrawable = blurScrimImage.getImageView().getDrawable();
82 if (mFromDrawable == null) {
83 mFromDrawable = fromDrawable;
91 protected ResultContainer doInBackground(final String... params) {
96 Bitmap bitmap = getBitmapInBackground(params);
98 ResultContainer result = new ResultContainer();
100 Bitmap output = null;
102 if (bitmap != null) {
103 // now create the blur bitmap
104 Bitmap input = bitmap;
106 // if the image is too small, scale it up before running through the blur
107 if (input.getWidth() < MIN_BITMAP_SIZE || input.getHeight() < MIN_BITMAP_SIZE) {
108 float multiplier = Math.max(MIN_BITMAP_SIZE / (float)input.getWidth(),
109 MIN_BITMAP_SIZE / (float)input.getHeight());
110 input = input.createScaledBitmap(bitmap, (int)(input.getWidth() * multiplier),
111 (int)(input.getHeight() * multiplier), true);
112 // since we created a new bitmap, we can re-use the bitmap for our output
115 // if we aren't creating a new bitmap, create a new output bitmap
116 output = Bitmap.createBitmap(input.getWidth(), input.getHeight(), input.getConfig());
119 // run the blur multiple times
120 for (int i = 0; i < NUM_BLUR_RUNS; i++) {
122 final Allocation inputAlloc = Allocation.createFromBitmap(mRenderScript, input);
123 final Allocation outputAlloc = Allocation.createTyped(mRenderScript,
124 inputAlloc.getType());
125 final ScriptIntrinsicBlur script = ScriptIntrinsicBlur.create(mRenderScript,
126 Element.U8_4(mRenderScript));
128 script.setRadius(BLUR_RADIUS);
129 script.setInput(inputAlloc);
130 script.forEach(outputAlloc);
131 outputAlloc.copyTo(output);
133 // if we run more than 1 blur, the new input should be the old output
135 } catch (RuntimeException e) {
136 Log.w(TAG, "Cannot blur image. " + e.getMessage());
141 // Set the scrim color to be 50% gray
142 result.mPaletteColor = 0x7f000000;
144 // create the bitmap transition drawable
145 result.mImageViewBitmapDrawable = createImageTransitionDrawable(output,
146 ImageWorker.FADE_IN_TIME_SLOW, true, true);
158 protected void onPostExecute(ResultContainer resultContainer) {
159 BlurScrimImage blurScrimImage = mBlurScrimImage.get();
160 if (blurScrimImage != null) {
161 if (resultContainer == null) {
162 // if we have no image, then signal the transition to the default state
163 blurScrimImage.transitionToDefaultState();
165 // create the palette transition
166 TransitionDrawable paletteTransition = ImageWorker.createPaletteTransition(
168 resultContainer.mPaletteColor);
170 // set the transition drawable
171 blurScrimImage.setTransitionDrawable(resultContainer.mImageViewBitmapDrawable,
181 protected final ImageView getAttachedImageView() {
182 final BlurScrimImage blurImage = mBlurScrimImage.get();
183 final BitmapWorkerTask bitmapWorkerTask = ImageWorker.getBitmapWorkerTask(blurImage);
184 if (this == bitmapWorkerTask) {
185 return blurImage.getImageView();