Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import android.graphics.Rect;
import android.os.Build;
import android.support.v4.util.Pools;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.SparseIntArray;
Expand All @@ -44,7 +45,9 @@ public class BlockImageLoader {

public static boolean DEBUG = false;
static final String TAG = "Loader";
private static Pools.SynchronizedPool<Bitmap> bitmapPool = new Pools.SynchronizedPool<>(6);
private static final String IMAGE_PNG = "png";

private Pools.SynchronizedPool<Bitmap> bitmapPool = new Pools.SynchronizedPool<>(6);
private Pools.SimplePool<BlockData> blockDataPool = new Pools.SimplePool<>(64);
private Pools.SimplePool<DrawData> drawDataPool = new Pools.SimplePool<>(64);
private LoadData mLoadData;
Expand Down Expand Up @@ -141,15 +144,15 @@ public void loadImageBlocks(List<DrawData> drawDataList, float imageScale, Rect
}
drawDataList.clear();

if (loadData.mDecoder == null) {
if (loadData.mDecoder == null || loadData.options == null) {
if (isUnRunning(loadData.task)) {
loadData.task = new LoadImageInfoTask(loadData, onImageLoadListener, onLoadStateChangeListener);
exeTask(loadData.task);
}
return;
}
int imageWidth = loadData.imageWidth;
int imageHeight = loadData.imageHeight;
int imageWidth = loadData.options.outWidth;
int imageHeight = loadData.options.outHeight;
BitmapRegionDecoder decoder = loadData.mDecoder;
if (loadData.thumbnailBlockData == null) {
int screenWidth = context.getResources().getDisplayMetrics().widthPixels;
Expand Down Expand Up @@ -377,7 +380,7 @@ public void loadImageBlocks(List<DrawData> drawDataList, float imageScale, Rect
for (int col = startCol; col < endCol; col++) {
positionKey.set(row, col);
//blockData可能为null
BlockData blockData = addRequestBlock(positionKey, tempCurrentDataMap.get(positionKey), loadData.currentScaleDataMap, scale, imageWidth, imageHeight, decoder);
BlockData blockData = addRequestBlock(positionKey, tempCurrentDataMap.get(positionKey), loadData.currentScaleDataMap, scale, imageWidth, imageHeight, decoder, loadData.options);
Bitmap bitmap = blockData.bitmap;
if (bitmap != null) {
DrawData drawData = drawDataPool.acquire();
Expand Down Expand Up @@ -412,30 +415,30 @@ public void loadImageBlocks(List<DrawData> drawDataList, float imageScale, Rect
for (int row = cacheStartRow; row < startRow; row++) {
for (int col = cacheStartCol; col < cacheEndCol; col++) {
positionKey.set(row, col);
addRequestBlock(positionKey, tempCurrentDataMap.get(positionKey), loadData.currentScaleDataMap, scale, imageWidth, imageHeight, decoder);
addRequestBlock(positionKey, tempCurrentDataMap.get(positionKey), loadData.currentScaleDataMap, scale, imageWidth, imageHeight, decoder, loadData.options);
}
}
// 下 #########
for (int row = endRow; row < cacheEndRow; row++) {
for (int col = cacheStartCol; col < cacheEndCol; col++) {
positionKey.set(row, col);
addRequestBlock(positionKey, tempCurrentDataMap.get(positionKey), loadData.currentScaleDataMap, scale, imageWidth, imageHeight, decoder);
addRequestBlock(positionKey, tempCurrentDataMap.get(positionKey), loadData.currentScaleDataMap, scale, imageWidth, imageHeight, decoder, loadData.options);
}
}
// # 左
// #
for (int row = startRow; row < endRow; row++) {
for (int col = cacheStartCol; col < startCol; col++) {
positionKey.set(row, col);
addRequestBlock(positionKey, tempCurrentDataMap.get(positionKey), loadData.currentScaleDataMap, scale, imageWidth, imageHeight, decoder);
addRequestBlock(positionKey, tempCurrentDataMap.get(positionKey), loadData.currentScaleDataMap, scale, imageWidth, imageHeight, decoder, loadData.options);
}
}
// # 右
// #
for (int row = startRow; row < endRow; row++) {
for (int col = endCol; col < cacheEndCol; col++) {
positionKey.set(row, col);
addRequestBlock(positionKey, tempCurrentDataMap.get(positionKey), loadData.currentScaleDataMap, scale, imageWidth, imageHeight, decoder);
addRequestBlock(positionKey, tempCurrentDataMap.get(positionKey), loadData.currentScaleDataMap, scale, imageWidth, imageHeight, decoder, loadData.options);
}
}
//移除掉那些没被用到的缓存的图片块
Expand Down Expand Up @@ -592,7 +595,7 @@ private void recycleBlock(BlockData block) {
blockDataPool.release(block);
}

private BlockData addRequestBlock(Position positionKey, BlockData blockData, Map<Position, BlockData> currentDataMap, int scale, int imageWidth, int imageHeight, BitmapRegionDecoder decoder) {
private BlockData addRequestBlock(Position positionKey, BlockData blockData, Map<Position, BlockData> currentDataMap, int scale, int imageWidth, int imageHeight, BitmapRegionDecoder decoder, BitmapFactory.Options options) {
if (blockData == null) {
blockData = blockDataPool.acquire();
if (blockData == null) {
Expand All @@ -606,7 +609,7 @@ private BlockData addRequestBlock(Position positionKey, BlockData blockData, Map
}
}
if (blockData.bitmap == null && isUnRunning(blockData.task)) {
blockData.task = new LoadBlockTask(blockData.position, blockData, scale, imageWidth, imageHeight, decoder, onImageLoadListener, onLoadStateChangeListener);
blockData.task = new LoadBlockTask(blockData.position, blockData, scale, imageWidth, imageHeight, decoder, options, onImageLoadListener, onLoadStateChangeListener);
exeTask(blockData.task);
}
currentDataMap.put(blockData.position, blockData);
Expand Down Expand Up @@ -641,17 +644,17 @@ static int dip2px(Context context, float dipValue) {
}

int getWidth() {
if (mLoadData == null) {
if (mLoadData == null || mLoadData.options == null) {
return 0;
}
return mLoadData.imageWidth;
return mLoadData.options.outWidth;
}

int getHeight() {
if (mLoadData == null) {
if (mLoadData == null || mLoadData.options == null) {
return 0;
}
return mLoadData.imageHeight;
return mLoadData.options.outHeight;
}

private static class LoadData {
Expand All @@ -678,9 +681,8 @@ private static class LoadData {

private BitmapDecoderFactory mFactory;
private BitmapRegionDecoder mDecoder;
private int imageHeight;
private int imageWidth;
private LoadImageInfoTask task;
private BitmapFactory.Options options;

LoadData(BitmapDecoderFactory factory) {
mFactory = factory;
Expand Down Expand Up @@ -765,8 +767,7 @@ private static class LoadImageInfoTask extends TaskQueue.Task {
private OnLoadStateChangeListener onLoadStateChangeListener;
private OnImageLoadListener onImageLoadListener;
private volatile BitmapRegionDecoder decoder;
private volatile int imageWidth;
private volatile int imageHeight;
private volatile BitmapFactory.Options options;
private volatile Exception e;

LoadImageInfoTask(LoadData loadData, OnImageLoadListener onImageLoadListener, OnLoadStateChangeListener onLoadStateChangeListener) {
Expand All @@ -775,6 +776,13 @@ private static class LoadImageInfoTask extends TaskQueue.Task {
this.onImageLoadListener = onImageLoadListener;
this.onLoadStateChangeListener = onLoadStateChangeListener;
if (DEBUG) {
int imageWidth = 0;
int imageHeight = 0;
if (options != null) {
imageWidth = options.outWidth;
imageHeight = options.outHeight;
}

Log.d(TAG, "start LoadImageInfoTask:imageW:" + imageWidth + " imageH:" + imageHeight);
}
}
Expand All @@ -791,8 +799,7 @@ protected void onPreExecute() {
protected void doInBackground() {
try {
decoder = mFactory.made();
imageWidth = decoder.getWidth();
imageHeight = decoder.getHeight();
options = mFactory.getImageInfo();
if (DEBUG) {
Log.d(TAG, "LoadImageInfoTask doInBackground");
}
Expand All @@ -818,14 +825,20 @@ protected void onCancelled() {
protected void onPostExecute() {
super.onPostExecute();
if (DEBUG) {
int imageWidth = 0;
int imageHeight = 0;
if (options != null) {
imageWidth = options.outWidth;
imageHeight = options.outHeight;
}

Log.d(TAG, "onPostExecute LoadImageInfoTask:" + e + " imageW:" + imageWidth + " imageH:" + imageHeight + " e:" + e);
}
imageInfo.task = null;
if (e == null) {
imageInfo.imageWidth = imageWidth;
imageInfo.imageHeight = imageHeight;
if (e == null && this.options != null) {
imageInfo.options = this.options;
imageInfo.mDecoder = decoder;
onImageLoadListener.onLoadImageSize(imageWidth, imageHeight);
onImageLoadListener.onLoadImageSize(this.options.outWidth, this.options.outHeight);
} else {
onImageLoadListener.onLoadFail(e);
}
Expand All @@ -839,10 +852,11 @@ protected void onPostExecute() {
}
}

private static class LoadBlockTask extends TaskQueue.Task {
private class LoadBlockTask extends TaskQueue.Task {
private int scale;
private BlockData blockData;
private Position position;
private BitmapFactory.Options options;
private int imageWidth;
private int imageHeight;
private BitmapRegionDecoder decoder;
Expand All @@ -852,13 +866,14 @@ private static class LoadBlockTask extends TaskQueue.Task {
private volatile Bitmap bitmap;
private volatile Throwable throwable;

LoadBlockTask(Position position, BlockData blockData, int scale, int imageWidth, int imageHeight, BitmapRegionDecoder decoder, OnImageLoadListener onImageLoadListener, OnLoadStateChangeListener onLoadStateChangeListener) {
LoadBlockTask(Position position, BlockData blockData, int scale, int imageWidth, int imageHeight, BitmapRegionDecoder decoder, BitmapFactory.Options options, OnImageLoadListener onImageLoadListener, OnLoadStateChangeListener onLoadStateChangeListener) {
this.blockData = blockData;
this.scale = scale;
this.position = position;
this.imageWidth = imageWidth;
this.imageHeight = imageHeight;
this.decoder = decoder;
this.options = options;
this.onImageLoadListener = onImageLoadListener;
this.onLoadStateChangeListener = onLoadStateChangeListener;
if (DEBUG) {
Expand Down Expand Up @@ -894,7 +909,12 @@ protected void doInBackground() {
try {
BitmapFactory.Options decodingOptions = new BitmapFactory.Options();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
Bitmap bitmap = acquireBitmap();
Bitmap.Config config = Bitmap.Config.RGB_565;
if (!TextUtils.isEmpty(options.outMimeType) && options.outMimeType.contains(IMAGE_PNG)) {
config = Bitmap.Config.ARGB_8888;
}

Bitmap bitmap = acquireBitmap(config);
decodingOptions.inBitmap = bitmap;
decodingOptions.inMutable = true;
}
Expand Down Expand Up @@ -954,10 +974,10 @@ protected void onPostExecute() {
}
}

private static Bitmap acquireBitmap() {
private Bitmap acquireBitmap(Bitmap.Config config) {
Bitmap bitmap = bitmapPool.acquire();
if (bitmap == null) {
bitmap = Bitmap.createBitmap(BASE_BLOCKSIZE, BASE_BLOCKSIZE, Bitmap.Config.RGB_565);
bitmap = Bitmap.createBitmap(BASE_BLOCKSIZE, BASE_BLOCKSIZE, config);
}
return bitmap;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package com.shizhefei.view.largeimage.factory;

import android.graphics.BitmapFactory;
import android.graphics.BitmapRegionDecoder;

import java.io.IOException;

public interface BitmapDecoderFactory {
BitmapRegionDecoder made() throws IOException;
int[] getImageInfo();
BitmapFactory.Options getImageInfo();
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ public BitmapRegionDecoder made() throws IOException {
}

@Override
public int[] getImageInfo() {
public BitmapFactory.Options getImageInfo() {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path, options);
return new int[]{options.outWidth, options.outHeight};
return options;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@
import java.io.IOException;
import java.io.InputStream;

import static android.R.attr.path;

public class InputStreamBitmapDecoderFactory implements BitmapDecoderFactory {
private InputStream inputStream;

Expand All @@ -23,10 +21,10 @@ public BitmapRegionDecoder made() throws IOException {
}

@Override
public int[] getImageInfo() {
public BitmapFactory.Options getImageInfo() {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(inputStream, new Rect(),options);
return new int[]{options.outWidth, options.outHeight};
return options;
}
}