返回介绍

Android 图片压缩技巧

发布于 2025-02-26 12:59:34 字数 5832 浏览 0 评论 0 收藏 0

请尊重他人的劳动成果,转载请注明出处: Android 图片压缩技巧

http://blog.csdn.net/fengyuzhengfan/article/details/41759835

当需要将 Android 客户端的图片上传到服务器时,往往需要将图片进行压缩,关于图片的压缩方法,小编分享几种常用的方式:

第一种方式:裁切以达到压缩的目的

我曾在《 Android 开发之裁剪照片 》一文中详细介绍过如何裁切照片,感兴趣的朋友可以去看一下。

第二种方式:将图片进行降质处理(即降低图片的质量)以达到压缩的目的

这种方式也是比较常用的方式,下面就为大家介绍如何对图片进行降质:将图片降质我们可以使用 Bitmap 的这个方法: boolean android.graphics.Bitmap.compress(CompressFormat format, int quality, OutputStream stream) ​,其中,参数 format 表示压缩后的格式,quality 压缩后的图片质量(0 表示最低,100 表示不压缩),stream 表示要将压缩后的图片保存到的输出流。

下面是详细代码:

/**
 * 多线程压缩图片的质量
 * @author JPH
 * @param bitmap 内存中的图片
 * @param imgPath 图片的保存路径
 * @date 2014-12-5 下午 11:30:43
 */
