Android中图片是以Bitmap形式存在的,Bitmap所占内存直接影响应用所占内存大小,Bitmap所占内存大小计算公式:
图片长度 * 图片宽度 * 一个像素点占用的字节数

Bitmap压缩颜色格式:

图1.png
  1. 质量压缩
        Bitmap bitmap = BitmapFactory.decodeFile(path);ByteArrayOutputStream baos = new ByteArrayOutputStream();int quality = 80;bitmap.compress(Bitmap.CompressFormat.JPEG, quality, baos);byte[] bytes = baos.toByteArray();bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);

图片的大小没有变化,因为质量有压缩不会减少图片的像素,它是在保持像素的前提下改变图图片的位深及透明度,来达到压缩图片的目的。
注: 当compress方法中第一个参数为Bitmap.CompressFormat.PNG时,quality没有作用,因为png图片时无损的,不能进行压缩。

  1. 采样率压缩
        BitmapFactory.Options options = new BitmapFactory.Options();options.inSampleSize = 2;Bitmap bitmap = BitmapFactory.decodeFile(path, options);

设置inSampleSize的值为2时,宽和高都变为原来的1/2。

注:当设置options.inJustDecodeBounds = true时,BitmapFactory解码图片时会返回空的Bitmap对象,但是也可以返回Bitmap的宽、高以及MimeType。

  1. 缩放法压缩(Martix)
        Matrix matrix = new Matrix();matrix.setScale(0.5f, 0.5f);Bitmap bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),bitmap.getHeight(), matrix, true);

其中,bitmap的宽高分别缩小了一半,图片大小压缩成1/4。

  1. RGB_565
        BitmapFactory.Options options = new BitmapFactory.Options();options.inPreferredConfig = Bitmap.Config.RGB_565;Bitmap bitmap = BitmapFactory.decodeFile(path, options);

图片大小直接缩小了一半,宽高没有变。
注意:由于ARGB_4444的画质惨不忍睹,一般假如对图片没有透明度要求的话,可以改成RGB_565,相比ARGB_8888将节省一半的内存开销。

  1. createScaledBitmap
        Bitmap bitmap = BitmapFactory.decodeFile(path);bitmap = Bitmap.createScaledBitmap(bitmap, 150, 150, true);

这里将图片压缩成用户所期望的宽高。

系统压缩工具类

从Android 2.2开始系统新增了一个缩略图ThumbnailUtils类,位于framework包下的android.media.ThumbnailUtils位置,可以帮助我们从mediaprovider中获取系统中的视频或图片文件的缩略图,该类提供了三种静态方法可以直接调用获取。1、extractThumbnail (source, width, height):/*** 创建一个指定大小的缩略图* @param source 源文件(Bitmap类型)* @param width  压缩成的宽度* @param height 压缩成的高度*/ThumbnailUtils.extractThumbnail(source, width, height);  2、extractThumbnail(source, width, height, options):
/*** 创建一个指定大小居中的缩略图* @param source 源文件(Bitmap类型)* @param width  输出缩略图的宽度* @param height 输出缩略图的高度* @param options 如果options定义为OPTIONS_RECYCLE_INPUT,则回收@param source这个资源文件* (除非缩略图等于@param source)**/
ThumbnailUtils.extractThumbnail(source, width, height, options);  3、createVideoThumbnail(filePath, kind):
/*** 创建一张视频的缩略图* 如果视频已损坏或者格式不支持可能返回null* @param filePath 视频文件路径  如:/sdcard/android.3gp* @param kind kind可以为MINI_KIND或MICRO_KIND**/ThumbnailUtils.createVideoThumbnail(filePath, kind);

压缩工具类

