通过采样率压缩图片的步骤:
- 将BitmapFactory.Options的inJustDecodeBounds参数设置为true并加载图片
- 从BitmapFactory.Options中取出图片的原始宽和高 ,分别对应outWidth和outHeight
- 根据采样率的就着并结合目标View的所需大小计算出采样率inSampleSize
- 将BitmapFactory.Options的inJustDecodeBounds参数设置为false,然后重新加载图片
BTW: 说一下BitmapFactory.Options的inJustDecodeBounds属性,当参数设置为true时,BitmapFactory只会解析图片的原始宽和高,并不会将图片加载到内存中。
// 如果图片不存在 则添加到任务队列中 addTask(new Runnable() { @Override public void run() { // 加载图片 TODO // 1.获取图片需要显示的宽和搞 ImageSize imageSize = getImageViewSize(imageView); // 利用Options压缩图片 Bitmap bm = decodeSampledBitmapFromPath(path, imageSize.width, imageSize.height); // 添加到LruCache中 addBitmapToLruCache(path, bm); // 发送消息,通知UIHandler更新图片 ImageBeanHoler holder = new ImageBeanHoler(); holder.bitmap = getBitmapFromLruCache(path); holder.imageView = imageView; holder.path = path; Message message = Message.obtain(); message.obj = holder; mUIHandler.sendMessage(message); // 执行完之后,释放一个信号量,通知mPoolThread可以从任务队列中获取下一个任务了去执行了。 mPoolThreadSemaphore.release(); } });
/** * 根据计算的inSampleSize得到压缩的图片 * * @param path * @param reqWidth * @param reqHeight * @return */ private Bitmap decodeSampledBitmapFromPath(String path, int reqWidth, int reqHeight) { // 第一次解析将inJustDecodeBounds设置为true,不将图片加载到内存,获取图片的大小 BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeFile(path, options); // 计算inSampleSize options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); // 使用获取到的inSampleSize再此获取图片,加载到内存中 options.inJustDecodeBounds = false; Bitmap bitmap = BitmapFactory.decodeFile(path, options); return bitmap; }
/** * 这个方法用户可以自己设置适合项目的图片比例 * * @param options * @param reqWidth * @param reqHeight * @return */ private int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) { // 源图片的宽度 int width = options.outWidth; int height = options.outHeight; int inSampleSize = 1; if (width > reqWidth && height > reqHeight) // ||也是可以的,看实际情况 { // 计算出实际宽度和目标宽度的比率 int widthRatio = Math.round((float) width / (float) reqWidth); int heightRatio = Math.round((float) width / (float) reqWidth); inSampleSize = Math.max(widthRatio, heightRatio); // 为了节省内存,取了大值。如果有变形,取小值试试。 } return inSampleSize; }