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: [email protected] 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 }
上面的是 比较正规具体的压缩方式 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);
}
时间: 2024-10-05 12:33:44