public class CompressUtils {  /** * 按质量压缩 * @param bitmap * @return */  public static Bitmap compressImage(Bitmap bitmap){  ByteArrayOutputStream baos = new ByteArrayOutputStream();  //质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中  bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);  int options = 100;  //循环判断如果压缩后图片是否大于100kb,大于继续压缩  while ( baos.toByteArray().length / 1024>100) {  //清空baos  baos.reset();  bitmap.compress(Bitmap.CompressFormat.JPEG, options, baos);  options -= 10;//每次都减少10  }  //把压缩后的数据baos存放到ByteArrayInputStream中  ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());  //把ByteArrayInputStream数据生成图片  Bitmap newBitmap = BitmapFactory.decodeStream(isBm, null, null);  return newBitmap;  }  /** * 按图片尺寸压缩 参数为路径 * @param imgPath 图片路径 * @param pixelW 目标图片宽度 * @param pixelH 目标图片高度 * @return */  public static Bitmap compressImageFromPath(String imgPath, int pixelW, int pixelH) {  BitmapFactory.Options options = new BitmapFactory.Options();  // 开始读入图片,此时把options.inJustDecodeBounds 设回true,即只读边不读内容  options.inJustDecodeBounds = true;  options.inPreferredConfig = Bitmap.Config.RGB_565;  BitmapFactory.decodeFile(imgPath,options);  options.inJustDecodeBounds = false;  options.inSampleSize = computeSampleSize(options , pixelH > pixelW ? pixelH : pixelW ,pixelW * pixelH );  Bitmap bitmap = BitmapFactory.decodeFile(imgPath, options);  return bitmap;  }  /** * 按图片尺寸压缩 参数是bitmap * @param bitmap * @param pixelW * @param pixelH * @return */  public static Bitmap compressImageFromBitmap(Bitmap bitmap, int pixelW, int pixelH) {  ByteArrayOutputStream os = new ByteArrayOutputStream();  bitmap.compress(Bitmap.CompressFormat.JPEG, 100, os);  if( os.toByteArray().length / 1024>1024) {//判断如果图片大于1M,进行压缩避免在生成图片(BitmapFactory.decodeStream)时溢出  os.reset();  bitmap.compress(Bitmap.CompressFormat.JPEG, 50, os);//这里压缩50%,把压缩后的数据存放到baos中  }  ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());  BitmapFactory.Options options = new BitmapFactory.Options();  options.inJustDecodeBounds = true;  options.inPreferredConfig = Bitmap.Config.RGB_565;  BitmapFactory.decodeStream(is, null, options);  options.inJustDecodeBounds = false;  options.inSampleSize = computeSampleSize(options , pixelH > pixelW ? pixelH : pixelW ,pixelW * pixelH );  is = new ByteArrayInputStream(os.toByteArray());  Bitmap newBitmap = BitmapFactory.decodeStream(is, null, options);  return newBitmap;  }  /** * 对图片进行缩放指定大小 * @param bitmap * @param width * @param height * @return */  public static Bitmap scaleTo(Bitmap bitmap, int width, int height){  int originalWidth = bitmap.getWidth();  int originalHeight = bitmap.getHeight();  float xScale = (float)width / originalWidth;  float yScale = (float)height / originalHeight;  Matrix matrix = new Matrix();  matrix.setScale(xScale,yScale);  return Bitmap.createBitmap(bitmap, 0, 0, originalWidth, originalHeight, matrix, true);  }  /** * 以最省内存的方式读取本地资源的图片 * @param context * @param resId * @return */  public static Bitmap readBitmap(Context context, int resId) {  BitmapFactory.Options opt = new BitmapFactory.Options();  opt.inPreferredConfig = Bitmap.Config.RGB_565;  opt.inPurgeable = true;  opt.inInputShareable = true;  // 获取资源图片  InputStream is = context.getResources().openRawResource(resId);  return BitmapFactory.decodeStream(is, null, opt);  }  /** * android源码提供给我们的动态计算出图片的inSampleSize方法 * @param options * @param minSideLength * @param maxNumOfPixels * @return */  public static int computeSampleSize(BitmapFactory.Options options, int minSideLength, int maxNumOfPixels) {  int initialSize = computeInitialSampleSize(options, minSideLength, maxNumOfPixels);  int roundedSize;  if (initialSize <= 8) {  roundedSize = 1;  while (roundedSize < initialSize) {  roundedSize <<= 1;  }  } else {  roundedSize = (initialSize + 7) / 8 * 8;  }  return roundedSize;  }  private static int computeInitialSampleSize(BitmapFactory.Options options,int minSideLength, int maxNumOfPixels) {  double w = options.outWidth;  double h = options.outHeight;  int lowerBound = (maxNumOfPixels == -1) ? 1 : (int) Math.ceil(Math.sqrt(w * h / maxNumOfPixels));  int upperBound = (minSideLength == -1) ? 128 :(int) Math.min(Math.floor(w / minSideLength), Math.floor(h / minSideLength));  if (upperBound < lowerBound) {  return lowerBound;  }  if ((maxNumOfPixels == -1) && (minSideLength == -1)) {  return 1;  } else if (minSideLength == -1) {  return lowerBound;  } else {  return upperBound;  }  }
}

有效的处理Bitmap OOM方法

public class BitmapActivity extends Activity {  public ImageView imageView = null;  @Override  protected void onCreate(Bundle savedInstanceState) {  super.onCreate(savedInstanceState);  setContentView(R.layout.bitmap_activity);  imageView = (ImageView) findViewById(R.id.imageView1);  ImageAsyncTask task = new ImageAsyncTask(imageView,50,50);  task.execute("http://image.baidu.com/search/down?tn=download&word=download&ie=utf8&fr=detail&url=http%3A%2F%2Fimg1.pconline.com.cn%2Fpiclib%2F200904%2F28%2Fbatch%2F1%2F32910%2F12408824046039mk21hbi75.jpg&thumburl=http%3A%2F%2Fimg2.imgtn.bdimg.com%2Fit%2Fu%3D3414739956%2C4196877666%26fm%3D21%26gp%3D0.jpg");  }  /** * 计算出压缩比 * @param options * @param reqWith * @param reqHeight * @return */  public int calculateInSampleSize(BitmapFactory.Options options,int reqWidth,int reqHeight)  {  //通过参数options来获取真实图片的宽、高  int width = options.outWidth;  int height = options.outHeight;  int inSampleSize = 1;//初始值是没有压缩的  if(width > reqWidth || height > reqHeight)  {  //计算出原始宽与现有宽,原始高与现有高的比率  int widthRatio = Math.round((float)width/(float)reqWidth);  int heightRatio = Math.round((float)height/(float)reqHeight);  //选出两个比率中的较小值,这样的话能够保证图片显示完全   inSampleSize = widthRatio < heightRatio ? widthRatio:heightRatio;  }  System.out.println("压缩比:  "+inSampleSize);  return inSampleSize;  }  /** * 将InputStream转换为Byte数组 * @param in * @return */  public static byte[] inputStreamToByteArray(InputStream in)  {  ByteArrayOutputStream outputStream = new ByteArrayOutputStream();  byte[] buffer = new byte[1024];  int len;  try {  while((len = in.read(buffer)) != -1)  {  outputStream.write(buffer, 0, len);  }  } catch (IOException e) {  e.printStackTrace();  }finally{  try {  in.close();  outputStream.close();  } catch (IOException e) {  e.printStackTrace();  }  }  return outputStream.toByteArray();  }  class ImageAsyncTask extends AsyncTask<String, Void, Bitmap>  {  public ImageView iv;  public int reqWidth;  public int reqHeight;  public ImageAsyncTask(ImageView imageView,int reqWidth,int reqHeight)  {  this.iv = imageView;  this.reqWidth = reqWidth;  this.reqHeight = reqHeight;  }  @Override  protected Bitmap doInBackground(String... params) {  URL url;  HttpURLConnection connection = null;  InputStream in = null;  Bitmap beforeBitmap = null;  Bitmap afterBitmap = null;  try {  url = new URL(params[0]);  connection = (HttpURLConnection) url.openConnection();  in = connection.getInputStream();  BitmapFactory.Options options = new BitmapFactory.Options();  //设置BitmapFactory.Options的inJustDecodeBounds属性为true表示禁止为bitmap分配内存  options.inJustDecodeBounds = true;  byte[] data = inputStreamToByteArray(in);  beforeBitmap = BitmapFactory.decodeByteArray(data, 0, data.length, options);//这次调用的目的是获取到原始图片的宽、高,但是这次操作是没有写内存操作的  options.inSampleSize = calculateInSampleSize(options,reqWidth, reqHeight);   //设置这次加载图片需要加载到内存中  options.inJustDecodeBounds = false;  afterBitmap = BitmapFactory.decodeByteArray(data, 0, data.length, options);  float afterSize = (float)(afterBitmap.getRowBytes()*afterBitmap.getHeight());  System.out.println("压缩之后的图片大小:  "+(float)afterSize/1024+"KB");  } catch (Exception e) {  System.out.println(e.toString());  }  return afterBitmap;  }  @Override  protected void onPostExecute(Bitmap result) {  if(result != null)  imageView.setImageBitmap(result);  }  }
}

Github图片压

Android 图像压缩相关推荐

