Android Bitmap 全面解析(一)加载大尺寸图片
http://www.eoeandroid.com/thread-331669-1-1.html
Android Bitmap 全面解析(二)加载多张图片的缓存处理
http://www.eoeandroid.com/thread-332399-1-1.html
Android Bitmap 全面解析(三)开源图片框架分析1-UIL(上)
http://www.eoeandroid.com/thread-333220-1-1.html
Android Bitmap 全面解析(三)开源图片框架分析1-UIL(下)
http://www.eoeandroid.com/thread-333229-1-1.html
Android Bitmap 全面解析(二)加载多张图片的缓存处理
http://www.eoeandroid.com/thread-332399-1-1.html
Android Bitmap 全面解析(三)开源图片框架分析1-UIL(上)
http://www.eoeandroid.com/thread-333220-1-1.html
Android Bitmap 全面解析(三)开源图片框架分析1-UIL(下)
http://www.eoeandroid.com/thread-333229-1-1.html
Android Bitmap 全面解析(三)开源图片框架分析2-ImageLoader和Volley
Android Bitmap 全面解析(四)图片处理效果对比
1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 xmlns:tools="http://schemas.android.com/tools" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:orientation="vertical" 6 tools:context=".MainActivity" > 7 8 <LinearLayout 9 android:layout_width="fill_parent" 10 android:layout_height="wrap_content" 11 android:orientation="horizontal" > 12 <ImageView 13 android:id="@+id/iv1" 14 android:layout_width="150dp" 15 android:layout_height="150dp" /> 16 <ImageView 17 android:id="@+id/iv2" 18 android:layout_width="150dp" 19 android:layout_height="150dp" 20 android:layout_marginLeft="20dp" 21 android:scaleType="centerCrop" /> 22 </LinearLayout> 23 24 <LinearLayout 25 android:layout_marginTop="50dp" 26 android:layout_width="fill_parent" 27 android:layout_height="wrap_content" 28 android:orientation="horizontal" > 29 <ImageView 30 android:id="@+id/iv3" 31 android:layout_width="150dp" 32 android:layout_height="150dp" /> 33 <ImageView 34 android:id="@+id/iv4" 35 android:layout_width="150dp" 36 android:layout_height="150dp" 37 android:layout_marginLeft="20dp" 38 android:scaleType="centerCrop" /> 39 </LinearLayout> 40 41 </LinearLayout>
1 package com.example.bdimagescale; 2 3 import android.app.Activity; 4 import android.content.res.Resources; 5 import android.graphics.Bitmap; 6 import android.graphics.BitmapFactory; 7 import android.os.Bundle; 8 import android.view.Menu; 9 import android.widget.ImageView; 10 11 public class MainActivity extends Activity { 12 13 private static final int FIT_INSIDE = 1; 14 private static final int CROP = 2; 15 16 private ImageView iv1;// 默认缩放类型,即FIT_INSIDE 17 private ImageView iv2;// centerCrop缩放类型,即CROP 18 private ImageView iv3;// 默认缩放类型,即FIT_INSIDE 19 private ImageView iv4;// centerCrop缩放类型,即CROP 20 21 @Override 22 protected void onCreate(Bundle savedInstanceState) { 23 super.onCreate(savedInstanceState); 24 setContentView(R.layout.activity_main); 25 26 // // 10000以内随机宽高 27 // for(int i=0; i<20; i++) { 28 // int width = (int)(Math.random()*9000+1000); 29 // int height = (int)(Math.random()*9000+1000); 30 // test(width, height, 400, 200, 200, 200); 31 // // compareInSampleSize(width, height, 400, 200); 32 // } 33 34 iv1 = (ImageView) findViewById(R.id.iv1); 35 iv2 = (ImageView) findViewById(R.id.iv2); 36 iv3 = (ImageView) findViewById(R.id.iv3); 37 iv4 = (ImageView) findViewById(R.id.iv4); 38 testLongImage(); 39 // testNormalImage(); 40 } 41 42 @Override 43 public boolean onCreateOptionsMenu(Menu menu) { 44 // Inflate the menu; this adds items to the action bar if it is present. 45 getMenuInflater().inflate(R.menu.main, menu); 46 return true; 47 } 48 49 // 数据对比 50 public void test(int width, int height, int limitWidth,
int limitHeight,int viewWidth, int viewHeight) { 52 System.out.println("原图宽高=" + width + ":" + height); 53 System.out.println("限定宽高=" + limitWidth + ":" + limitHeight); 54 System.out.println("控件大小=" + viewWidth + ":" + viewHeight); 55 float densityOfINSIDE0 = calculateImagePxDensityOfINSIDE(
limitWidth,limitHeight, viewWidth, viewHeight); 57 System.out.println("默认即INDESE情况下目标像素密度为="
+ densityOfINSIDE0); 58 float densityOfCROP0 = calculateImagePxDensityOfCROP(limitWidth, 59 limitHeight, viewWidth, viewHeight); 60 System.out.println("CROP情况下目标像素密度为=" + densityOfCROP0); 61 System.out.println("---------------------"); 62 63 int inSampleSize1 = calculateInSampleSize(
width, height, limitWidth,limitHeight); 65 int imageWidth = width / inSampleSize1; 66 int imageHeight = height / inSampleSize1; 67 System.out.println("官方:对应缩放后图片大小="
+ imageWidth + ":" + imageHeight); 68 float densityOfINSIDE = calculateImagePxDensityOfINSIDE(
imageWidth,imageHeight, viewWidth, viewHeight); 70 System.out.println("默认即INDESE情况下像素密度为="
+ densityOfINSIDE); 71 float densityOfCROP = calculateImagePxDensityOfCROP(imageWidth, 72 imageHeight, viewWidth, viewHeight); 73 System.out.println("CROP情况下像素密度为=" + densityOfCROP); 74 System.out.println("---------------------"); 75 76 int reWidth = getResizedDimension(limitWidth, limitHeight,
width,height); 78 int reHeight = getResizedDimension(limitHeight, limitWidth,
height,width); 80 // System.out.println("处理后限定宽高="+reWidth+":"+reHeight); 81 int inSampleSize2 = findBestSampleSize(width, height, reWidth,
reHeight); 82 int imageWidth2 = width / inSampleSize2; 83 int imageHeight2 = height / inSampleSize2; 84 System.out.println("Volley:对应缩放后图片大小=" + imageWidth2 + ":" 85 + imageHeight2); 86 float densityOfINSIDE2 = calculateImagePxDensityOfINSIDE(
imageWidth2,imageHeight2, viewWidth, viewHeight); 88 System.out.println("默认即INDESE情况下像素密度为="
+ densityOfINSIDE2); 89 float densityOfCROP2 = calculateImagePxDensityOfCROP(imageWidth2, 90 imageHeight2, viewWidth, viewHeight); 91 System.out.println("CROP情况下像素密度为=" + densityOfCROP2); 92 System.out.println("---------------------"); 93 94 int inSampleSize3OfINSIDE = computeImageSampleSize(width, height, 95 limitWidth, limitHeight, FIT_INSIDE, true); 96 int imageWidthOfINSIDE = width / inSampleSize3OfINSIDE; 97 int imageHeightOfINSIDE = height / inSampleSize3OfINSIDE; 98 System.out.println("UIL FIT_INSIDE:对应缩放后图片大小=" + imageWidthOfINSIDE 99 + ":" + imageHeightOfINSIDE); 100 float densityOfINSIDE3 = calculateImagePxDensityOfINSIDE( 101 imageWidthOfINSIDE, imageHeightOfINSIDE, viewWidth, viewHeight); 102 System.out.println("默认即INDESE情况下像素密度为=" + densityOfINSIDE3); 103 int inSampleSize3OfCROP = computeImageSampleSize(width, height, 104 limitWidth, limitHeight, CROP, true); 105 int imageWidthOfCROP = width / inSampleSize3OfCROP; 106 int imageHeightOfCROP = height / inSampleSize3OfCROP; 107 System.out.println("UIL CROP:对应缩放后图片大小=" + imageWidthOfCROP + ":" 108 + imageHeightOfCROP); 109 float densityOfCROP3 = calculateImagePxDensityOfCROP(imageWidthOfCROP, 110 imageHeightOfCROP, viewWidth, viewHeight); 111 System.out.println("CROP情况下像素密度为=" + densityOfCROP3); 112 System.out.println("---------------------"); 113 114 System.out.println(); 115 } 116 117 // inSampleSize对比 118 public void compareInSampleSize(int imageWidth, int imageHeight, 119 int reqWidth, int reqHeight) { 120 System.out.println("原图片 " + imageWidth + ":" + imageHeight); 121 System.out.print("官方 " 122 + calculateInSampleSize(imageWidth, imageHeight, reqWidth, 123 reqHeight)); 124 System.out.print(" ... "); 125 System.out.print("UIL " 126 + computeImageSampleSize(imageWidth, imageHeight, reqWidth, 127 reqHeight, CROP, true)); 128 System.out.print(" ... "); 129 System.out.print("Volley " 130 + findBestSampleSize(imageWidth, imageHeight, reqWidth, 131 reqHeight)); 132 System.out.println(); 133 System.out.println(); 134 } 135 136 public void testLongImage() { 137 Bitmap vbitmap = decodeByVolley(getResources(), R.drawable.longimage, 138 300, 300); 139 // UIL框架中会自行判断处理viewScaleType,这里为了简单临时手写了 140 Bitmap ubitmap_inside = decodeByUIL(getResources(), 141 R.drawable.longimage, 300, 300, FIT_INSIDE); 142 Bitmap ubitmap_crop = decodeByUIL(getResources(), R.drawable.longimage, 143 300, 300, CROP); 144 145 iv1.setImageBitmap(vbitmap); 146 iv2.setImageBitmap(vbitmap); 147 148 iv3.setImageBitmap(ubitmap_inside); 149 iv4.setImageBitmap(ubitmap_crop); 150 } 151 152 public void testNormalImage() { 153 Bitmap vbitmap = decodeByVolley(getResources(), R.drawable.normalimage, 154 300, 300); 155 // UIL框架中会自行判断处理viewScaleType,这里为了简单临时手写了 156 Bitmap ubitmap_inside = decodeByUIL(getResources(), 157 R.drawable.normalimage, 300, 300, FIT_INSIDE); 158 Bitmap ubitmap_crop = decodeByUIL(getResources(), 159 R.drawable.normalimage, 300, 300, CROP); 160 161 iv1.setImageBitmap(vbitmap); 162 iv2.setImageBitmap(vbitmap); 163 164 iv3.setImageBitmap(ubitmap_inside); 165 iv4.setImageBitmap(ubitmap_crop); 166 } 167 168 public Bitmap decodeByVolley(Resources res, int resId, int limitWidth, 169 int limitHeight) { 170 171 // 首先不加载图片,仅获取图片尺寸 172 final BitmapFactory.Options options = new BitmapFactory.Options(); 173 // 当inJustDecodeBounds设为true时,不会加载图片仅获取图片尺寸信息 174 options.inJustDecodeBounds = true; 175 // 此时仅会将图片信息会保存至options对象内,decode方法不会返回bitmap对象 176 BitmapFactory.decodeResource(res, resId, options); 177 178 int reWidth = getResizedDimension(limitWidth, limitHeight, 179 options.outWidth, options.outHeight); 180 int reHeight = getResizedDimension(limitHeight, limitWidth, 181 options.outHeight, options.outWidth); 182 183 // 计算压缩比例,如inSampleSize=4时,图片会压缩成原图的1/4 184 options.inSampleSize = findBestSampleSize(options.outWidth, 185 options.outHeight, reWidth, reHeight); 186 187 // 当inJustDecodeBounds设为false时,BitmapFactory.decode...就会返回图片对象了 188 options.inJustDecodeBounds = false; 189 // 利用计算的比例值获取压缩后的图片对象 190 return BitmapFactory.decodeResource(res, resId, options); 191 } 192 193 public Bitmap decodeByUIL(Resources res, int resId, int limitWidth, 194 int limitHeight, int scaleType) { 195 196 // 首先不加载图片,仅获取图片尺寸 197 final BitmapFactory.Options options = new BitmapFactory.Options(); 198 // 当inJustDecodeBounds设为true时,不会加载图片仅获取图片尺寸信息 199 options.inJustDecodeBounds = true; 200 // 此时仅会将图片信息会保存至options对象内,decode方法不会返回bitmap对象 201 BitmapFactory.decodeResource(res, resId, options); 202 203 // 计算压缩比例,如inSampleSize=4时,图片会压缩成原图的1/4 204 options.inSampleSize = computeImageSampleSize(options.outWidth, 205 options.outWidth, limitWidth, limitHeight, scaleType, true); 206 207 // 当inJustDecodeBounds设为false时,BitmapFactory.decode...就会返回图片对象了 208 options.inJustDecodeBounds = false; 209 // 利用计算的比例值获取压缩后的图片对象 210 return BitmapFactory.decodeResource(res, resId, options); 211 } 212 213 // 计算FIT_INSIDE时像素密度 214 static float calculateImagePxDensityOfINSIDE(int imageWidth, 215 int imageHeight, int viewWidth, int viewHeight) { 216 float density = -1; 217 if (imageWidth >= imageHeight) { 218 density = (float) imageWidth / (float) viewWidth; 219 } else { 220 density = (float) imageHeight / (float) viewHeight; 221 } 222 return density * density; 223 } 224 225 // 计算CROP时像素密度 226 static float calculateImagePxDensityOfCROP(int imageWidth, int imageHeight, 227 int viewWidth, int viewHeight) { 228 float density = -1; 229 if (imageWidth >= imageHeight) { 230 density = (float) imageHeight / (float) viewHeight; 231 } else { 232 density = (float) imageWidth / (float) viewWidth; 233 } 234 return density * density; 235 } 236 237 // ////////////////// 官方 //////////////////////////////// 238 int calculateInSampleSize(int width, int height, int reqWidth, int reqHeight) { 239 // 初始化压缩比例为1 240 int inSampleSize = 1; 241 242 // 当图片宽高值任何一个大于所需压缩图片宽高值时,进入循环计算系统 243 if (height > reqHeight || width > reqWidth) { 244 245 final int halfHeight = height / 2; 246 final int halfWidth = width / 2; 247 248 // 压缩比例值每次循环两倍增加, 249 // 直到原图宽高值的一半除以压缩值后都~大于所需宽高值为止(将>改成了>=) 250 while ((halfHeight / inSampleSize) >= reqHeight 251 && (halfWidth / inSampleSize) >= reqWidth) { 252 inSampleSize *= 2; 253 } 254 } 255 return inSampleSize; 256 } 257 258 // ////////////////// UIL //////////////////////////////// 259 int computeImageSampleSize(int width, int height, int limitWidth, 260 int limitHeight, int viewScaleType, boolean powerOf2Scale) { 261 262 int scale = 1; 263 264 int widthScale = width / limitWidth; 265 int heightScale = height / limitHeight; 266 267 switch (viewScaleType) { 268 case FIT_INSIDE: 269 if (powerOf2Scale) { 270 while (width / 2 >= limitWidth || height / 2 >= limitHeight) { // || 271 width /= 2; 272 height /= 2; 273 scale *= 2; 274 } 275 } else { 276 scale = Math.max(widthScale, heightScale); // max 277 } 278 break; 279 case CROP: 280 if (powerOf2Scale) { 281 while (width / 2 >= limitWidth && height / 2 >= limitHeight) { // && 282 width /= 2; 283 height /= 2; 284 scale *= 2; 285 } 286 } else { 287 scale = Math.min(widthScale, heightScale); // min 288 } 289 break; 290 } 291 292 if (scale < 1) { 293 scale = 1; 294 } 295 296 return scale; 297 } 298 299 // ////////////////// Volley //////////////////////////////// 300 int findBestSampleSize(int actualWidth, int actualHeight, int desiredWidth, 301 int desiredHeight) { 302 double wr = (double) actualWidth / desiredWidth; 303 double hr = (double) actualHeight / desiredHeight; 304 double ratio = Math.min(wr, hr); 305 float n = 1.0f; 306 while ((n * 2) <= ratio) { 307 n *= 2; 308 } 309 310 return (int) n; 311 } 312 313 int getResizedDimension(int maxPrimary, int maxSecondary, 314 int actualPrimary, int actualSecondary) { 315 // If no dominant value at all, just return the actual. 316 if (maxPrimary == 0 && maxSecondary == 0) { 317 return actualPrimary; 318 } 319 320 // If primary is unspecified, scale primary to match secondary's scaling 321 // ratio. 322 if (maxPrimary == 0) { 323 double ratio = (double) maxSecondary / (double) actualSecondary; 324 return (int) (actualPrimary * ratio); 325 } 326 327 if (maxSecondary == 0) { 328 return maxPrimary; 329 } 330 331 double ratio = (double) actualSecondary / (double) actualPrimary; 332 int resized = maxPrimary; 333 if (resized * ratio > maxSecondary) { 334 resized = (int) (maxSecondary / ratio); 335 } 336 return resized; 337 } 338 339 }