Android图片压缩

最近项目需求中,有对图片上传需求,既不能压缩过小导致不清晰,又不能原图上传,导致上传过慢,不仅浪费了流量,体验上也不好

影响图片大小的一个是图片质量,一个是图片像素。压缩方法无非是,采样率压缩和质量压缩,还有一个是微信压缩(这个请自行学习,涉及到jni层面)

图片像素:图片像素大家应该都知道,不知道的请自行百度。为了解决大图片在控件上引起崩溃,我们通常的做法就是修改采样率,采样率是什么?可以简单理解,它与像素有关。修改采样率即修改了像素

图片质量:这个可以理解成图片的饱和度,感光率等等吧!它很大程度上影响了图片的大小,但是不能够无限压缩,因为就算质量压缩没了,也不会影响像素,这是两个概念。

那么在app上传图片的时候,如何保证图片清晰且压缩的较小?

经过多轮测试,最后得出的结果就是,用长宽比率进行采样率的等比压缩,然后进行质量压缩,循环判断是否小于100k,如果不是,那么继续压缩,一直到小于100k

附上代码
这是采样率的等比压缩

/**
 * 修改图片的采样率
 * @param reqWidth
 * @param reqHeight
 * @return
 */
public static Bitmap decodeSampledBitmapFromData(String imgPath,int reqWidth, int reqHeight) {
   try {
      // 第一次解析将inJustDecodeBounds设置为true,来获取图片大小
       final BitmapFactory.Options options = new BitmapFactory.Options();
       options.inJustDecodeBounds = true;
       BitmapFactory.decodeFile(imgPath, options);

      int minSize = options.outWidth > options.outHeight ? options.outHeight : options.outWidth;
      if (minSize > reqWidth) {
         // 调用上面定义的方法计算inSampleSize值
         options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
      }
       // 使用获取到的inSampleSize值再次解析图片
       options.inJustDecodeBounds = false;
       return BitmapFactory.decodeFile(imgPath, options);
   } catch (Exception e) {
      e.printStackTrace();
      return null;
   }
}

/**
 * 计算图片缩放的比例
 * @param options
 * @param reqWidth
 * @param reqHeight
 * @return
 */
public static int calculateInSampleSize(BitmapFactory.Options options,
   int reqWidth, int reqHeight) {
   // 源图片的高度和宽度
   final int height = options.outHeight;
   final int width = options.outWidth;
   int inSampleSize = 1;
   if (height > reqHeight || width > reqWidth) {
      // 计算出实际宽高和目标宽高的比率
      final int heightRatio = Math.round((float) height / (float) reqHeight);
      final int widthRatio = Math.round((float) width / (float) reqWidth);
      // 选择宽和高中最小的比率作为inSampleSize的值,这样可以保证最终图片的宽和高
      // 一定都会大于等于目标的宽和高。
      inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
   }
   return inSampleSize;
}
这是图片的质量压缩(借用下别人的代码)
  1. private Bitmap compressImage(Bitmap image) {  
  2.   
  3.         ByteArrayOutputStream baos = new ByteArrayOutputStream();  
  4.         image.compress(Bitmap.CompressFormat.JPEG, 100, baos);//质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中  
  5.         int options = 100;  
  6.         while ( baos.toByteArray().length / 1024>100) {  //循环判断如果压缩后图片是否大于100kb,大于继续压缩         
  7.             baos.reset();//重置baos即清空baos  
  8.             image.compress(Bitmap.CompressFormat.JPEG, options, baos);//这里压缩options%,把压缩后的数据存放到baos中  
  9.             options -= 10;//每次都减少10  
  10.         }  
  11.         ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());//把压缩后的数据baos存放到ByteArrayInputStream中  
  12.         Bitmap bitmap = BitmapFactory.decodeStream(isBm, nullnull);//把ByteArrayInputStream数据生成图片  
  13.         return bitmap;  
  14.     }  

附一个压缩后本地保存方法

/**
     * 将压缩后的图片写入sd卡
     *
     */
    public static  String inputPicTosdcard(Bitmap bitmap, String picName) {
        String path = "";
        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
//            bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);

            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);//质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中
            int options = 80;
            while ( baos.toByteArray().length / 1024>200) {  //循环判断如果压缩后图片是否大于100kb,大于继续压缩
                baos.reset();//重置baos即清空baos
                bitmap.compress(Bitmap.CompressFormat.JPEG, options, baos);//这里压缩options%,把压缩后的数据存放到baos中
                if(options>=10){
                    options -= 10;//每次都减少10
                }else {
                    break;
                }
            }

            File SDFile = Environment.getExternalStorageDirectory();
            File destDir = new File(SDFile.getAbsolutePath() + "/文件夹名称/");//文件目录

            if (!destDir.exists()) {//判断目录是否存在,不存在创建
                destDir.mkdir();//创建目录
            }
            File pic = new File(destDir.getPath() + File.separator +picName);
            path = pic.getAbsolutePath();
            if (!pic.exists()) {
                try {
                    pic.createNewFile();//创建文件
                    FileOutputStream outputStream = new FileOutputStream(pic, true);
                    outputStream.write(baos.toByteArray());//写入内容
                    outputStream.close();//关闭流
                } catch (IOException e) {
                    e.printStackTrace();

                }
            }

        }
        return path;

    }

注意:如果光进行质量压缩,压缩到一定程度就压缩不下去了啊!光采样率压缩,可能会造成失真啊。

大概能看懂就行,然后根据自己的需求去改。


参照博客:http://blog.csdn.net/maqianli23/article/details/53980798
http://104zz.iteye.com/blog/1694762
http://blog.csdn.net/eiuly/article/details/46648215

你可能感兴趣的:(android升级篇)