码迷,mamicode.com
首页 > 其他好文 > 详细

图片的压缩(二次采样)

时间:2015-11-06 22:26:30      阅读:378      评论:0      收藏:0      [点我收藏+]

标签:

技术分享
  1 package com.qianfeng.bitmapdisplay.tasks;
  2 
  3 import android.graphics.Bitmap;
  4 import android.graphics.BitmapFactory;
  5 import android.graphics.drawable.Drawable;
  6 import android.os.AsyncTask;
  7 import android.widget.ImageView;
  8 import com.qianfeng.bitmapdisplay.cache.FileCache;
  9 import com.qianfeng.bitmapdisplay.utils.HttpTools;
 10 
 11 import java.lang.ref.WeakReference;
 12 
 13 /**
 14  * Created
 15  * Author: vhly[FR]
 16  * Email: vhly@163.com
 17  * Date: 2015/10/12
 18  */
 19 public class ImageLoadTask extends AsyncTask<String, Integer, Bitmap> {
 20 
 21     /**
 22      * 使用弱引用来进行ImageView对象的引用,当UI销毁,任务不再使用ImageView
 23      */
 24     private final WeakReference<ImageView> imageViewReference;
 25 
 26     /**
 27      * 加载的图片,最终显示的宽度
 28      */
 29     private int requestWidth;
 30 
 31     private int requestHeight;
 32 
 33     /**
 34      * 异步任务的构造
 35      *
 36      * @param imageView ImageView 需要显示的ImageView
 37      * @param reqWidth  请求的宽度 0 代表显示原始图像,> 0 将图像缩小
 38      * @param reqHeight 请求的高度 0 代表显示原始图像,> 0 将图像缩小
 39      */
 40     public ImageLoadTask(ImageView imageView, int reqWidth, int reqHeight) {
 41         imageViewReference = new WeakReference<ImageView>(imageView);
 42 
 43         requestWidth = reqWidth;
 44 
 45         requestHeight = reqHeight;
 46     }
 47 
 48     @Override
 49     protected Bitmap doInBackground(String... params) {
 50         Bitmap ret = null;
 51 
 52         if (params != null && params.length > 0) {
 53 
 54             String url = params[0];
 55 
 56             // 获取 url 对应的文件缓存
 57             byte[] data = FileCache.getInstance().load(url);
 58 
 59             if (data != null) {
 60                 // TODO 有文件数据,那么不需要联网
 61             } else {
 62                 // TODO 联网下载图片
 63                 data = HttpTools.doGet(url);
 64                 FileCache.getInstance().save(url, data);
 65             }
 66 
 67             if (data != null) {
 68 
 69 
 70                 // 按照原始的图片尺寸,进行Bitmap的生成,
 71                 // 按照Bitmap生成,是按照 图片原始宽高,进行生成,并且每一个像素占用四个字节 也就是 ARGB
 72                 // ret = BitmapFactory.decodeByteArray(data, 0, data.length);
 73 
 74 
 75                 // 采用二次采样(缩小图片尺寸的方式)
 76 
 77                 // 1. 步骤1 获取原始图片的宽高信息,用于进行采样的计算
 78 
 79                 // 1.1 创建 Options ,给BitmapFactory 的内部解码器传递参数
 80                 BitmapFactory.Options options = new BitmapFactory.Options();
 81 
 82                 // 1.2 设置 inJustDecodeBounds 来控制解码器,只进行图片宽高的获取,不会加载 Bitmap
 83                 //     不占用内存,当使用这个参数,代表 BitmapFactory.decodeXxxx 类似的方法,不会返回 Bitmap
 84                 options.inJustDecodeBounds = true;
 85 
 86                 // 解码,使用 Options 参数设置 解码方式
 87                 BitmapFactory.decodeByteArray(data, 0, data.length, options);
 88 
 89                 //------------------------------------------
 90 
 91                 // 2. 步骤2 根据图片的真实尺寸,与当前需要显示的尺寸,进行计算,生成图片采样率。
 92 
 93                 // 2.1
 94 
 95                 int picW = options.outWidth;   // 6000
 96                 int picH = options.outHeight;  // 4000
 97 
 98                 // 2.2 准备 显示在 手机上的尺寸。 256x128   128x64
 99                 //     尺寸是根据程序需要来设置的。
100 
101                 // maxWidth, maxHeight
102                 int reqW = requestWidth;
103 
104                 int reqH = requestHeight;  // 测试数据
105 
106                 // 2.3 计算、设置 图片采样率
107 
108                 options.inSampleSize =
109                         calculateInSampleSize(options, reqW, reqH);  // 宽度的 1/32  高度的 1/32
110 
111                 // 2.4 开放 解码,实际生成Bitmap
112                 options.inJustDecodeBounds = false;
113 
114                 // 2.4.1 Bitmap.Config 的说明
115                 // 要求解码器对于每一个采样的像素,使用 RGB_565 存储方式
116                 // 一个像素,占用两个 字节;比 ARGB_8888 小了一半。
117                 // 如果解码器不能够使用指定配置,就自动使用 ARGB_8888
118                 options.inPreferredConfig = Bitmap.Config.RGB_565;
119 
120                 // 2.4.2 是一个过时的设置
121                 options.inPurgeable = true;
122 
123                 // 2.5 使用设置采样的参数,来进行 解码,获取 Bitmap
124                 ret = BitmapFactory.decodeByteArray(data, 0, data.length, options);
125 
126                 // data 需要显示释放
127                 data = null;
128 
129             }
130         }
131 
132         return ret;
133     }
134 
135     @Override
136     protected void onPostExecute(Bitmap bitmap) {
137         if (bitmap != null) {
138 
139             // 获取弱引用包含的对象,可能为null
140             ImageView imageView = imageViewReference.get();
141 
142             if (imageView != null) {
143                 // 每一个图片都可以包含 AsyncDrawable对象
144                 // 这个对象用于处理图片错位的
145                 Drawable drawable = imageView.getDrawable();
146 
147                 if (drawable != null && drawable instanceof AsyncDrawable) {
148                     // 用于检测图片错位
149 
150                     AsyncDrawable asyncDrawable = (AsyncDrawable) drawable;
151 
152                     ImageLoadTask task = asyncDrawable.getImageLoadTask();
153 
154                     // 当前ImageView 内部包含的 AsyncDrawable和当前
155                     // 任务是对应的,代表 当前任务可以设置图片
156                     if (this == task) {
157                         imageView.setImageBitmap(bitmap);
158                     }
159 
160                 } else { // 不用检测 图片错位的情况
161                     imageView.setImageBitmap(bitmap);
162                 }
163             }
164 
165         }
166     }
167 
168     /**
169      * 计算图片二次采样的采样率,使用获取图片宽高之后的 Options 作为第一个参数;
170      * 并且,通过请求的 宽度、高度尺寸,进行采样率的计算;
171      *
172      * @param options
173      * @param reqWidth  请求的宽度
174      * @param reqHeight 请求的高度
175      * @return int 采样率
176      */
177     public static int calculateInSampleSize(
178             BitmapFactory.Options options, int reqWidth, int reqHeight) {
179         // Raw height and width of image
180         final int height = options.outHeight;
181         final int width = options.outWidth;
182         int inSampleSize = 1;
183 
184         // 当请求的宽度、高度 > 0 时候,进行缩放,
185         // 否则,图片不进行缩放;
186         if (reqWidth > 0 && reqHeight > 0) {
187             if (height > reqHeight || width > reqWidth) {
188 
189                 final int halfHeight = height / 2;
190                 final int halfWidth = width / 2;
191 
192                 // Calculate the largest inSampleSize value that is a power of 2 and keeps both
193                 // height and width larger than the requested height and width.
194                 while ((halfHeight / inSampleSize) >= reqHeight
195                         && (halfWidth / inSampleSize) >= reqWidth) {
196                     inSampleSize *= 2;
197                 }
198             }
199         }
200 
201         return inSampleSize;
202     }
203 
204 }
View Code

上面的是  比较正规具体的压缩方式  decodeByteArray

 

下边的是比较快捷的方式   decodeFile

private void resizePhoto() {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;

BitmapFactory.decodeFile(mcurrentPhotoPath, options);

double ratio = Math.max(options.outWidth*1.0d/1024 , options.outHeight*1.0d/1024);

options.inSampleSize = (int)Math.ceil(ratio);

options.inJustDecodeBounds = false;

mphotoImage = BitmapFactory.decodeFile(mcurrentPhotoPath, options);
}

图片的压缩(二次采样)

标签:

原文地址:http://www.cnblogs.com/bimingcong/p/4943659.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!