Android图片压缩非两种,一种质量压缩,一种像素压缩,前者多用于图片上传时,后者多用于本地图片展示缩略图时。总结并记录一下,方便以后使用。
具体的分析可以参考这篇文章,http://www.codeceo.com/article/android-image-compression.html
/** * Image compress factory class */ public class ImageUtils { /** * Get bitmap from specified image path * * @param imgPath image path * @return Bitmap */ public Bitmap getBitmap(String imgPath) { // Get bitmap through image path BitmapFactory.Options newOpts = new BitmapFactory.Options(); newOpts.inJustDecodeBounds = false; // Do not compress newOpts.inSampleSize = 1; newOpts.inPreferredConfig = Config.RGB_565; return BitmapFactory.decodeFile(imgPath, newOpts); } /** * Store bitmap into specified image path * * @param bitmap * @param outPath * @throws FileNotFoundException */ public static void storeImage(Bitmap bitmap, String outPath) throws FileNotFoundException { FileOutputStream os = new FileOutputStream(outPath); bitmap.compress(Bitmap.CompressFormat.JPEG, 100, os); } /** * Compress image by pixel, this will modify image width/height. * Used to get thumbnail * * @param imgPath image path * @param pixelW target pixel of width * @param pixelH target pixel of height * @return */ public Bitmap ratio(String imgPath, float pixelW, float pixelH) { BitmapFactory.Options newOpts = new BitmapFactory.Options(); // 开始读入图片,此时把options.inJustDecodeBounds 设回true,即只读边不读内容 newOpts.inJustDecodeBounds = true; newOpts.inPreferredConfig = Config.RGB_565; // Get bitmap info, but notice that bitmap is null now BitmapFactory.decodeFile(imgPath, newOpts); int originalWidth = newOpts.outWidth; int originalHeight = newOpts.outHeight; // 想要缩放的目标尺寸 float convertedWidth = pixelW;// 设置宽度为120f,可以明显看到图片缩小了 float convertedHeight = pixelH;// 设置高度为240f时,可以明显看到图片缩小了 // 缩放比。由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可 int ratio = 1; //ratio=1表示不缩放 if (originalWidth > originalHeight && originalWidth > convertedWidth) { //如果宽度大的话根据宽度固定大小缩放 ratio = (int) (newOpts.outWidth / convertedWidth); } else if (originalWidth < originalHeight && originalHeight > convertedHeight) { //如果高度高的话根据高度固定大小缩放 ratio = (int) (newOpts.outHeight / convertedHeight); } if (ratio <= 0) { ratio = 1; } newOpts.inJustDecodeBounds = false; newOpts.inSampleSize = ratio;//设置缩放比例 // 开始压缩图片,注意此时已经把options.inJustDecodeBounds 设回false了 Bitmap bitmap = BitmapFactory.decodeFile(imgPath, newOpts); // 压缩好比例大小后再进行质量压缩 // return compress(bitmap, maxSize); // 这里再进行质量压缩的意义不大,反而耗资源,删除 return bitmap; } /** * Compress image by size, this will modify image width/height. * Used to get thumbnail * * @param image * @param pixelW target pixel of width * @param pixelH target pixel of height * @return */ public Bitmap ratio(Bitmap image, float pixelW, float pixelH) { ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); image.compress(Bitmap.CompressFormat.JPEG, 100, byteArrayOutputStream); if (byteArrayOutputStream.toByteArray().length / 1024 > 1024) {//判断如果图片大于1M,进行压缩避免在生成图片(BitmapFactory // .decodeStream)时溢出 byteArrayOutputStream.reset();//重置baos即清空baos image.compress(Bitmap.CompressFormat.JPEG, 50, byteArrayOutputStream);//这里压缩50%,把压缩后的数据存放到baos中 } ByteArrayInputStream byteArrayInputStream; // 开始压缩图片,注意此时已经把options.inJustDecodeBounds 设回false了 byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray()); BitmapFactory.Options newOpts = new BitmapFactory.Options(); // 开始读入图片,此时把options.inJustDecodeBounds 设回true,即只读边不读内容 newOpts.inJustDecodeBounds = true; newOpts.inPreferredConfig = Config.RGB_565; BitmapFactory.decodeStream(byteArrayInputStream, null, newOpts); int originalWidth = image.getWidth(); int originalHeight = image.getHeight(); // 想要缩放的目标尺寸 float convertedWidth = pixelW;// 设置宽度为120f,可以明显看到图片缩小了 float convertedHeight = pixelH;// 设置高度为240f时,可以明显看到图片缩小了 // 缩放比。由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可 int ratio = 1; //ratio=1表示不缩放 if (originalWidth > originalHeight && originalWidth > convertedWidth) { //如果宽度大的话根据宽度固定大小缩放 ratio = (int) (newOpts.outWidth / convertedWidth); } else if (originalWidth < originalHeight && originalHeight > convertedHeight) { //如果高度高的话根据高度固定大小缩放 ratio = (int) (newOpts.outHeight / convertedHeight); } if (ratio <= 0) { ratio = 1; } newOpts.inJustDecodeBounds = false; //注意此时已经把options.inJustDecodeBounds 设回false了 newOpts.inSampleSize = ratio; //设置缩放比例 return BitmapFactory.decodeStream(byteArrayInputStream, null, newOpts); } /** * Compress by quality, and generate image to the path specified * Use to upload * * @param image * @param outPath * @param maxSize target will be compressed to be smaller than this size.(kb) * @throws IOException */ public static void compressAndGenImage(Bitmap image, String outPath, int maxSize) throws IOException { ByteArrayOutputStream os = new ByteArrayOutputStream(); // scale int options = 100; // Store the bitmap into output stream(no compress) image.compress(Bitmap.CompressFormat.JPEG, options, os); // Compress by loop while (os.toByteArray().length / 1024 > maxSize) { // Clean up os os.reset(); // interval 10 options -= 10; if (options < 0) { options = 0; image.compress(Bitmap.CompressFormat.JPEG, options, os); break; } image.compress(Bitmap.CompressFormat.JPEG, options, os); } // Generate compressed image file FileOutputStream fos = new FileOutputStream(outPath); fos.write(os.toByteArray()); fos.flush(); fos.close(); } /** * Compress by quality, and generate image to the path specified * * @param imgPath * @param outPath * @param maxSize target will be compressed to be smaller than this size.(kb) * @param needsDelete Whether delete original file after compress * @throws IOException */ public void compressAndGenImage(String imgPath, String outPath, int maxSize, boolean needsDelete) throws IOException { compressAndGenImage(getBitmap(imgPath), outPath, maxSize); // Delete original file if (needsDelete) { File file = new File(imgPath); if (file.exists()) { file.delete(); } } } /** * Ratio and generate thumb to the path specified * * @param image * @param outPath * @param pixelW target pixel of width * @param pixelH target pixel of height * @throws FileNotFoundException */ public void ratioAndGenThumb(Bitmap image, String outPath, float pixelW, float pixelH) throws FileNotFoundException { Bitmap bitmap = ratio(image, pixelW, pixelH); storeImage(bitmap, outPath); } /** * Ratio and generate thumb to the path specified * * @param imgPath * @param outPath * @param pixelW target pixel of width * @param pixelH target pixel of height * @param needsDelete Whether delete original file after compress * @throws FileNotFoundException */ public void ratioAndGenThumb(String imgPath, String outPath, float pixelW, float pixelH, boolean needsDelete) throws FileNotFoundException { Bitmap bitmap = ratio(imgPath, pixelW, pixelH); storeImage(bitmap, outPath); // Delete original file if (needsDelete) { File file = new File(imgPath); if (file.exists()) { file.delete(); } } } /** * 根据路径获取图片资源(已缩放) * * @param url 图片存储路径 * @param width 缩放的宽度 * @param height 缩放的高度 * @return */ public static Bitmap getBitmapFromUrl(String url, double width, double height) { BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; // 设置了此属性一定要记得将值设置为false Bitmap bitmap = BitmapFactory.decodeFile(url); // 防止OOM发生 options.inJustDecodeBounds = false; int mWidth = bitmap.getWidth(); int mHeight = bitmap.getHeight(); Matrix matrix = new Matrix(); float scaleWidth = 1; float scaleHeight = 1; // 按照固定宽高进行缩放 // 这里希望知道照片是横屏拍摄还是竖屏拍摄 // 因为两种方式宽高不同,缩放效果就会不同 // 这里用了比较笨的方式 if (mWidth <= mHeight) { scaleWidth = (float) (width / mWidth); scaleHeight = (float) (height / mHeight); } else { scaleWidth = (float) (height / mWidth); scaleHeight = (float) (width / mHeight); } // 按照固定大小对图片进行缩放 matrix.postScale(scaleWidth, scaleHeight); Bitmap newBitmap = Bitmap.createBitmap(bitmap, 0, 0, mWidth, mHeight, matrix, true); // 用完了记得回收 bitmap.recycle(); try { storeImage(newBitmap, url); } catch (FileNotFoundException e) { e.printStackTrace(); } return newBitmap; } }