[Android]Android图片压缩(质量压缩和尺寸压缩)
两种方法都实装在了我的项目中,结果却发现在质量压缩的模块中,本来1.9M的图片压缩后反而变成3M多了,很是奇怪,再做了进一步调查终于知道原因了。下面这个博客说的比较清晰:
android图片压缩总结
总结来看,图片有三种存在形式:硬盘上时是file,网络传输时是stream,内存中是stream或bitmap,所谓的质量压缩,它其实只能实现对file的影响,你可以把一个file转成bitmap再转成file,或者直接将一个bitmap转成file时,这个最终的file是被压缩过的,但是中间的bitmap并没有被压缩(或者说几乎没有被压缩,我不确定),因为bigmap在内存中的大小是按像素计算的,也就是width * height,对于质量压缩,并不会改变图片的像素,所以就算质量被压缩了,但是bitmap在内存的占有率还是没变小,但你做成file时,它确实变小了;
而尺寸压缩由于是减小了图片的像素,所以它直接对bitmap产生了影响,当然最终的file也是相对的变小了;
最后把自己总结的工具类贴出来:
- import java.io.ByteArrayInputStream;
- import java.io.ByteArrayOutputStream;
- import java.io.File;
- import java.io.FileNotFoundException;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import android.graphics.Bitmap;
- import android.graphics.Bitmap.Config;
- import android.graphics.BitmapFactory;
- /**
- * Image compress factory class
- *
- * @author
- *
- */
- public class ImageFactory {
- /**
- * Get bitmap from specified image path
- *
- * @param imgPath
- * @return
- */
- public Bitmap getBitmap(String imgPath) {
- // Get bitmap through image path
- BitmapFactory.Options newOpts = new BitmapFactory.Options();
- newOpts.inJustDecodeBounds = false;
- newOpts.inPurgeable = true;
- newOpts.inInputShareable = true;
- // 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 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
- Bitmap bitmap = BitmapFactory.decodeFile(imgPath,newOpts);
- newOpts.inJustDecodeBounds = false;
- int w = newOpts.outWidth;
- int h = newOpts.outHeight;
- // 想要缩放的目标尺寸
- float hh = pixelH;// 设置高度为240f时,可以明显看到图片缩小了
- float ww = pixelW;// 设置宽度为120f,可以明显看到图片缩小了
- // 缩放比。由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可
- int be = 1;//be=1表示不缩放
- if (w > h && w > ww) {//如果宽度大的话根据宽度固定大小缩放
- be = (int) (newOpts.outWidth / ww);
- } else if (w < h && h > hh) {//如果高度高的话根据宽度固定大小缩放
- be = (int) (newOpts.outHeight / hh);
- }
- if (be <= 0) be = 1;
- newOpts.inSampleSize = be;//设置缩放比例
- // 开始压缩图片,注意此时已经把options.inJustDecodeBounds 设回false了
- 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 os = new ByteArrayOutputStream();
- image.compress(Bitmap.CompressFormat.JPEG, 100, os);
- if( os.toByteArray().length / 1024>1024) {//判断如果图片大于1M,进行压缩避免在生成图片(BitmapFactory.decodeStream)时溢出
- os.reset();//重置baos即清空baos
- image.compress(Bitmap.CompressFormat.JPEG, 50, os);//这里压缩50%,把压缩后的数据存放到baos中
- }
- ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
- BitmapFactory.Options newOpts = new BitmapFactory.Options();
- //开始读入图片,此时把options.inJustDecodeBounds 设回true了
- newOpts.inJustDecodeBounds = true;
- newOpts.inPreferredConfig = Config.RGB_565;
- Bitmap bitmap = BitmapFactory.decodeStream(is, null, newOpts);
- newOpts.inJustDecodeBounds = false;
- int w = newOpts.outWidth;
- int h = newOpts.outHeight;
- float hh = pixelH;// 设置高度为240f时,可以明显看到图片缩小了
- float ww = pixelW;// 设置宽度为120f,可以明显看到图片缩小了
- //缩放比。由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可
- int be = 1;//be=1表示不缩放
- if (w > h && w > ww) {//如果宽度大的话根据宽度固定大小缩放
- be = (int) (newOpts.outWidth / ww);
- } else if (w < h && h > hh) {//如果高度高的话根据宽度固定大小缩放
- be = (int) (newOpts.outHeight / hh);
- }
- if (be <= 0) be = 1;
- newOpts.inSampleSize = be;//设置缩放比例
- //重新读入图片,注意此时已经把options.inJustDecodeBounds 设回false了
- is = new ByteArrayInputStream(os.toByteArray());
- bitmap = BitmapFactory.decodeStream(is, null, newOpts);
- //压缩好比例大小后再进行质量压缩
- // return compress(bitmap, maxSize); // 这里再进行质量压缩的意义不大,反而耗资源,删除
- return bitmap;
- }
- /**
- * Compress by quality, and generate image to the path specified
- *
- * @param image
- * @param outPath
- * @param maxSize target will be compressed to be smaller than this size.(kb)
- * @throws IOException
- */
- public 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;
- 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 image
- * @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();
- }
- }
- }
- }
android图片压缩总结
一.图片的存在形式
2.流的形式(即以二进制形式存在于内存中)
3.Bitmap形式
二.常见的压缩方式
- public static void compressBmpToFile(Bitmap bmp,File file){
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- int options = 80;//个人喜欢从80开始,
- bmp.compress(Bitmap.CompressFormat.JPEG, options, baos);
- while (baos.toByteArray().length / 1024 > 100) {
- baos.reset();
- options -= 10;
- bmp.compress(Bitmap.CompressFormat.JPEG, options, baos);
- }
- try {
- FileOutputStream fos = new FileOutputStream(file);
- fos.write(baos.toByteArray());
- fos.flush();
- fos.close();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
既然它是改变了图片的显示质量, 达到了对File形式的图片进行压缩, 图片的像素没有改变的话, 那重新读取经过压缩 的file为Bitmap时, 它占用的内存并不会少.(不相信的可以试试)
2. 将图片从本地读到内存时,进行压缩 ,即图片从File形式变为Bitmap形式
- private Bitmap compressBmpFromBmp(Bitmap image) {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- int options = 100;
- image.compress(Bitmap.CompressFormat.JPEG, 100, baos);
- while (baos.toByteArray().length / 1024 > 100) {
- baos.reset();
- options -= 10;
- image.compress(Bitmap.CompressFormat.JPEG, options, baos);
- }
- ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());
- Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);
- return bitmap;
- }
再看一个方法:
- private Bitmap compressImageFromFile(String srcPath) {
- BitmapFactory.Options newOpts = new BitmapFactory.Options();
- newOpts.inJustDecodeBounds = true;//只读边,不读内容
- Bitmap bitmap = BitmapFactory.decodeFile(srcPath, newOpts);
- newOpts.inJustDecodeBounds = false;
- int w = newOpts.outWidth;
- int h = newOpts.outHeight;
- float hh = 800f;//
- float ww = 480f;//
- int be = 1;
- if (w > h && w > ww) {
- be = (int) (newOpts.outWidth / ww);
- } else if (w < h && h > hh) {
- be = (int) (newOpts.outHeight / hh);
- }
- if (be <= 0)
- be = 1;
- newOpts.inSampleSize = be;//设置采样率
- newOpts.inPreferredConfig = Config.ARGB_8888;//该模式是默认的,可不设
- newOpts.inPurgeable = true;// 同时设置才会有效
- newOpts.inInputShareable = true;//。当系统内存不够时候图片自动被回收
- bitmap = BitmapFactory.decodeFile(srcPath, newOpts);
- // return compressBmpFromBmp(bitmap);//原来的方法调用了这个方法企图进行二次压缩
- //其实是无效的,大家尽管尝试
- return bitmap;
- }
- public static void compressPicture(String srcPath, String desPath) {
- FileOutputStream fos = null;
- BitmapFactory.Options op = new BitmapFactory.Options();
- // 开始读入图片,此时把options.inJustDecodeBounds 设回true了
- op.inJustDecodeBounds = true;
- Bitmap bitmap = BitmapFactory.decodeFile(srcPath, op);
- op.inJustDecodeBounds = false;
- // 缩放图片的尺寸
- float w = op.outWidth;
- float h = op.outHeight;
- float hh = 1024f;//
- float ww = 1024f;//
- // 最长宽度或高度1024
- float be = 1.0f;
- if (w > h && w > ww) {
- be = (float) (w / ww);
- } else if (w < h && h > hh) {
- be = (float) (h / hh);
- }
- if (be <= 0) {
- be = 1.0f;
- }
- op.inSampleSize = (int) be;// 设置缩放比例,这个数字越大,图片大小越小.
- // 重新读入图片,注意此时已经把options.inJustDecodeBounds 设回false了
- bitmap = BitmapFactory.decodeFile(srcPath, op);
- int desWidth = (int) (w / be);
- int desHeight = (int) (h / be);
- bitmap = Bitmap.createScaledBitmap(bitmap, desWidth, desHeight, true);
- try {
- fos = new FileOutputStream(desPath);
- if (bitmap != null) {
- bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
- }
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- }
- }
[Android]Android图片压缩(质量压缩和尺寸压缩)相关推荐
- 【jquery】通过降低图片的质量(或尺寸)压缩图片大小
生产上图片太大除了用户体验不好,上传等待时间过长,还可能会引发用户缓存丢失,导致必要参数缺失请求失败,或者超时引起的请求失败,查找资料,原理是经过一系列的转化过程file文件=>base64=& ...
- android 不压缩保存图片格式,Android中图片的压缩方法
Bitmap Android中图片是以Bitmap(位图)形式存在,位图常见的文件格式有:.bmp .jpg .png .gif . Bitmap的大小计算 = 图片的长度图片的宽度单位像素所占用的字 ...
- 性能优化之图片压缩(质量压缩、尺寸压缩)
前言 作为开发者的我们,经常会做一些上传图片和和保存图片啦 但是由于一些图片非常大,我们在上传或者保存的时候会占用大量的网络资源和本地资源,那么我们需要做的就是对图片就行压缩.以下介绍常见的两种压缩方 ...
- 图像的压缩算法--尺寸压缩、格式压缩和品质压缩
图像分辨率指图像中存储的信息量,是每英寸图像内有多少个像素点,分辨率的单位为PPI(Pixels Per Inch),通常叫做像素每英寸.图像分辨率一般被用于ps中,用来改变图像的清晰度. 一个影像可 ...
- Android图片压缩(质量压缩和尺寸压缩)
在网上调查了图片压缩的方法并实装后,大致上可以认为有两类压缩:质量压缩(不改变图片的尺寸)和尺寸压缩(相当于是像素上的压缩):质量压缩一般可用于上传大图前的处理,这样就可以节省一定的流量,毕竟现在的手 ...
- Android图片压缩(质量压缩和尺寸压缩)Bitmap转成字符串上传
在网上调查了图片压缩的方法并实装后,大致上可以认为有两类压缩:质量压缩(不改变图片的尺寸)和尺寸压缩(相当于是像素上的压缩):质量压缩一般可用于上传大图前的处理,这样就可以节省一定的流量,毕竟现在的手 ...
- 【Android 内存优化】图片文件压缩 ( Android 原生 API 提供的图片压缩功能能 | 图片质量压缩 | 图片尺寸压缩 )
文章目录 一. 图片压缩 二. 图片文件压缩类型 三. Android 原生 API 提供的质量压缩 四. Android 原生 API 提供的尺寸压缩 一. 图片压缩 图片压缩 : ① 文件压缩 : ...
- android bitmap 无损压缩,详解Bitmap尺寸压缩与质量压缩
转载请注明出自flowsky37的博客,尊重他人辛苦劳动! 在Android系统中,关于图片处理的是一个既常见又比较棘手的问题.一个应用中,存在需要展示大量的图片的布局,那我们必须要小心翼翼的处理了, ...
- 【Android 内存优化】Android 原生 API 图片压缩代码示例 ( PNG 格式压缩 | JPEG 格式压缩 | WEBP 格式压缩 | 动态权限申请 | Android10 存储策略 )
文章目录 一. 图片质量压缩 二. 图片尺寸压缩 三. Android 10 文件访问 四. 完整源码示例 上一篇博客 [Android 内存优化]图片文件压缩 ( Android 原生 API 提供 ...
最新文章
- 关于前后端交互的一些基础知识点
- 微软发布 VS Code Java 安装程序,一键安装所有 Java 开发环境
- 前端学习(2697):重读vue电商网站18之监听图片删除事件
- Grafana文档(在Centos / Redhat上安装)
- python安装后无法使用_Python在终端通过pip安装好包以后在Pycharm中依然无法使用的问题(三种解决方案)...
- 面试题11. 旋转数组的最小数字
- jdbc事物提交,回滚不起作用的解决方案
- Windows 10 全新界面来了:焕然一新!
- android 人脸相似度,微软“我们”正式发布 :测试人脸相似度
- firefox改html内容,Firefox 中的 HTML5 音视频
- WIN7 VS2005 安装wince6.0教程(不管是X86还是X64,我都尝试成功了)
- 三维扫描用于3D打印技术
- (Java实现) 工作分配问题
- Windows 8/8.1/10 删除微软拼音、微软五笔输入法的方法
- android型号的平板电脑,AUTOID Pad /Air-(win)/Air-(android)工业级平板电脑
- 年薪30W+的IC验证工程师究竟是做什么的?一文为你讲解清楚
- 考试周刊杂志考试周刊杂志社考试周刊编辑部2022年第39期目录
- 求斐波那契数列c++实现
- html无序站点,html有序无序定义列表详解(案例介绍)
- Qt实现一个简易截图工具(支持缩放、移动、保存、复制到粘贴板)