Android9.0 之前 ,使用BitmapFactory生成缩略图。
举例:使用ThumbnailTask生成缩略图,GridViewAdapter显示缩略图
static class ThumbnailTask extends AsyncTask {
private String path;
private int screenW;
private int screenH;
private Map thumbnails = new TreeMap();
public ThumbnailTask (String path, int screenW, int screenH) {
this.path = path;
this.screenW = screenW;
this.screenH = screenH;
}
@Override
protected Map doInBackground(Object... params) {
Log.d(TAG,"doInBackground");
File file = new File(path);
if (file != null && file.exists()) {
mPhotoPaths = getImagePath(file, path);
if (!mPhotoPaths.isEmpty()) {
int len = mPhotoPaths.size();
Log.d(TAG,"Begin to build thumb.len=" + len);
for(int i = 0; i < len; i++) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
Bitmap bitmap = BitmapFactory.decodeFile(mPhotoPaths.get(i), options);
int outWidth = options.outWidth;
int outHeight = options.outHeight;
Log.i(TAG,"The " + i + " picture resolution:" + outWidth + "*" + outHeight);
if (screenW != outWidth || screenH != outHeight) {
Log.w(TAG, "The " + i + " picture resolution doesn't meet the requirement!");
mPhotoPaths.remove(i);
len--;
i--;
continue;
}
String type = options.outMimeType;
if (TextUtils.isEmpty(type)) {
type = "unknown";
} else {
type = type.substring(6, type.length());
}
mPhotoTypes.put(mPhotoPaths.get(i), type);
options.inJustDecodeBounds = false;
int be = options.outHeight / (screenW * 2/15 - 20);
if (be <= 0) {
be = 10;
}
options.inSampleSize = be;
bitmap = BitmapFactory.decodeFile(mPhotoPaths.get(i), options);
if (bitmap != null) {
int width = bitmap.getWidth();
int height = bitmap.getHeight();
int newWidth = screenW * 2 /15 - 20;
int newHeight = newWidth;
float scaleWidth = ((float)newWidth) / width;
float scaleHeight = ((float)newHeight) / height;
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleHeight);
Bitmap bitmapNew = Bitmap.createBitmap(bitmap, 0, 0, width, height,
matrix, true);
bitmap.recycle();
thumbnails.put(mPhotoPaths.get(i), bitmapNew);
publishProgress(new LoadedImage(bitmapNew));
if (isCancelled()) {
Log.d(TAG,"The Async Task is cancelled");
break;
}
}
}
}
}
return thumbnails;
}
@Override
protected void onProgressUpdate(LoadedImage... value) {
Log.d(TAG,"onProgressUpdate");
addImage(value);
}
@Override
protected void onPostExecute(Object obj) {
Log.d(TAG,"onPostExecute");
Message msgUpdate = mMainHandler.obtainMessage(MSG_UPDATE_UI);
msgUpdate.obj = thumbnails;
mMainHandler.sendMessage(msgUpdate);
}
}
private static class LoadedImage {
private Bitmap bitmap;
LoadedImage(Bitmap bm) {
bitmap = bm;
}
public Bitmap getBitmap() {
return bitmap;
}
}
private static void addImage(LoadedImage... value) { //更新adapter
Log.d(TAG,"addImage");
for (LoadedImage image : value) {
mGridViewAdapter.addPhoto(image);
mGridViewAdapter.notifyDataSetChanged();
}
}
private static ArrayList getImagePath(File file, String path) { //仅保存后缀为bmp的图片路径
ArrayList list = new ArrayList();
File[] files = file.listFiles();
boolean isBitmapExist = false;
if (files != null) {
for (File f: files) {
if (f.getAbsolutePath().indexOf(".bmp") == -1 && f.getAbsolutePath().indexOf(".BMP") == -1) {
continue;
} else {
Log.d(TAG,"There exist bitmap.");
isBitmapExist = true;
list.add(f.getAbsolutePath());
}
}
Collections.sort(list);
}
if (isBitmapExist) {
mExistBmpPath = path;
}
return list;
}
private class GridViewAdapter extends BaseAdapter {
private Context context;
private ArrayList photos = new ArrayList();
public GridViewAdapter(Context ctx) {
context = ctx;
}
@Override
public int getCount() {
return photos.size();
}
@Override
public Object getItem(int position) {
return photos.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {//According to the photos size.
Log.d(TAG,"getView");
final ImageView imageView;
if (convertView == null) {
imageView = new ImageView(context);
} else {
imageView = (ImageView)convertView;
}
imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
imageView.setPadding(8,8,8,8);
imageView.setImageBitmap(photos.get(position).getBitmap());
return imageView;
}
public void addPhoto(LoadedImage photo) {
photos.add(photo);
}
public void clearPhoto() {
photos.clear();
}
}
Android Pie(Android 9.0)中引入了新类ImageDecoder ,可利用该类进行解码。
官方文档:https://developer.android.google.cn/reference/android/graphics/ImageDecoder
该类的优点:Android P的APP适配总结,让你快人一步
private class GridViewAdapter extends BaseAdapter {
private Context context;
private ArrayList photos = new ArrayList();
public GridViewAdapter(Context ctx) {
context = ctx;
}
@Override
public int getCount() {
return photos.size();
}
@Override
public Object getItem(int position) {
return photos.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {//According to the photos size.
Log.d(TAG,"getView");
final ImageView imageView;
if (convertView == null) {
imageView = new ImageView(context);
} else {
imageView = (ImageView)convertView;
}
imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
imageView.setPadding(8,8,8,8);
imageView.setImageBitmap(photos.get(position).getBitmap());
return imageView;
}
public void addPhoto(LoadedImage photo) {
photos.add(photo);
}
public void clearPhoto() {
photos.clear();
}
}
static class ThumbnailTask extends AsyncTask {
private String path;
private int screenW;
private int screenH;
//=========
private int bmpOrigW;//The width of encoded image
private int bmpOrigH; //The height of encoded image
private String bmpOrigType;
private OnHeaderDecodedListener listener = new OnHeaderDecodedListener() {
@Override
public void onHeaderDecoded(@NonNull ImageDecoder decoder,
@NonNull ImageInfo info, @NonNull Source source) {
bmpOrigW = info.getSize().getWidth();//获取原图的width
bmpOrigH = info.getSize().getHeight();//获取原图的height
bmpOrigType = info.getMimeType();//获取原图的mime type
decoder.setTargetSampleSize(bmpOrigW/(screenW * 2/15 - 20));//设置采样率
}
};
//=========
private Map thumbnails = new TreeMap();
public ThumbnailTask (String path, int screenW, int screenH) {
this.path = path;
this.screenW = screenW;
this.screenH = screenH;
}
@Override
protected Map doInBackground(Object... params) {
Log.d(TAG,"doInBackground");
File file = new File(path);
if (file != null && file.exists()) {
mPhotoPaths = getImagePath(file, path);
if (!mPhotoPaths.isEmpty()) {
int len = mPhotoPaths.size();
Log.d(TAG,"Begin to build thumb.len=" + len);
for(int i = 0; i < len; i++) {
ImageDecoder.Source source = ImageDecoder.createSource(new File(mPhotoPaths.get(i)));
Bitmap bitmap = null;
try {
bitmap = ImageDecoder.decodeBitmap(source, listener);
} catch (IOException e) {
e.printStackTrace();
}
Log.i(TAG,"The " + i + " picture resolution:" + bmpOrigW + "*" + bmpOrigH);
if (screenW != bmpOrigW || screenH != bmpOrigH) {
Log.w(TAG, "The " + i + " picture resolution doesn't meet the requirement!");
mPhotoPaths.remove(i);
len--;
i--;
continue;
}
if (TextUtils.isEmpty(bmpOrigType)) {
bmpOrigType = "unknown";
} else {
bmpOrigType = bmpOrigType.substring(6, bmpOrigType.length());
}
mPhotoTypes.put(mPhotoPaths.get(i), bmpOrigType);
if (bitmap != null) {
int width = bitmap.getWidth();
int height = bitmap.getHeight();
int newWidth = screenW * 2 /15 - 20;
int newHeight = newWidth;
float scaleWidth = ((float)newWidth) / width;
float scaleHeight = ((float)newHeight) / height;
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleHeight);
Bitmap bitmapNew = Bitmap.createBitmap(bitmap, 0, 0, width, height,
matrix, true);
bitmap.recycle();
thumbnails.put(mPhotoPaths.get(i), bitmapNew);
publishProgress(new LoadedImage(bitmapNew));
if (isCancelled()) {
Log.d(TAG,"The Async Task is cancelled");
break;
}
}
}
}
}
return thumbnails;
}
@Override
protected void onProgressUpdate(LoadedImage... value) {
Log.d(TAG,"onProgressUpdate");
addImage(value);
}
@Override
protected void onPostExecute(Object obj) {
Log.d(TAG,"onPostExecute");
Message msgUpdate = mMainHandler.obtainMessage(MSG_UPDATE_UI);
msgUpdate.obj = thumbnails;
mMainHandler.sendMessage(msgUpdate);
}
}
private static class LoadedImage {
private Bitmap bitmap;
LoadedImage(Bitmap bm) {
bitmap = bm;
}
public Bitmap getBitmap() {
return bitmap;
}
}
private static void addImage(LoadedImage... value) {
Log.d(TAG,"addImage");
for (LoadedImage image : value) {
mGridViewAdapter.addPhoto(image);
mGridViewAdapter.notifyDataSetChanged();
}
}
private static ArrayList getImagePath(File file, String path) {
ArrayList list = new ArrayList();
File[] files = file.listFiles();
boolean isBitmapExist = false;
if (files != null) {
for (File f: files) {
if (f.getAbsolutePath().indexOf(".bmp") == -1 && f.getAbsolutePath().indexOf(".BMP") == -1) {
continue;
} else {
Log.d(TAG,"There exist bitmap.");
isBitmapExist = true;
list.add(f.getAbsolutePath());
}
}
Collections.sort(list);
}
if (isBitmapExist) {
mExistBmpPath = path;
}
return list;
}