171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck/* 271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck * Copyright (C) 2013 The Android Open Source Project 371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck * 471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck * Licensed under the Apache License, Version 2.0 (the "License"); 571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck * you may not use this file except in compliance with the License. 671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck * You may obtain a copy of the License at 771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck * 871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck * http://www.apache.org/licenses/LICENSE-2.0 971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck * 1071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck * Unless required by applicable law or agreed to in writing, software 1171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck * distributed under the License is distributed on an "AS IS" BASIS, 1271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck * See the License for the specific language governing permissions and 1471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck * limitations under the License. 1571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck */ 1671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 1771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reckpackage com.android.photos.drawables; 1871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 1971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reckimport android.graphics.Bitmap; 2071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reckimport android.graphics.BitmapFactory; 2171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reckimport android.graphics.Canvas; 2271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reckimport android.graphics.ColorFilter; 2371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reckimport android.graphics.Matrix; 2471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reckimport android.graphics.Paint; 2571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reckimport android.graphics.PixelFormat; 2671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reckimport android.graphics.Rect; 2771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reckimport android.graphics.drawable.Drawable; 2871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reckimport android.util.Log; 2971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 30b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescuimport com.android.photos.data.GalleryBitmapPool; 31b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu 32b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescuimport java.io.InputStream; 3371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reckimport java.util.concurrent.ExecutorService; 3471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reckimport java.util.concurrent.Executors; 3571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 36b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescupublic abstract class AutoThumbnailDrawable<T> extends Drawable { 3771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 38b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu private static final String TAG = "AutoThumbnailDrawable"; 3971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 4071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck private static ExecutorService sThreadPool = Executors.newSingleThreadExecutor(); 41b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu private static GalleryBitmapPool sBitmapPool = GalleryBitmapPool.getInstance(); 4271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck private static byte[] sTempStorage = new byte[64 * 1024]; 4371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 44d26f1ad5a859da0847ab181df2eebd45e155118bJohn Reck // UI thread only 4571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck private Paint mPaint = new Paint(); 46d26f1ad5a859da0847ab181df2eebd45e155118bJohn Reck private Matrix mDrawMatrix = new Matrix(); 47d26f1ad5a859da0847ab181df2eebd45e155118bJohn Reck 48d26f1ad5a859da0847ab181df2eebd45e155118bJohn Reck // Decoder thread only 49d26f1ad5a859da0847ab181df2eebd45e155118bJohn Reck private BitmapFactory.Options mOptions = new BitmapFactory.Options(); 50d26f1ad5a859da0847ab181df2eebd45e155118bJohn Reck 51d26f1ad5a859da0847ab181df2eebd45e155118bJohn Reck // Shared, guarded by mLock 52d26f1ad5a859da0847ab181df2eebd45e155118bJohn Reck private Object mLock = new Object(); 53d26f1ad5a859da0847ab181df2eebd45e155118bJohn Reck private Bitmap mBitmap; 54b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu protected T mData; 5571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck private boolean mIsQueued; 5671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck private int mImageWidth, mImageHeight; 5771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck private Rect mBounds = new Rect(); 58b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu private int mSampleSize = 1; 5971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 6071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck public AutoThumbnailDrawable() { 6171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mPaint.setAntiAlias(true); 6271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mPaint.setFilterBitmap(true); 6371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mDrawMatrix.reset(); 6471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mOptions.inTempStorage = sTempStorage; 6571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 6671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 67b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu protected abstract byte[] getPreferredImageBytes(T data); 68b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu protected abstract InputStream getFallbackImageStream(T data); 69b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu protected abstract boolean dataChangedLocked(T data); 70b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu 71b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu public void setImage(T data, int width, int height) { 72b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu if (!dataChangedLocked(data)) return; 73d26f1ad5a859da0847ab181df2eebd45e155118bJohn Reck synchronized (mLock) { 7471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mImageWidth = width; 7571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mImageHeight = height; 76b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu mData = data; 77b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu setBitmapLocked(null); 7871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck refreshSampleSizeLocked(); 7971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 8071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck invalidateSelf(); 8171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 8271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 83b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu private void setBitmapLocked(Bitmap b) { 84b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu if (b == mBitmap) { 85b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu return; 86b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu } 87b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu if (mBitmap != null) { 88b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu sBitmapPool.put(mBitmap); 89b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu } 90b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu mBitmap = b; 91b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu } 92b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu 9371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck @Override 9471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck protected void onBoundsChange(Rect bounds) { 9571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck super.onBoundsChange(bounds); 96d26f1ad5a859da0847ab181df2eebd45e155118bJohn Reck synchronized (mLock) { 9771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mBounds.set(bounds); 9871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (mBounds.isEmpty()) { 9971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mBitmap = null; 10071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } else { 10171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck refreshSampleSizeLocked(); 10271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck updateDrawMatrixLocked(); 10371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 10471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 10571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck invalidateSelf(); 10671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 10771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 10871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck @Override 10971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck public void draw(Canvas canvas) { 11071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (mBitmap != null) { 11171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck canvas.save(); 11271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck canvas.clipRect(mBounds); 11371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck canvas.concat(mDrawMatrix); 11471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck canvas.drawBitmap(mBitmap, 0, 0, mPaint); 11571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck canvas.restore(); 11671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } else { 11771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck // TODO: Draw placeholder...? 11871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 11971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 12071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 12171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck private void updateDrawMatrixLocked() { 12271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (mBitmap == null || mBounds.isEmpty()) { 12371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mDrawMatrix.reset(); 12471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck return; 12571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 12671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 12771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck float scale; 12871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck float dx = 0, dy = 0; 12971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 13071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck int dwidth = mBitmap.getWidth(); 13171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck int dheight = mBitmap.getHeight(); 13271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck int vwidth = mBounds.width(); 13371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck int vheight = mBounds.height(); 13471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 13571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck // Calculates a matrix similar to ScaleType.CENTER_CROP 13671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (dwidth * vheight > vwidth * dheight) { 13771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck scale = (float) vheight / (float) dheight; 13871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck dx = (vwidth - dwidth * scale) * 0.5f; 13971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } else { 14071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck scale = (float) vwidth / (float) dwidth; 14171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck dy = (vheight - dheight * scale) * 0.5f; 14271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 14371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (scale < .8f) { 14471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck Log.w(TAG, "sample size was too small! Overdrawing! " + scale + ", " + mSampleSize); 14571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } else if (scale > 1.5f) { 14671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck Log.w(TAG, "Potential quality loss! " + scale + ", " + mSampleSize); 14771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 14871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 14971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mDrawMatrix.setScale(scale, scale); 15071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mDrawMatrix.postTranslate((int) (dx + 0.5f), (int) (dy + 0.5f)); 15171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 15271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 15371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck private int calculateSampleSizeLocked(int dwidth, int dheight) { 15471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck float scale; 15571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 15671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck int vwidth = mBounds.width(); 15771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck int vheight = mBounds.height(); 15871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 15971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck // Inverse of updateDrawMatrixLocked 16071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (dwidth * vheight > vwidth * dheight) { 16171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck scale = (float) dheight / (float) vheight; 16271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } else { 16371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck scale = (float) dwidth / (float) vwidth; 16471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 165b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu int result = Math.round(scale); 166b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu return result > 0 ? result : 1; 16771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 16871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 16971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck private void refreshSampleSizeLocked() { 170a73acc17eea200014edba9c9c6a40f1c632fa57dBobby Georgescu if (mBounds.isEmpty() || mImageWidth == 0 || mImageHeight == 0) { 171a73acc17eea200014edba9c9c6a40f1c632fa57dBobby Georgescu return; 172a73acc17eea200014edba9c9c6a40f1c632fa57dBobby Georgescu } 17371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 17471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck int sampleSize = calculateSampleSizeLocked(mImageWidth, mImageHeight); 17571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (sampleSize != mSampleSize || mBitmap == null) { 17671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mSampleSize = sampleSize; 17771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck loadBitmapLocked(); 17871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 17971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 18071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 18171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck private void loadBitmapLocked() { 18271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (!mIsQueued && !mBounds.isEmpty()) { 18371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck unscheduleSelf(mUpdateBitmap); 18471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck sThreadPool.execute(mLoadBitmap); 18571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mIsQueued = true; 18671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 18771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 18871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 18971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck public float getAspectRatio() { 19071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck return (float) mImageWidth / (float) mImageHeight; 19171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 19271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 19371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck @Override 19471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck public int getIntrinsicWidth() { 19571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck return -1; 19671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 19771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 19871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck @Override 19971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck public int getIntrinsicHeight() { 20071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck return -1; 20171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 20271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 20371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck @Override 20471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck public int getOpacity() { 20571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck Bitmap bm = mBitmap; 20671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck return (bm == null || bm.hasAlpha() || mPaint.getAlpha() < 255) ? 20771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck PixelFormat.TRANSLUCENT : PixelFormat.OPAQUE; 20871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 20971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 21071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck @Override 21171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck public void setAlpha(int alpha) { 21271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck int oldAlpha = mPaint.getAlpha(); 21371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (alpha != oldAlpha) { 21471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mPaint.setAlpha(alpha); 21571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck invalidateSelf(); 21671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 21771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 21871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 21971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck @Override 22071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck public void setColorFilter(ColorFilter cf) { 22171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mPaint.setColorFilter(cf); 22271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck invalidateSelf(); 22371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 22471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 22571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck private final Runnable mLoadBitmap = new Runnable() { 22671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck @Override 22771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck public void run() { 228b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu T data; 229b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu synchronized (mLock) { 230b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu data = mData; 231b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu } 232b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu int preferredSampleSize = 1; 233b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu byte[] preferred = getPreferredImageBytes(data); 234b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu boolean hasPreferred = (preferred != null && preferred.length > 0); 235b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu if (hasPreferred) { 236b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu mOptions.inJustDecodeBounds = true; 237b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu BitmapFactory.decodeByteArray(preferred, 0, preferred.length, mOptions); 238b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu mOptions.inJustDecodeBounds = false; 239b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu } 240b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu int sampleSize, width, height; 241d26f1ad5a859da0847ab181df2eebd45e155118bJohn Reck synchronized (mLock) { 242b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu if (dataChangedLocked(data)) { 243b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu return; 244b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu } 245b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu width = mImageWidth; 246b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu height = mImageHeight; 247b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu if (hasPreferred) { 248b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu preferredSampleSize = calculateSampleSizeLocked( 249b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu mOptions.outWidth, mOptions.outHeight); 250b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu } 251b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu sampleSize = calculateSampleSizeLocked(width, height); 25271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mIsQueued = false; 25371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 254b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu Bitmap b = null; 255b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu InputStream is = null; 25671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck try { 257b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu if (hasPreferred) { 258b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu mOptions.inSampleSize = preferredSampleSize; 259b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu mOptions.inBitmap = sBitmapPool.get( 260b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu mOptions.outWidth / preferredSampleSize, 261b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu mOptions.outHeight / preferredSampleSize); 262b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu b = BitmapFactory.decodeByteArray(preferred, 0, preferred.length, mOptions); 263b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu if (mOptions.inBitmap != null && b != mOptions.inBitmap) { 264b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu sBitmapPool.put(mOptions.inBitmap); 265b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu mOptions.inBitmap = null; 266b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu } 267b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu } 268b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu if (b == null) { 269b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu is = getFallbackImageStream(data); 270b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu mOptions.inSampleSize = sampleSize; 271b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu mOptions.inBitmap = sBitmapPool.get(width / sampleSize, height / sampleSize); 272b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu b = BitmapFactory.decodeStream(is, null, mOptions); 273b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu if (mOptions.inBitmap != null && b != mOptions.inBitmap) { 274b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu sBitmapPool.put(mOptions.inBitmap); 275b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu mOptions.inBitmap = null; 27671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 27771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 27871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } catch (Exception e) { 279b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu Log.d(TAG, "Failed to fetch bitmap", e); 28071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck return; 28171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } finally { 28271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck try { 283b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu if (is != null) { 284b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu is.close(); 285d26f1ad5a859da0847ab181df2eebd45e155118bJohn Reck } 28671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } catch (Exception e) {} 287b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu if (b != null) { 288b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu synchronized (mLock) { 289b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu if (!dataChangedLocked(data)) { 290b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu setBitmapLocked(b); 291b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu scheduleSelf(mUpdateBitmap, 0); 292b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu } 293b4338b0fefea317bf18a3116c1bf231097535d35Bobby Georgescu } 29471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 29571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 29671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 29771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck }; 29871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 29971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck private final Runnable mUpdateBitmap = new Runnable() { 30071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck @Override 30171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck public void run() { 30271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck synchronized (AutoThumbnailDrawable.this) { 30371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck updateDrawMatrixLocked(); 30471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck invalidateSelf(); 30571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 30671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 30771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck }; 30871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 30971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck} 310