Android生成縮圖的方法
阿新 • • 發佈:2018-12-28
Android9.0 之前,使用BitmapFactory生成縮圖。
舉例:使用ThumbnailTask生成縮圖,GridViewAdapter顯示縮圖
static class ThumbnailTask extends AsyncTask<Object, LoadedImage, Object> { private String path; private int screenW; private int screenH; private Map<String, Bitmap> thumbnails = new TreeMap<String, Bitmap>(); public ThumbnailTask (String path, int screenW, int screenH) { this.path = path; this.screenW = screenW; this.screenH = screenH; } @Override protected Map<String, Bitmap> 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<String> getImagePath(File file, String path) { //僅儲存字尾為bmp的圖片路徑 ArrayList<String> list = new ArrayList<String>(); 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<LoadedImage> photos = new ArrayList<LoadedImage>(); 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<LoadedImage> photos = new ArrayList<LoadedImage>(); 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<Object, LoadedImage, Object> { 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<String, Bitmap> thumbnails = new TreeMap<String, Bitmap>(); public ThumbnailTask (String path, int screenW, int screenH) { this.path = path; this.screenW = screenW; this.screenH = screenH; } @Override protected Map<String, Bitmap> 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<String> getImagePath(File file, String path) { ArrayList<String> list = new ArrayList<String>(); 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; }