OSDN Git Service

75db039f6623ec8f8d76f129e2a00eb5218a2dd9
[android-x86/packages-apps-Eleven.git] / src / org / lineageos / eleven / cache / BlurBitmapWorkerTask.java
1 /*
2 * Copyright (C) 2014 The CyanogenMod Project
3 *
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
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
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.
15 */
16 package org.lineageos.eleven.cache;
17
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;
28
29 import org.lineageos.eleven.cache.ImageWorker.ImageType;
30 import org.lineageos.eleven.widgets.BlurScrimImage;
31
32 import java.lang.ref.WeakReference;
33
34 /**
35  * This will download the image (if needed) and create a blur and set the scrim as well on the
36  * BlurScrimImage
37  */
38 public class BlurBitmapWorkerTask extends BitmapWorkerTask<String, Void, BlurBitmapWorkerTask.ResultContainer> {
39
40     private static final String TAG = BlurBitmapWorkerTask.class.getSimpleName();
41
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;
49
50     // container for the result
51     public static class ResultContainer {
52         public TransitionDrawable mImageViewBitmapDrawable;
53         public int mPaletteColor;
54     }
55
56     /**
57      * The {@link org.lineageos.eleven.widgets.BlurScrimImage} used to set the result
58      */
59     private final WeakReference<BlurScrimImage> mBlurScrimImage;
60
61     /**
62      * RenderScript used to blur the image
63      */
64     protected final RenderScript mRenderScript;
65
66     /**
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
72      */
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;
79
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;
84         }
85     }
86
87     /**
88      * {@inheritDoc}
89      */
90     @Override
91     protected ResultContainer doInBackground(final String... params) {
92         if (isCancelled()) {
93             return null;
94         }
95
96         Bitmap bitmap = getBitmapInBackground(params);
97
98         ResultContainer result = new ResultContainer();
99
100         Bitmap output = null;
101
102         if (bitmap != null) {
103             // now create the blur bitmap
104             Bitmap input = bitmap;
105
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
113                 output = input;
114             } else {
115                 // if we aren't creating a new bitmap, create a new output bitmap
116                 output = Bitmap.createBitmap(input.getWidth(), input.getHeight(), input.getConfig());
117             }
118
119             // run the blur multiple times
120             for (int i = 0; i < NUM_BLUR_RUNS; i++) {
121                 try {
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));
127
128                     script.setRadius(BLUR_RADIUS);
129                     script.setInput(inputAlloc);
130                     script.forEach(outputAlloc);
131                     outputAlloc.copyTo(output);
132
133                     // if we run more than 1 blur, the new input should be the old output
134                     input = output;
135                 } catch (RuntimeException e) {
136                     Log.w(TAG, "Cannot blur image. " + e.getMessage());
137                     break;
138                 }
139             }
140
141             // Set the scrim color to be 50% gray
142             result.mPaletteColor = 0x7f000000;
143
144             // create the bitmap transition drawable
145             result.mImageViewBitmapDrawable = createImageTransitionDrawable(output,
146                     ImageWorker.FADE_IN_TIME_SLOW, true, true);
147
148             return result;
149         }
150
151         return null;
152     }
153
154     /**
155      * {@inheritDoc}
156      */
157     @Override
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();
164             } else {
165                 // create the palette transition
166                 TransitionDrawable paletteTransition = ImageWorker.createPaletteTransition(
167                         blurScrimImage,
168                         resultContainer.mPaletteColor);
169
170                 // set the transition drawable
171                 blurScrimImage.setTransitionDrawable(resultContainer.mImageViewBitmapDrawable,
172                         paletteTransition);
173             }
174         }
175     }
176
177     /**
178      * {@inheritDoc}
179      */
180     @Override
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();
186         }
187         return null;
188     }
189 }