2 * Copyright (C) 2011 The Android Open Source 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.
17 package com.android.gallery3d.data;
19 import android.graphics.Bitmap;
20 import android.graphics.BitmapFactory;
21 import android.graphics.BitmapFactory.Options;
23 import com.android.gallery3d.common.Utils;
24 import com.android.gallery3d.ui.Log;
25 import com.android.gallery3d.util.ThreadPool.JobContext;
27 import java.io.FileDescriptor;
28 import java.util.ArrayList;
30 public class BitmapPool {
31 private static final String TAG = "BitmapPool";
33 private final ArrayList<Bitmap> mPool;
34 private final int mPoolLimit;
36 // mOneSize is true if the pool can only cache Bitmap with one size.
37 private final boolean mOneSize;
38 private final int mWidth, mHeight; // only used if mOneSize is true
40 // Construct a BitmapPool which caches bitmap with the specified size.
41 public BitmapPool(int width, int height, int poolLimit) {
44 mPoolLimit = poolLimit;
45 mPool = new ArrayList<Bitmap>(poolLimit);
49 // Construct a BitmapPool which caches bitmap with any size;
50 public BitmapPool(int poolLimit) {
53 mPoolLimit = poolLimit;
54 mPool = new ArrayList<Bitmap>(poolLimit);
58 // Get a Bitmap from the pool.
59 public synchronized Bitmap getBitmap() {
60 Utils.assertTrue(mOneSize);
61 int size = mPool.size();
62 return size > 0 ? mPool.remove(size - 1) : null;
65 // Get a Bitmap from the pool with the specified size.
66 public synchronized Bitmap getBitmap(int width, int height) {
67 Utils.assertTrue(!mOneSize);
68 for (int i = mPool.size() - 1; i >= 0; i--) {
69 Bitmap b = mPool.get(i);
70 if (b.getWidth() == width && b.getHeight() == height) {
71 return mPool.remove(i);
77 // Put a Bitmap into the pool, if the Bitmap has a proper size. Otherwise
78 // the Bitmap will be recycled. If the pool is full, an old Bitmap will be
80 public void recycle(Bitmap bitmap) {
81 if (bitmap == null) return;
82 if (mOneSize && ((bitmap.getWidth() != mWidth) ||
83 (bitmap.getHeight() != mHeight))) {
88 if (mPool.size() >= mPoolLimit) mPool.remove(0);
93 public synchronized void clear() {
97 private Bitmap findCachedBitmap(JobContext jc,
98 byte[] data, int offset, int length, Options options) {
99 if (mOneSize) return getBitmap();
100 DecodeUtils.decodeBounds(jc, data, offset, length, options);
101 return getBitmap(options.outWidth, options.outHeight);
104 private Bitmap findCachedBitmap(JobContext jc,
105 FileDescriptor fileDescriptor, Options options) {
106 if (mOneSize) return getBitmap();
107 DecodeUtils.decodeBounds(jc, fileDescriptor, options);
108 return getBitmap(options.outWidth, options.outHeight);
111 public Bitmap decode(JobContext jc,
112 byte[] data, int offset, int length, BitmapFactory.Options options) {
113 if (options == null) options = new BitmapFactory.Options();
114 if (options.inSampleSize < 1) options.inSampleSize = 1;
115 options.inPreferredConfig = Bitmap.Config.ARGB_8888;
116 options.inBitmap = (options.inSampleSize == 1)
117 ? findCachedBitmap(jc, data, offset, length, options) : null;
119 Bitmap bitmap = DecodeUtils.decode(jc, data, offset, length, options);
120 if (options.inBitmap != null && options.inBitmap != bitmap) {
121 recycle(options.inBitmap);
122 options.inBitmap = null;
125 } catch (IllegalArgumentException e) {
126 if (options.inBitmap == null) throw e;
128 Log.w(TAG, "decode fail with a given bitmap, try decode to a new bitmap");
129 recycle(options.inBitmap);
130 options.inBitmap = null;
131 return DecodeUtils.decode(jc, data, offset, length, options);
135 // This is the same as the method above except the source data comes
136 // from a file descriptor instead of a byte array.
137 public Bitmap decode(JobContext jc,
138 FileDescriptor fileDescriptor, Options options) {
139 if (options == null) options = new BitmapFactory.Options();
140 if (options.inSampleSize < 1) options.inSampleSize = 1;
141 options.inPreferredConfig = Bitmap.Config.ARGB_8888;
142 options.inBitmap = (options.inSampleSize == 1)
143 ? findCachedBitmap(jc, fileDescriptor, options) : null;
145 Bitmap bitmap = DecodeUtils.decode(jc, fileDescriptor, options);
146 if (options.inBitmap != null&& options.inBitmap != bitmap) {
147 recycle(options.inBitmap);
148 options.inBitmap = null;
151 } catch (IllegalArgumentException e) {
152 if (options.inBitmap == null) throw e;
154 Log.w(TAG, "decode fail with a given bitmap, try decode to a new bitmap");
155 recycle(options.inBitmap);
156 options.inBitmap = null;
157 return DecodeUtils.decode(jc, fileDescriptor, options);