1. 程式人生 > >Android生成縮圖的方法

Android生成縮圖的方法

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;
    }