Android 图片压缩 策略

Android设备的内存有限,对于大图片,必须进行压缩后再进行显示,否则会出现内存溢出:OOM;

处理策略:

1.使用缩略图(Thumbnails);

Android系统会给检测到的图片创建缩略图;可以操作Media内容提供者中的Image对图片进行操作;

2.手动压缩:
(1)根据图片和屏幕尺寸,等比压缩,完美显示;
(2)降低图片质量,压缩图片大小;

以下是自己整理的小工具类(对于按比例缩放后,在此并未再进行质量缩放,此时图片大小有可能超出我们期望的限制;假如我们有严格的大小限制需求,可先进行按比例缩放后,判断此时图片大小是否超出限制;如果超出限制,对其再进行质量缩放即可。建议使用按比例缩放,按质量缩放很有可能导致图片失真。)

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. </pre><p><pre name="code" class="java">package com.util;  
  2.   
  3. import java.io.ByteArrayOutputStream;  
  4. import java.io.IOException;  
  5. import java.io.InputStream;  
  6.   
  7. import android.graphics.Bitmap;  
  8. import android.graphics.Matrix;  
  9. import android.graphics.Bitmap.CompressFormat;  
  10. import android.graphics.BitmapFactory;  
  11. import android.media.ExifInterface;  
  12.   
  13. /** 
  14.  * 图片压缩工具类 
  15.  *  
  16.  * @author 丶Life_ 
  17.  *  
  18.  */  
  19. public class ImageCompressUtil {  
  20.   
  21.     /** 
  22.      * 通过降低图片的质量来压缩图片 
  23.      *  
  24.      * @param bmp 
  25.      *            要压缩的图片位图对象 
  26.      * @param maxSize 
  27.      *            压缩后图片大小的最大值,单位KB 
  28.      * @return 压缩后的图片位图对象 
  29.      */  
  30.     public static Bitmap compressByQuality(Bitmap bitmap, int maxSize) {  
  31.         ByteArrayOutputStream baos = new ByteArrayOutputStream();  
  32.         int quality = 100;  
  33.         bitmap.compress(CompressFormat.JPEG, quality, baos);  
  34.         System.out.println("图片压缩前大小:" + baos.toByteArray().length + "byte");  
  35.         boolean isCompressed = false;  
  36.         while (baos.toByteArray().length / 1024 > maxSize) {  
  37.             quality -= 10;  
  38.             baos.reset();  
  39.             bitmap.compress(CompressFormat.JPEG, quality, baos);  
  40.             System.out.println("质量压缩到原来的" + quality + "%时大小为:"  
  41.                     + baos.toByteArray().length + "byte");  
  42.             isCompressed = true;  
  43.         }  
  44.         System.out.println("图片压缩后大小:" + baos.toByteArray().length + "byte");  
  45.         if (isCompressed) {  
  46.             Bitmap compressedBitmap = BitmapFactory.decodeByteArray(  
  47.                     baos.toByteArray(), 0, baos.toByteArray().length);  
  48.             recycleBitmap(bitmap);  
  49.             return compressedBitmap;  
  50.         } else {  
  51.             return bitmap;  
  52.         }  
  53.     }  
  54.   
  55.     /** 
  56.      * 传入图片url,通过压缩图片的尺寸来压缩图片大小
  57.      *  
  58.      * @param pathName  图片的完整路径 
  59.      * @param targetWidth  缩放的目标宽度 
  60.      * @param targetHeight 缩放的目标高度 
  61.      * @return 缩放后的图片 
  62.      */  
  63.     public static Bitmap compressBySize(String pathName, int targetWidth,  
  64.             int targetHeight) {  
  65.         BitmapFactory.Options opts = new BitmapFactory.Options();  
  66.         opts.inJustDecodeBounds = true;// 不去真的解析图片,只是获取图片的头部信息,包含宽高等;  
  67.         Bitmap bitmap = BitmapFactory.decodeFile(pathName, opts);  
  68.         // 得到图片的宽度、高度;  
  69.         int imgWidth = opts.outWidth;  
  70.         int imgHeight = opts.outHeight;  
  71.         // 分别计算图片宽度、高度与目标宽度、高度的比例;取大于等于该比例的最小整数;  
  72.         int widthRatio = (int) Math.ceil(imgWidth / (float) targetWidth);  
  73.         int heightRatio = (int) Math.ceil(imgHeight / (float) targetHeight);  
  74.         if (widthRatio > 1 || heightRatio > 1) {  
  75.             if (widthRatio > heightRatio) {  
  76.                 opts.inSampleSize = widthRatio;  
  77.             } else {  
  78.                 opts.inSampleSize = heightRatio;  
  79.             }  
  80.         }  
  81.         // 设置好缩放比例后,加载图片进内容;  
  82.         opts.inJustDecodeBounds = false;  
  83.         bitmap = BitmapFactory.decodeFile(pathName, opts);  
  84.         return bitmap;  
  85.     }  
  86.   
  87.     /** 
  88.      * 传入bitmap,通过压缩图片的尺寸来压缩图片大小 
  89.      *  
  90.      * @param bitmap  要压缩图片 
  91.      * @param targetWidth 缩放的目标宽度 
  92.      * @param targetHeight  缩放的目标高度 
  93.      * @return 缩放后的图片 
  94.      */  
  95.     public static Bitmap compressBySize(Bitmap bitmap, int targetWidth,  
  96.             int targetHeight) {  
  97.         ByteArrayOutputStream baos = new ByteArrayOutputStream();  
  98.         bitmap.compress(CompressFormat.JPEG, 100, baos);  
  99.         BitmapFactory.Options opts = new BitmapFactory.Options();  
  100.         opts.inJustDecodeBounds = true;  
  101.         bitmap = BitmapFactory.decodeByteArray(baos.toByteArray(), 0,  
  102.                 baos.toByteArray().length, opts);  
  103.         // 得到图片的宽度、高度;  
  104.         int imgWidth = opts.outWidth;  
  105.         int imgHeight = opts.outHeight;  
  106.         // 分别计算图片宽度、高度与目标宽度、高度的比例;取大于该比例的最小整数;  
  107.         int widthRatio = (int) Math.ceil(imgWidth / (float) targetWidth);  
  108.         int heightRatio = (int) Math.ceil(imgHeight / (float) targetHeight);  
  109.         if (widthRatio > 1 || heightRatio > 1) {  
  110.             if (widthRatio > heightRatio) {  
  111.                 opts.inSampleSize = widthRatio;  
  112.             } else {  
  113.                 opts.inSampleSize = heightRatio;  
  114.             }  
  115.         }  
  116.         // 设置好缩放比例后,加载图片进内存;  
  117.         opts.inJustDecodeBounds = false;  
  118.         Bitmap compressedBitmap = BitmapFactory.decodeByteArray(  
  119.                 baos.toByteArray(), 0, baos.toByteArray().length, opts);  
  120.         recycleBitmap(bitmap);  
  121.         return compressedBitmap;  
  122.     }  
  123.   
  124.     /** 
  125.      * 通过压缩图片的尺寸来压缩图片大小,通过读入流的方式,可以有效防止网络图片数据流形成位图对象时内存过大的问题; 
  126.      *  
  127.      * @param InputStream 要压缩图片,以流的形式传入 
  128.      * @param targetWidth 缩放的目标宽度 
  129.      * @param targetHeight 缩放的目标高度 
  130.      * @return 缩放后的图片 
  131.      * @throws IOException 读输入流的时候发生异常 
  132.      */  
  133.     public static Bitmap compressBySize(InputStream is, int targetWidth,  
  134.             int targetHeight) throws IOException {  
  135.         ByteArrayOutputStream baos = new ByteArrayOutputStream();  
  136.         byte[] buff = new byte[1024];  
  137.         int len = 0;  
  138.         while ((len = is.read(buff)) != -1) {  
  139.             baos.write(buff, 0, len);  
  140.         }  
  141.   
  142.         byte[] data = baos.toByteArray();  
  143.         BitmapFactory.Options opts = new BitmapFactory.Options();  
  144.         opts.inJustDecodeBounds = true;  
  145.         Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length,  
  146.                 opts);  
  147.         // 得到图片的宽度、高度;  
  148.         int imgWidth = opts.outWidth;  
  149.         int imgHeight = opts.outHeight;  
  150.         // 分别计算图片宽度、高度与目标宽度、高度的比例;取大于该比例的最小整数;  
  151.         int widthRatio = (int) Math.ceil(imgWidth / (float) targetWidth);  
  152.         int heightRatio = (int) Math.ceil(imgHeight / (float) targetHeight);  
  153.         if (widthRatio > 1 || heightRatio > 1) {  
  154.             if (widthRatio > heightRatio) {  
  155.                 opts.inSampleSize = widthRatio;  
  156.             } else {  
  157.                 opts.inSampleSize = heightRatio;  
  158.             }  
  159.         }  
  160.         // 设置好缩放比例后,加载图片进内存;  
  161.         opts.inJustDecodeBounds = false;  
  162.         bitmap = BitmapFactory.decodeByteArray(data, 0, data.length, opts);  
  163.         return bitmap;  
  164.     }  
  165.   
  166.     /** 
  167.      * 旋转图片摆正显示 
  168.      *  
  169.      * @param srcPath 
  170.      * @param bitmap 
  171.      * @return 
  172.      */  
  173.     public static Bitmap rotateBitmapByExif(String srcPath, Bitmap bitmap) {  
  174.         ExifInterface exif;  
  175.         Bitmap newBitmap = null;  
  176.         try {  
  177.             exif = new ExifInterface(srcPath);  
  178.             if (exif != null) { // 读取图片中相机方向信息  
  179.                 int ori = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION,  
  180.                         ExifInterface.ORIENTATION_NORMAL);  
  181.                 int digree = 0;  
  182.                 switch (ori) {  
  183.                 case ExifInterface.ORIENTATION_ROTATE_90:  
  184.                     digree = 90;  
  185.                     break;  
  186.                 case ExifInterface.ORIENTATION_ROTATE_180:  
  187.                     digree = 180;  
  188.                     break;  
  189.                 case ExifInterface.ORIENTATION_ROTATE_270:  
  190.                     digree = 270;  
  191.                     break;  
  192.                 }  
  193.                 if (digree != 0) {  
  194.                     Matrix m = new Matrix();  
  195.                     m.postRotate(digree);  
  196.                     newBitmap = Bitmap.createBitmap(bitmap, 00,  
  197.                             bitmap.getWidth(), bitmap.getHeight(), m, true);  
  198.                     recycleBitmap(bitmap);  
  199.                     return newBitmap;  
  200.                 }  
  201.             }  
  202.         } catch (IOException e) {  
  203.             e.printStackTrace();  
  204.         }  
  205.         return bitmap;  
  206.     }  
  207.   
  208.     /** 
  209.      * 回收位图对象 
  210.      *  
  211.      * @param bitmap 
  212.      */  
  213.     public static void recycleBitmap(Bitmap bitmap) {  
  214.         if (bitmap != null && !bitmap.isRecycled()) {  
  215.             bitmap.recycle();  
  216.             System.gc();  
  217.             bitmap = null;  
  218.         }  
  219.     }  
  220.   
  221. }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值