转载自http://www.jb51.net/article/32366.htm
1 package com.testbitmapscale; 2 3 import java.io.File; 4 import java.io.FileInputStream; 5 import java.io.FileOutputStream; 6 import java.io.IOException; 7 import java.io.InputStream; 8 import java.util.Iterator; 9 import com.testbitmapscale.R.drawable; 10 import android.app.Activity; 11 import android.graphics.Bitmap; 12 import android.graphics.Bitmap.Config; 13 import android.graphics.BitmapFactory; 14 import android.graphics.Canvas; 15 import android.graphics.Matrix; 16 import android.graphics.Paint; 17 import android.graphics.PorterDuff.Mode; 18 import android.graphics.PorterDuffXfermode; 19 import android.graphics.Rect; 20 import android.graphics.RectF; 21 import android.graphics.drawable.BitmapDrawable; 22 import android.graphics.drawable.Drawable; 23 import android.media.ThumbnailUtils; 24 import android.os.Bundle; 25 import android.os.Environment; 26 import android.view.View; 27 import android.widget.ImageView; 28 //方法: 29 //1 生成圆角Bitmap图片 30 //2 生成Bitmap缩量图 31 //3 压缩图片场长宽以及kB 32 //注意: 33 //以上代码,测试其中一个方法时最好注释掉其余的代码 34 35 public class MainActivity extends Activity { 36 private ImageView imageView; 37 private Bitmap copyRawBitmap1; 38 private Bitmap copyRawBitmap2; 39 private Bitmap copyRawBitmap3; 40 41 @Override 42 public void onCreate(Bundle savedInstanceState) { 43 super.onCreate(savedInstanceState); 44 setContentView(R.layout.main); 45 imageView = (ImageView) findViewById(R.id.imageView); 46 // 第一种方式:从资源文件中得到图片 47 Bitmap rawBitmap = BitmapFactory.decodeResource(getResources(), 48 R.drawable.haha); 49 copyRawBitmap1 = rawBitmap; 50 copyRawBitmap2 = rawBitmap; 51 copyRawBitmap3 = rawBitmap; 52 // 第二种方式:从SD卡中得到图片(方法1) 53 String SDCarePath = Environment.getExternalStorageDirectory() 54 .toString(); 55 String filePath = SDCarePath + "/" + "haha.jpg"; 56 Bitmap rawBitmap1 = BitmapFactory.decodeFile(filePath, null); 57 // 第二种方式:从SD卡中得到图片(方法2) 58 InputStream inputStream = getBitmapInputStreamFromSDCard("haha.jpg"); 59 Bitmap rawBitmap2 = BitmapFactory.decodeStream(inputStream); 60 61 // ————>以下为将设置图片的圆角 62 Bitmap roundCornerBitmap = this.toRoundCorner(rawBitmap, 40); 63 imageView.setImageBitmap(roundCornerBitmap); 64 // ————>以上为将设置图片的圆角 65 66 // ————>以下为将图片高宽和的大小kB压缩 67 // 得到图片原始的高宽 68 int rawHeight = rawBitmap.getHeight(); 69 int rawWidth = rawBitmap.getWidth(); 70 // 设定图片新的高宽 71 int newHeight = 500; 72 int newWidth = 500; 73 // 计算缩放因子 74 float heightScale = ((float) newHeight) / rawHeight; 75 float widthScale = ((float) newWidth) / rawWidth; 76 // 新建立矩阵 77 Matrix matrix = new Matrix(); 78 matrix.postScale(heightScale, widthScale); 79 // 设置图片的旋转角度 80 // matrix.postRotate(-30); 81 // 设置图片的倾斜 82 // matrix.postSkew(0.1f, 0.1f); 83 // 将图片大小压缩 84 // 压缩后图片的宽和高以及kB大小均会变化 85 Bitmap newBitmap = Bitmap.createBitmap(rawBitmap, 0, 0, rawWidth, 86 rawWidth, matrix, true); 87 // 将Bitmap转换为Drawable 88 Drawable newBitmapDrawable = new BitmapDrawable(newBitmap); 89 imageView.setImageDrawable(newBitmapDrawable); 90 // 然后将Bitmap保存到SDCard中,方便于原图片的比较 91 this.compressAndSaveBitmapToSDCard(newBitmap, "xx100.jpg", 80); 92 // 问题: 93 // 原图大小为625x690 90.2kB 94 // 如果设置图片500x500 压缩后大小为171kB.即压缩后kB反而变大了. 95 // 原因是将:compress(Bitmap.CompressFormat.JPEG, quality, fileOutputStream); 96 // 第二个参数quality设置得有些大了(比如100). 97 // 常用的是80,刚设100太大了造成的. 98 // ————>以上为将图片高宽和的大小kB压缩 99 100 // ————>以下为将图片的kB压缩,宽高不变 101 this.compressAndSaveBitmapToSDCard(copyRawBitmap1, "0011fa.jpg", 80); 102 // ————>以上为将图片的kB压缩,宽高不变 103 104 // ————>以下为获取SD卡图片的缩略图方法1 105 String SDCarePath1 = Environment.getExternalStorageDirectory() 106 .toString(); 107 String filePath1 = SDCarePath1 + "/" + "haha.jpg"; 108 Bitmap bitmapThumbnail1 = this.getBitmapThumbnail(filePath1); 109 imageView.setImageBitmap(bitmapThumbnail1); 110 // ————>以上为获取SD卡图片的缩略图方法1 111 112 // ————>以下为获取SD卡图片的缩略图方法2 113 String SDCarePath2 = Environment.getExternalStorageDirectory() 114 .toString(); 115 String filePath2 = SDCarePath2 + "/" + "haha.jpg"; 116 Bitmap tempBitmap = BitmapFactory.decodeFile(filePath2); 117 Bitmap bitmapThumbnail2 = ThumbnailUtils.extractThumbnail(tempBitmap, 118 100, 100); 119 imageView.setImageBitmap(bitmapThumbnail2); 120 // ————>以上为获取SD卡图片的缩略图方法2 121 122 } 123 124 // 读取SD卡下的图片 125 private InputStream getBitmapInputStreamFromSDCard(String fileName) { 126 if (Environment.getExternalStorageState().equals( 127 Environment.MEDIA_MOUNTED)) { 128 String SDCarePath = Environment.getExternalStorageDirectory() 129 .toString(); 130 String filePath = SDCarePath + File.separator + fileName; 131 File file = new File(filePath); 132 try { 133 FileInputStream fileInputStream = new FileInputStream(file); 134 return fileInputStream; 135 } catch (Exception e) { 136 e.printStackTrace(); 137 } 138 139 } 140 return null; 141 } 142 143 // 获取SDCard的目录路径功能 144 private String getSDCardPath() { 145 String SDCardPath = null; 146 // 判断SDCard是否存在 147 boolean IsSDcardExist = Environment.getExternalStorageState().equals( 148 android.os.Environment.MEDIA_MOUNTED); 149 if (IsSDcardExist) { 150 SDCardPath = Environment.getExternalStorageDirectory().toString(); 151 } 152 return SDCardPath; 153 } 154 155 // 压缩且保存图片到SDCard 156 private void compressAndSaveBitmapToSDCard(Bitmap rawBitmap, 157 String fileName, int quality) { 158 String saveFilePaht = this.getSDCardPath() + File.separator + fileName; 159 File saveFile = new File(saveFilePaht); 160 if (!saveFile.exists()) { 161 try { 162 saveFile.createNewFile(); 163 FileOutputStream fileOutputStream = new FileOutputStream( 164 saveFile); 165 if (fileOutputStream != null) { 166 // imageBitmap.compress(format, quality, stream); 167 // 把位图的压缩信息写入到一个指定的输出流中 168 // 第一个参数format为压缩的格式 169 // 第二个参数quality为图像压缩比的值,0-100.0 意味着小尺寸压缩,100意味着高质量压缩 170 // 第三个参数stream为输出流 171 rawBitmap.compress(Bitmap.CompressFormat.JPEG, quality, 172 fileOutputStream); 173 } 174 fileOutputStream.flush(); 175 fileOutputStream.close(); 176 } catch (IOException e) { 177 e.printStackTrace(); 178 179 } 180 } 181 } 182 183 // 获取图片的缩略图 184 private Bitmap getBitmapThumbnail(String filePath) { 185 BitmapFactory.Options options = new BitmapFactory.Options(); 186 // true那么将不返回实际的bitmap对象,不给其分配内存空间但是可以得到一些解码边界信息即图片大小等信息 187 options.inJustDecodeBounds = true; 188 // 此时rawBitmap为null 189 Bitmap rawBitmap = BitmapFactory.decodeFile(filePath, options); 190 if (rawBitmap == null) { 191 System.out.println("此时rawBitmap为null"); 192 } 193 // inSampleSize表示缩略图大小为原始图片大小的几分之一,若该值为3 194 // 则取出的缩略图的宽和高都是原始图片的1/3,图片大小就为原始大小的1/9 195 // 计算sampleSize 196 int sampleSize = computeSampleSize(options, 150, 200 * 200); 197 // 为了读到图片,必须把options.inJustDecodeBounds设回false 198 options.inJustDecodeBounds = false; 199 options.inSampleSize = sampleSize; 200 // 原图大小为625x690 90.2kB 201 // 测试调用computeSampleSize(options, 100, 200*100); 202 // 得到sampleSize=8 203 // 得到宽和高位79和87 204 // 79*8=632 87*8=696 205 Bitmap thumbnailBitmap = BitmapFactory.decodeFile(filePath, options); 206 // 保存到SD卡方便比较 207 this.compressAndSaveBitmapToSDCard(thumbnailBitmap, "15.jpg", 80); 208 return thumbnailBitmap; 209 } 210 211 // 参考资料: 212 // http://my.csdn.net/zljk000/code/detail/18212 213 // 第一个参数:原本Bitmap的options 214 // 第二个参数:希望生成的缩略图的宽高中的较小的值 215 // 第三个参数:希望生成的缩量图的总像素 216 public static int computeSampleSize(BitmapFactory.Options options, 217 int minSideLength, int maxNumOfPixels) { 218 int initialSize = computeInitialSampleSize(options, minSideLength, 219 maxNumOfPixels); 220 int roundedSize; 221 if (initialSize <= 8) { 222 roundedSize = 1; 223 while (roundedSize < initialSize) { 224 roundedSize <<= 1; 225 } 226 } else { 227 roundedSize = (initialSize + 7) / 8 * 8; 228 } 229 return roundedSize; 230 } 231 232 private static int computeInitialSampleSize(BitmapFactory.Options options, 233 int minSideLength, int maxNumOfPixels) { 234 // 原始图片的宽 235 double w = options.outWidth; 236 // 原始图片的高 237 double h = options.outHeight; 238 System.out.println("========== w=" + w + ",h=" + h); 239 int lowerBound = (maxNumOfPixels == -1) ? 1 : (int) Math.ceil(Math 240 .sqrt(w * h / maxNumOfPixels)); 241 int upperBound = (minSideLength == -1) ? 128 : (int) Math.min( 242 Math.floor(w / minSideLength), Math.floor(h / minSideLength)); 243 if (upperBound < lowerBound) { 244 // return the larger one when there is no overlapping zone. 245 return lowerBound; 246 } 247 if ((maxNumOfPixels == -1) && (minSideLength == -1)) { 248 return 1; 249 } else if (minSideLength == -1) { 250 return lowerBound; 251 } else { 252 return upperBound; 253 } 254 } 255 256 /** 257 * @param bitmap 258 * 需要修改的图片 259 * @param pixels 260 * 圆角的弧度 261 * @return 圆角图片 262 */ 263 // 参考资料: 264 // http://blog.csdn.net/c8822882/article/details/6906768 265 public Bitmap toRoundCorner(Bitmap bitmap, int pixels) { 266 Bitmap roundCornerBitmap = Bitmap.createBitmap(bitmap.getWidth(), 267 bitmap.getHeight(), Config.ARGB_8888); 268 Canvas canvas = new Canvas(roundCornerBitmap); 269 int color = 0xff424242;// int color = 0xff424242; 270 Paint paint = new Paint(); 271 paint.setColor(color); 272 // 防止锯齿 273 paint.setAntiAlias(true); 274 Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()); 275 RectF rectF = new RectF(rect); 276 float roundPx = pixels; 277 // 相当于清屏 278 canvas.drawARGB(0, 0, 0, 0); 279 // 先画了一个带圆角的矩形 280 canvas.drawRoundRect(rectF, roundPx, roundPx, paint); 281 paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN)); 282 // 再把原来的bitmap画到现在的bitmap!!!注意这个理解 283 canvas.drawBitmap(bitmap, rect, rect, paint); 284 return roundCornerBitmap; 285 } 286 287 }