-// Copyright 2012 Google Inc. All Rights Reserved.
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * 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.
+ */
package com.android.gallery3d.data;
import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.BitmapFactory.Options;
-import com.android.gallery3d.ui.Log;
-import com.android.gallery3d.util.ThreadPool.JobContext;
+import com.android.gallery3d.common.Utils;
-import java.io.FileDescriptor;
import java.util.ArrayList;
public class BitmapPool {
private static final String TAG = "BitmapPool";
- private static final int POOL_SIZE = 16;
- private final ArrayList<Bitmap> mPool = new ArrayList<Bitmap>(POOL_SIZE);
+ private final ArrayList<Bitmap> mPool;
+ private final int mPoolLimit;
- private final int mWidth;
- private final int mHeight;
+ // mOneSize is true if the pool can only cache Bitmap with one size.
+ private final boolean mOneSize;
+ private final int mWidth, mHeight; // only used if mOneSize is true
- public BitmapPool(int width, int height) {
+ // Construct a BitmapPool which caches bitmap with the specified size.
+ public BitmapPool(int width, int height, int poolLimit) {
mWidth = width;
mHeight = height;
+ mPoolLimit = poolLimit;
+ mPool = new ArrayList<Bitmap>(poolLimit);
+ mOneSize = true;
}
+ // Construct a BitmapPool which caches bitmap with any size;
+ public BitmapPool(int poolLimit) {
+ mWidth = -1;
+ mHeight = -1;
+ mPoolLimit = poolLimit;
+ mPool = new ArrayList<Bitmap>(poolLimit);
+ mOneSize = false;
+ }
+
+ // Get a Bitmap from the pool.
public synchronized Bitmap getBitmap() {
+ Utils.assertTrue(mOneSize);
int size = mPool.size();
return size > 0 ? mPool.remove(size - 1) : null;
}
+ // Get a Bitmap from the pool with the specified size.
+ public synchronized Bitmap getBitmap(int width, int height) {
+ Utils.assertTrue(!mOneSize);
+ for (int i = mPool.size() - 1; i >= 0; i--) {
+ Bitmap b = mPool.get(i);
+ if (b.getWidth() == width && b.getHeight() == height) {
+ return mPool.remove(i);
+ }
+ }
+ return null;
+ }
+
+ // Put a Bitmap into the pool, if the Bitmap has a proper size. Otherwise
+ // the Bitmap will be recycled. If the pool is full, an old Bitmap will be
+ // recycled.
public void recycle(Bitmap bitmap) {
if (bitmap == null) return;
- if ((bitmap.getWidth() != mWidth) || (bitmap.getHeight() != mHeight)) {
+ if (mOneSize && ((bitmap.getWidth() != mWidth) ||
+ (bitmap.getHeight() != mHeight))) {
bitmap.recycle();
return;
}
synchronized (this) {
- if (mPool.size() < POOL_SIZE) mPool.add(bitmap);
+ if (mPool.size() >= mPoolLimit) mPool.remove(0);
+ mPool.add(bitmap);
}
}
mPool.clear();
}
- public Bitmap decode(JobContext jc,
- byte[] data, int offset, int length, BitmapFactory.Options options) {
- if (options == null) options = new BitmapFactory.Options();
- if (options.inSampleSize < 1) options.inSampleSize = 1;
- options.inPreferredConfig = Bitmap.Config.ARGB_8888;
- options.inBitmap = (options.inSampleSize == 1) ? getBitmap() : null;
- try {
- Bitmap bitmap = DecodeUtils.decode(jc, data, offset, length, options);
- if (options.inBitmap != null && options.inBitmap != bitmap) {
- recycle(options.inBitmap);
- options.inBitmap = null;
- }
- return bitmap;
- } catch (IllegalArgumentException e) {
- if (options.inBitmap == null) throw e;
-
- Log.w(TAG, "decode fail with a given bitmap, try decode to a new bitmap");
- recycle(options.inBitmap);
- options.inBitmap = null;
- return DecodeUtils.decode(jc, data, offset, length, options);
- }
- }
-
- // This is the same as the method above except the source data comes
- // from a file descriptor instead of a byte array.
- public Bitmap decode(JobContext jc,
- FileDescriptor fileDescriptor, Options options) {
- if (options == null) options = new BitmapFactory.Options();
- if (options.inSampleSize < 1) options.inSampleSize = 1;
- options.inPreferredConfig = Bitmap.Config.ARGB_8888;
- options.inBitmap = (options.inSampleSize == 1) ? getBitmap() : null;
- try {
- Bitmap bitmap = DecodeUtils.decode(jc, fileDescriptor, options);
- if (options.inBitmap != null&& options.inBitmap != bitmap) {
- recycle(options.inBitmap);
- options.inBitmap = null;
- }
- return bitmap;
- } catch (IllegalArgumentException e) {
- if (options.inBitmap == null) throw e;
-
- Log.w(TAG, "decode fail with a given bitmap, try decode to a new bitmap");
- recycle(options.inBitmap);
- options.inBitmap = null;
- return DecodeUtils.decode(jc, fileDescriptor, options);
- }
+ public boolean isOneSize() {
+ return mOneSize;
}
}