Android 图像压缩
Android中图片是以Bitmap形式存在的,Bitmap所占内存直接影响应用所占内存大小,Bitmap所占内存大小计算公式:
图片长度 * 图片宽度 * 一个像素点占用的字节数
Bitmap压缩颜色格式:
- 质量压缩
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图片时无损的,不能进行压缩。
- 采样率压缩
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。
- 缩放法压缩(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。
- 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将节省一半的内存开销。
- 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 图像压缩相关推荐
- 全网最全Android开发工具,Android开发框架大全
涵盖Android方方面面的技术, 目前保持更新. 时刻与Android开发流行前沿同步. 目录 一.工具 Android开发工具 在线工具宝典大全 二.框架 *缓存框架* DiskLruCache ...
- Google发布新的图像压缩技术,最高可节省75%带宽
Google发布新的图像压缩技术,最高可节省75%带宽 在社交网络上,每天都有难以计数的图片被人们分享.存储.但有一个现实的问题是,大量的照片由于网络限制被人为压缩降低了画质.而Apple在2010年 ...
- Android开发常用开源框架:图片处理
1. 图片加载,缓存,处理 框架名称 功能描述 Android Universal Image Loader 一个强大的加载,缓存,展示图片的库,已过时 Picasso 一个强大的图片下载与缓存的库 ...
- 2017年伊始,你需要尝试的25个Android第三方库
作者:Jack-sen,原文地址:http://blog.csdn.net/crazy1235/article/details/55805071 medium 平台有位作者总结了2017年初最棒最受欢 ...
- 如何节省 1TB 图片带宽?解密极致图像压缩
欢迎大家前往云+社区,获取更多腾讯海量技术实践干货哦~ 作者:Gophery 本文由 腾讯技术工程官方号 发布在云+社区 图像已经发展成人类沟通的视觉语言.无论传统互联网还是移动互联网,图像一直占据着 ...
- [Android] 使用Matrix矩阵类对图像进行缩放、旋转、对比度、亮度处理
前一篇文章讲述了Android拍照.截图.保存并显示在ImageView控件中,该篇文章继续讲述Android图像处理技术,主要操作包括:通过打开相册里的图片,使用Matrix对图像进行缩放. ...
- 利用Android Camera2 的照相机api 实现 实时的图像采集与预览
最近想要做一个客户端往服务器推送实时画面的功能,首先可以考虑到两种思路,一种是在客户端进行视频流的推送,主要利用RTSP等流媒体协议进行传输,而另外一种是通过摄像头获取当前画面,将每一帧作为对象单独传 ...
- 如何节省1T图片带宽?解密极致图像压缩!
图像已经发展成人类沟通的视觉语言.无论传统互联网还是移动互联网,图像一直占据着很大部分的流量.如何在保证视觉体验的情况下减少数据流量消耗,一直是图像处理领域研究的热点.也诞生了许多种类的图像格式JPE ...
- 动脑2017android_您肯定要在2017年初尝试的25个新Android库
动脑2017android by Michal Bialas 由Michal Bialas 您肯定要在2017年初试用的25个Android库 (25 Android libraries you de ...
最新文章
- Javascript_初学第1天
- WINCE支持的波斯语的codepages
- EhCache的配置
- 浅谈ASP中Web页面间的数据传递
- thinkphp3 php jwt,thinkphp框架使用JWTtoken的方法详解
- Java核心篇之泛型--day5
- ORA-12011+ORA-06512–job执行失败问题
- android studio react native 模拟器,Windows下搭建React Native环境与Android Studio集成
- QCC---Temperature component
- Win7 Hiberfil.sys pagefile.sys
- 跨时区时间运算以及时间实时更新方法
- 为知笔记 | 3 分钟创建格式美美的笔记
- matlab2019b重装导致mjs安装失败问题解决
- 如何把可爱的Live2d看板娘放到自己的网页上
- 【vi】vi编辑器卡死解决方法
- 火山引擎数智平台的这款产品,正在帮助 APP 提升用户活跃度
- Direct Show学习方法
- 力扣题:977. 有序数组的平方
- hdu 1861 游船出租
- MySQL 8.0.31 最新版详细安装教程(下载+安装+配置+登录测试)