  1. 全网最全Android开发工具,Android开发框架大全

    涵盖Android方方面面的技术, 目前保持更新. 时刻与Android开发流行前沿同步. 目录 一.工具 Android开发工具 在线工具宝典大全 二.框架 *缓存框架* DiskLruCache ...

  2. Google发布新的图像压缩技术,最高可节省75%带宽

    Google发布新的图像压缩技术,最高可节省75%带宽 在社交网络上,每天都有难以计数的图片被人们分享.存储.但有一个现实的问题是,大量的照片由于网络限制被人为压缩降低了画质.而Apple在2010年 ...

  3. Android开发常用开源框架:图片处理

    1. 图片加载,缓存,处理 框架名称 功能描述 Android Universal Image Loader 一个强大的加载,缓存,展示图片的库,已过时 Picasso 一个强大的图片下载与缓存的库 ...

  4. 2017年伊始,你需要尝试的25个Android第三方库

    作者:Jack-sen,原文地址:http://blog.csdn.net/crazy1235/article/details/55805071 medium 平台有位作者总结了2017年初最棒最受欢 ...

  5. 如何节省 1TB 图片带宽?解密极致图像压缩

    欢迎大家前往云+社区,获取更多腾讯海量技术实践干货哦~ 作者:Gophery 本文由 腾讯技术工程官方号 发布在云+社区 图像已经发展成人类沟通的视觉语言.无论传统互联网还是移动互联网,图像一直占据着 ...