public static void compressImageByQuality(final Bitmap bitmap,final String imgPath){
  new Thread(new Runnable() {//开启多线程进行压缩处理
    @Override
    public void run() {
      // TODO Auto-generated method stub
      ByteArrayOutputStream baos = new ByteArrayOutputStream();
      options = 100;
      bitmap.compress(Bitmap.CompressFormat.JPEG, options, baos);//质量压缩方法,把压缩后的数据存放到 baos 中 (100 表示不压缩,0 表示压缩到最小)
      while (baos.toByteArray().length / 1024 > 100) {//循环判断如果压缩后图片是否大于 100kb,大于继续压缩     
        baos.reset();//重置 baos 即让下一次的写入覆盖之前的内容 
        options -= 10;//图片质量每次减少 10
        if(options<0)options=0;//如果图片质量小于 10,则将图片的质量压缩到最小值
        bitmap.compress(Bitmap.CompressFormat.JPEG, options, baos);//将压缩后的图片保存到 baos 中
        if(options==0)break;//如果图片的质量已降到最低则,不再进行压缩
      }
      try {
        FileOutputStream fos = new FileOutputStream(new File(imgPath));//将压缩后的图片保存的本地上指定路径中
        fos.write(baos.toByteArray());
        fos.flush();
        fos.close();
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
  }).start();
}

方法解析:由于此方法中包含 I/O 操作和递归调用比较耗时所以我采用了多线程去处理。

第三种方式:按比例缩小图片的像素以达到压缩的目的

此种方法主要是使用 android.graphics.BitmapFactory.Options.Options() 方法将图片以指定的采用率加载到内存然后输出到本地以达到压缩像素的目的。详细代码:

/**
 * 按比例缩小图片的像素以达到压缩的目的
 * @author JPH
 * @param imgPath
 * @date 2014-12-5 下午 11:30:59
 */
public static void compressImageByPixel(String imgPath) {
  BitmapFactory.Options newOpts = new BitmapFactory.Options();
  newOpts.inJustDecodeBounds = true;//只读边,不读内容
  Bitmap bitmap = BitmapFactory.decodeFile(imgPath, newOpts);
  newOpts.inJustDecodeBounds = false;
  int width = newOpts.outWidth;
  int height = newOpts.outHeight;
  float maxSize = 1000f;//默认 1000px
  int be = 1;
  if (width > height && width > maxSize) {//缩放比,用高或者宽其中较大的一个数据进行计算
    be = (int) (newOpts.outWidth / maxSize);
  } else if (width < height && height > maxSize) {
    be = (int) (newOpts.outHeight / maxSize);
  }
  be++;
  newOpts.inSampleSize = be;//设置采样率
  newOpts.inPreferredConfig = Config.ARGB_8888;//该模式是默认的,可不设
  newOpts.inPurgeable = true;// 同时设置才会有效
  newOpts.inInputShareable = true;//。当系统内存不够时候图片自动被回收
  bitmap = BitmapFactory.decodeFile(imgPath, newOpts);

  ByteArrayOutputStream baos = new ByteArrayOutputStream();
  bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
  try {
    FileOutputStream fos = new FileOutputStream(new File(imgPath));
    fos.write(baos.toByteArray());
    fos.flush();
    fos.close();
  } catch (Exception e) {
    e.printStackTrace();
  }
}

第四种方式:将图片先按比例压缩然后再降质

此种方式主要结合第二种和第三种方法以下是详细代码:

/**
 * 多线程压缩图片的质量
 * @author JPH
 * @param bitmap 内存中的图片
 * @param imgPath 图片的保存路径
 * @date 2014-12-5 下午 11:30:43
 */
public static void compressImageByQuality(final Bitmap bitmap,final String imgPath){
  new Thread(new Runnable() {//开启多线程进行压缩处理
    @Override
    public void run() {
      // TODO Auto-generated method stub
      ByteArrayOutputStream baos = new ByteArrayOutputStream();
      options = 100;
      bitmap.compress(Bitmap.CompressFormat.JPEG, options, baos);//质量压缩方法,把压缩后的数据存放到 baos 中 (100 表示不压缩,0 表示压缩到最小)
      while (baos.toByteArray().length / 1024 > 100) {//循环判断如果压缩后图片是否大于 100kb,大于继续压缩     
        baos.reset();//重置 baos 即让下一次的写入覆盖之前的内容 
        options -= 10;//图片质量每次减少 10
        if(options<0)options=0;//如果图片质量小于 10,则将图片的质量压缩到最小值
        bitmap.compress(Bitmap.CompressFormat.JPEG, options, baos);//将压缩后的图片保存到 baos 中
        if(options==0)break;//如果图片的质量已降到最低则,不再进行压缩
      }
      try {
        FileOutputStream fos = new FileOutputStream(new File(imgPath));//将压缩后的图片保存的本地上指定路径中
        fos.write(baos.toByteArray());
        fos.flush();
        fos.close();
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
  }).start();
}
/**
 * 按比例缩小图片的像素以达到压缩的目的
 * @author JPH
 * @param imgPath
 * @date 2014-12-5 下午 11:30:59
 */
public static void compressImageByPixel(String imgPath) {
  BitmapFactory.Options newOpts = new BitmapFactory.Options();
  newOpts.inJustDecodeBounds = true;//只读边,不读内容
  Bitmap bitmap = BitmapFactory.decodeFile(imgPath, newOpts);
  newOpts.inJustDecodeBounds = false;
  int width = newOpts.outWidth;
  int height = newOpts.outHeight;
  float maxSize = 1000f;//默认 1000px
  int be = 1;
  if (width > height && width > maxSize) {//缩放比,用高或者宽其中较大的一个数据进行计算
    be = (int) (newOpts.outWidth / maxSize);
  } else if (width < height && height > maxSize) {
    be = (int) (newOpts.outHeight / maxSize);
  }
  be++;
  newOpts.inSampleSize = be;//设置采样率
  newOpts.inPreferredConfig = Config.ARGB_8888;//该模式是默认的,可不设
  newOpts.inPurgeable = true;// 同时设置才会有效
  newOpts.inInputShareable = true;//。当系统内存不够时候图片自动被回收
  bitmap = BitmapFactory.decodeFile(imgPath, newOpts);
  compressImageByQuality(bitmap,imgPath);//压缩好比例大小后再进行质量压缩  
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文