• 图片的压缩(二次采样)


      1 package com.qianfeng.bitmapdisplay.tasks;
      2 
      3 import android.graphics.Bitmap;
      4 import android.graphics.BitmapFactory;
      5 import android.graphics.drawable.Drawable;
      6 import android.os.AsyncTask;
      7 import android.widget.ImageView;
      8 import com.qianfeng.bitmapdisplay.cache.FileCache;
      9 import com.qianfeng.bitmapdisplay.utils.HttpTools;
     10 
     11 import java.lang.ref.WeakReference;
     12 
     13 /**
     14  * Created
     15  * Author: vhly[FR]
     16  * Email: vhly@163.com
     17  * Date: 2015/10/12
     18  */
     19 public class ImageLoadTask extends AsyncTask<String, Integer, Bitmap> {
     20 
     21     /**
     22      * 使用弱引用来进行ImageView对象的引用,当UI销毁,任务不再使用ImageView
     23      */
     24     private final WeakReference<ImageView> imageViewReference;
     25 
     26     /**
     27      * 加载的图片,最终显示的宽度
     28      */
     29     private int requestWidth;
     30 
     31     private int requestHeight;
     32 
     33     /**
     34      * 异步任务的构造
     35      *
     36      * @param imageView ImageView 需要显示的ImageView
     37      * @param reqWidth  请求的宽度 0 代表显示原始图像,> 0 将图像缩小
     38      * @param reqHeight 请求的高度 0 代表显示原始图像,> 0 将图像缩小
     39      */
     40     public ImageLoadTask(ImageView imageView, int reqWidth, int reqHeight) {
     41         imageViewReference = new WeakReference<ImageView>(imageView);
     42 
     43         requestWidth = reqWidth;
     44 
     45         requestHeight = reqHeight;
     46     }
     47 
     48     @Override
     49     protected Bitmap doInBackground(String... params) {
     50         Bitmap ret = null;
     51 
     52         if (params != null && params.length > 0) {
     53 
     54             String url = params[0];
     55 
     56             // 获取 url 对应的文件缓存
     57             byte[] data = FileCache.getInstance().load(url);
     58 
     59             if (data != null) {
     60                 // TODO 有文件数据,那么不需要联网
     61             } else {
     62                 // TODO 联网下载图片
     63                 data = HttpTools.doGet(url);
     64                 FileCache.getInstance().save(url, data);
     65             }
     66 
     67             if (data != null) {
     68 
     69 
     70                 // 按照原始的图片尺寸,进行Bitmap的生成,
     71                 // 按照Bitmap生成,是按照 图片原始宽高,进行生成,并且每一个像素占用四个字节 也就是 ARGB
     72                 // ret = BitmapFactory.decodeByteArray(data, 0, data.length);
     73 
     74 
     75                 // 采用二次采样(缩小图片尺寸的方式)
     76 
     77                 // 1. 步骤1 获取原始图片的宽高信息,用于进行采样的计算
     78 
     79                 // 1.1 创建 Options ,给BitmapFactory 的内部解码器传递参数
     80                 BitmapFactory.Options options = new BitmapFactory.Options();
     81 
     82                 // 1.2 设置 inJustDecodeBounds 来控制解码器,只进行图片宽高的获取,不会加载 Bitmap
     83                 //     不占用内存,当使用这个参数,代表 BitmapFactory.decodeXxxx 类似的方法,不会返回 Bitmap
     84                 options.inJustDecodeBounds = true;
     85 
     86                 // 解码,使用 Options 参数设置 解码方式
     87                 BitmapFactory.decodeByteArray(data, 0, data.length, options);
     88 
     89                 //------------------------------------------
     90 
     91                 // 2. 步骤2 根据图片的真实尺寸,与当前需要显示的尺寸,进行计算,生成图片采样率。
     92 
     93                 // 2.1
     94 
     95                 int picW = options.outWidth;   // 6000
     96                 int picH = options.outHeight;  // 4000
     97 
     98                 // 2.2 准备 显示在 手机上的尺寸。 256x128   128x64
     99                 //     尺寸是根据程序需要来设置的。
    100 
    101                 // maxWidth, maxHeight
    102                 int reqW = requestWidth;
    103 
    104                 int reqH = requestHeight;  // 测试数据
    105 
    106                 // 2.3 计算、设置 图片采样率
    107 
    108                 options.inSampleSize =
    109                         calculateInSampleSize(options, reqW, reqH);  // 宽度的 1/32  高度的 1/32
    110 
    111                 // 2.4 开放 解码,实际生成Bitmap
    112                 options.inJustDecodeBounds = false;
    113 
    114                 // 2.4.1 Bitmap.Config 的说明
    115                 // 要求解码器对于每一个采样的像素,使用 RGB_565 存储方式
    116                 // 一个像素,占用两个 字节;比 ARGB_8888 小了一半。
    117                 // 如果解码器不能够使用指定配置,就自动使用 ARGB_8888
    118                 options.inPreferredConfig = Bitmap.Config.RGB_565;
    119 
    120                 // 2.4.2 是一个过时的设置
    121                 options.inPurgeable = true;
    122 
    123                 // 2.5 使用设置采样的参数,来进行 解码,获取 Bitmap
    124                 ret = BitmapFactory.decodeByteArray(data, 0, data.length, options);
    125 
    126                 // data 需要显示释放
    127                 data = null;
    128 
    129             }
    130         }
    131 
    132         return ret;
    133     }
    134 
    135     @Override
    136     protected void onPostExecute(Bitmap bitmap) {
    137         if (bitmap != null) {
    138 
    139             // 获取弱引用包含的对象,可能为null
    140             ImageView imageView = imageViewReference.get();
    141 
    142             if (imageView != null) {
    143                 // 每一个图片都可以包含 AsyncDrawable对象
    144                 // 这个对象用于处理图片错位的
    145                 Drawable drawable = imageView.getDrawable();
    146 
    147                 if (drawable != null && drawable instanceof AsyncDrawable) {
    148                     // 用于检测图片错位
    149 
    150                     AsyncDrawable asyncDrawable = (AsyncDrawable) drawable;
    151 
    152                     ImageLoadTask task = asyncDrawable.getImageLoadTask();
    153 
    154                     // 当前ImageView 内部包含的 AsyncDrawable和当前
    155                     // 任务是对应的,代表 当前任务可以设置图片
    156                     if (this == task) {
    157                         imageView.setImageBitmap(bitmap);
    158                     }
    159 
    160                 } else { // 不用检测 图片错位的情况
    161                     imageView.setImageBitmap(bitmap);
    162                 }
    163             }
    164 
    165         }
    166     }
    167 
    168     /**
    169      * 计算图片二次采样的采样率,使用获取图片宽高之后的 Options 作为第一个参数;
    170      * 并且,通过请求的 宽度、高度尺寸,进行采样率的计算;
    171      *
    172      * @param options
    173      * @param reqWidth  请求的宽度
    174      * @param reqHeight 请求的高度
    175      * @return int 采样率
    176      */
    177     public static int calculateInSampleSize(
    178             BitmapFactory.Options options, int reqWidth, int reqHeight) {
    179         // Raw height and width of image
    180         final int height = options.outHeight;
    181         final int width = options.outWidth;
    182         int inSampleSize = 1;
    183 
    184         // 当请求的宽度、高度 > 0 时候,进行缩放,
    185         // 否则,图片不进行缩放;
    186         if (reqWidth > 0 && reqHeight > 0) {
    187             if (height > reqHeight || width > reqWidth) {
    188 
    189                 final int halfHeight = height / 2;
    190                 final int halfWidth = width / 2;
    191 
    192                 // Calculate the largest inSampleSize value that is a power of 2 and keeps both
    193                 // height and width larger than the requested height and width.
    194                 while ((halfHeight / inSampleSize) >= reqHeight
    195                         && (halfWidth / inSampleSize) >= reqWidth) {
    196                     inSampleSize *= 2;
    197                 }
    198             }
    199         }
    200 
    201         return inSampleSize;
    202     }
    203 
    204 }
    View Code

    上面的是  比较正规具体的压缩方式  decodeByteArray

    下边的是比较快捷的方式   decodeFile

    private void resizePhoto() {
    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;  //此属性为true的时候  只把bitmap的宽和高加载出来  并不把图片加载到内存

    BitmapFactory.decodeFile(mcurrentPhotoPath, options);

    double ratio = Math.max(options.outWidth*1.0d/1024 , options.outHeight*1.0d/1024);

    options.inSampleSize = (int)Math.ceil(ratio);

    options.inJustDecodeBounds = false;  //此属性为false的时候  把图片加载到内存

    mphotoImage = BitmapFactory.decodeFile(mcurrentPhotoPath, options);
    }

    上边主要是对图片大小的压缩  下边是对质量的压缩

    //质量压缩    这种方式的压缩 是针对压缩到磁盘的file文件会变小  但是加载在内存的bitmap大小是不会变的
    //上边的尺寸压缩 是针对加载到内存的Bitmap是会变小的,但是磁盘上的file大小是不会变的 只是读取时候按照小的 比例 去读取而已
    public static Bitmap compressImage(Bitmap image, int size) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); image.compress(Bitmap.CompressFormat.JPEG, 100, baos);//质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中 int options = 100; while ( baos.toByteArray().length / 1024>50) { //循环判断如果压缩后图片是否大于50kb,大于继续压缩 baos.reset();//重置baos即清空baos image.compress(Bitmap.CompressFormat.JPEG, options, baos);//这里压缩options%,把压缩后的数据存放到baos中 options -= 10;//每次都减少10 } ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());//把压缩后的数据baos存放到ByteArrayInputStream中 Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);//把ByteArrayInputStream数据生成图片 return bitmap; }
  • 相关阅读:
    python: 字符串按空格分成列表split与加密密码maketrans
    android 几个工具方法
    华硕N43sl VNP 连接问题 800 807 621
    git 创建新项目,下载工程,合并和更新工程简单应用记录
    android分析windowManager、window、viewGroup之间关系(二)
    android分析windowManager、window、viewGroup之间关系(一)
    meta-data获取小结
    转载: 项目经验分享
    不想写代码了
    MapReduce源码分析总结(转)
  • 原文地址:https://www.cnblogs.com/bimingcong/p/4943659.html
Copyright © 2020-2023  润新知