  6. [Android] 使用Matrix矩阵类对图像进行缩放、旋转、对比度、亮度处理

        前一篇文章讲述了Android拍照.截图.保存并显示在ImageView控件中,该篇文章继续讲述Android图像处理技术,主要操作包括:通过打开相册里的图片,使用Matrix对图像进行缩放. ...

  7. 利用Android Camera2 的照相机api 实现 实时的图像采集与预览

    最近想要做一个客户端往服务器推送实时画面的功能,首先可以考虑到两种思路,一种是在客户端进行视频流的推送,主要利用RTSP等流媒体协议进行传输,而另外一种是通过摄像头获取当前画面,将每一帧作为对象单独传 ...

  8. 如何节省1T图片带宽?解密极致图像压缩!

    图像已经发展成人类沟通的视觉语言.无论传统互联网还是移动互联网,图像一直占据着很大部分的流量.如何在保证视觉体验的情况下减少数据流量消耗,一直是图像处理领域研究的热点.也诞生了许多种类的图像格式JPE ...

  9. 动脑2017android_您肯定要在2017年初尝试的25个新Android库

    动脑2017android by Michal Bialas 由Michal Bialas 您肯定要在2017年初试用的25个Android库 (25 Android libraries you de ...

最新文章

  1. Javascript_初学第1天
  2. WINCE支持的波斯语的codepages
  3. EhCache的配置
  4. 浅谈ASP中Web页面间的数据传递
  5. thinkphp3 php jwt,thinkphp框架使用JWTtoken的方法详解
  6. Java核心篇之泛型--day5
  7. ORA-12011+ORA-06512–job执行失败问题
  8. android studio react native 模拟器,Windows下搭建React Native环境与Android Studio集成
  9. QCC---Temperature component
  10. Win7 Hiberfil.sys pagefile.sys
  11. 跨时区时间运算以及时间实时更新方法
  12. 为知笔记 | 3 分钟创建格式美美的笔记
  13. matlab2019b重装导致mjs安装失败问题解决
  14. 如何把可爱的Live2d看板娘放到自己的网页上
  15. 【vi】vi编辑器卡死解决方法
  16. 火山引擎数智平台的这款产品,正在帮助 APP 提升用户活跃度
  17. Direct Show学习方法
  18. 力扣题:977. 有序数组的平方
  19. hdu 1861 游船出租
  20. MySQL 8.0.31 最新版详细安装教程(下载+安装+配置+登录测试)

热门文章

  1. Microsoft 365 安全吗?
  2. [读点书吧]近期书单
  3. 让我们一起学习《Node.js入门》一书吧!
  4. connectionstrings汇总
  5. QT如何生成Release版本(得到exe运行DLL)
  6. 一篇文章带你了解3D 打印机,新手点进来
  7. vue中触发按钮的点击事件
  8. JavaFX中TableView的使用
  9. 有哪些网站用爬虫爬取能得到很有价值的数据
  10. 0基础网络分析之获取好友位置