Drawable 与 Bitmap

Drawable

作为Android平下通用的图形对象,它可以装载常用格式的图像,比如GIF、PNG、JPG,当然也支持BMP,当然还提供一些高级的可视化对象,比如渐变、图形等

Bitmap

称作位图,一般位图的文件格式后缀为bmp,当然编码器也有很多如RGB565、RGB888。作为一种逐像素的显示对象执行效率高,但是缺点也很明显存储效率低。我们理解为一种存储对象比较好。

Bitmap 格式类型

  • ALPHA_8

表示8位Alpha位图,即A=8,一个像素点占用1个字节,它没有颜色,只有透明度

  • ARGB_4444

表示16位ARGB位图,即A=4,R=4,G=4,B=4,一个像素点占4+4+4+4=16位,2个字节

  • ARGB_8888

表示32位ARGB位图,即A=8,R=8,G=8,B=8,一个像素点占8+8+8+8=32位,4个字节

  • RGB_565

表示16位RGB位图,即R=5,G=6,B=5,它没有透明度,一个像素点占5+6+5=16位,2个字节

图片压缩

质量压缩(compress)

压缩bitmap到目标大小
    原理:保持像素的前提下改变图片的位深及透明度,只影响file的大小,加载这个图片出来的bitmap内存是无法节省的
    使用场景:将图片压缩后将图片上传到服务器,或者保存到本地
    代码:
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);

等比压缩(createBitmap)

原理:通过减少单位尺寸的像素值,真正意义上的降低像素
    使用场景:缓存缩略图的时候(头像处理)
    其实ThumbnailUtils.extractThumbnail()获取缩略图就是这种压缩方式;
    代码:

    float sourceWidth = bitmap.getWidth();float sourceHeight = bitmap.getHeight();float scaleWidth = targetWidth / sourceWidth;float scaleHeight = targetHeight / sourceHeight;Matrix matrix = new Matrix();matrix.postScale(scaleWidth, scaleHeight); //长和宽放大缩小的比例Bitmap bm = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
采样率压缩(option.inSimpleSize)

原理:设置图片的采样率,降低图片像素
     好处:是不会先将大图片读入内存,大大减少了内存的使用,也不必考虑将大图片读入内存后的释放事宜
     不足:问题:因为采样率是整数,所以不能很好的保证图片的质量。
     代码:

final BitmapFactory.Options options = new BitmapFactory.Options();//预加载,只加载宽高不加载bitmap,不占内存options.inJustDecodeBounds = true;BitmapFactory.decodeFile(imageFile, options); //加载图片信息int sourceWidth = options.outWidth;int sourceHeight = options.outHeight;options.inJustDecodeBounds = false;//计算inSampleSizeint inSampleSize = 1;//先根据宽度进行缩小while (sourceWidth / inSampleSize > targetWidth) {inSampleSize++;}//然后根据高度进行缩小while (sourceHeight / inSampleSize > targetHeight) {inSampleSize++;}if (inSampleSize <= 0) {inSampleSize = 1;}options.inSampleSize = inSampleSize;Bitmap bitmap = BitmapFactory.decodeFile(imageFile, options);//加载真正bitmap
位图格式压缩(RGB_565)
BitmapFactory.Options options = new BitmapFactory.Options();options.inPreferredConfig = Bitmap.Config.RGB_565;  //将格式设置成RGB_565bm = BitmapFactory.decodeFile(Environment.getExternalStorageDirectory().getAbsolutePath()+ "/DCIM/Camera/test.jpg", options);

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

android 几种常用图片框架的使用注意点

Glide默认加载图片时是通过将图片转换成ImageView的大小后再加
    默认的Bitmap格式就是RGB_565
    Picasso默认是加载了全尺寸的图片到内存,然后让GPU来实时重绘大小(也可以手动设置或者将scaletype设置成   centerCrop等);
    默认格式Bitmap格式就是ARGB_8888
    重点的Fresco来了:
    对于5.0以下系统,fresco使用”ashmem”(匿名共享内存)区域存储Bitmap缓存,这样Bitmap对象的创建、释放将不会触发GC,不会占用javaheap. 这个特点是其他图片加载框架所没有做到的.
    5.0以上系统,由于安卓系统本身内存管理的优化,所以对于5.0以上的系统Fresco将Bitmap缓存直接放到了javaheap内存中.
    并且,fresco实现了真正的三级缓存:两级的内存缓存+一个磁盘缓存.两个内存缓存为:bitmap缓存 和未解码的图片缓存,这样既可以加快图片的加载速度,又能节省内存的占用.这个两级的内存缓存也是其他图片加载框架所没有做到的.
    另外提一点,在app切换到后台时,fresco会自动清理两级的内存缓存,无需手动.
###### 补充:加载超级大图还是会卡
终极的解决方法肯定是,客户端在图片请求中带上需要的宽和高,服务器将图片缩略到该规格后返回该小图.这个做得比较好的是七牛.
但是如果服务端控制不了,如果服务器只能拿到原图或大图,fresco怎么缩略显示?
fresco中提供了三个功能来生成缩略图:

    Scaling :画布操作,通常是由硬件加速的。图片实际大小保持不变,它只不过在绘制时被放大或缩小.使用时需要配置缩放类型fresco:actualImageScaleType,具体类型名与Imageview的ScaleType几乎一样. 
    Resizing 是一种软件执行的管道操作。它返回一张新的,尺寸不同的图片,也就是说直接改变bitmap的大小,可惜是单独使用时,只支持jpg,当然,结合Downsampling使用时,可以支持除gif以为的所有常见图片,包括webp.
    Downsampling 同样是软件实现的管道操作。它不是创建一张新的图片,而是在解码时改变图片的大小。 同样是软件实现的管道操作。它不是创建一张新的图片,而是在解码时改变图片的大小。类似于android中的BitmapFactory在decodefile时的inSampleSize,都是指定一个采样率,默认是关闭的,如果开启,那么需要结合Resizing来使用.
综上,要缩小内存占用,以及减少cpu计算量,减少卡顿,应该是Downsampling结合Resizing来使用.其中Downsampling是在Fresco初始化时开启,而Resizing则是通过构建ImageRequest时通过制定宽高来实现,所以可以定制每一张或每一类图片的宽高.(对gif无效)

示例代码如下:

 /**     * 初始化操作,建议在子线程中进行
     * 添加的依赖:* compile 'com.facebook.fresco:fresco:0.10.0+'* compile 'com.facebook.fresco:animated-webp:0.10.0'* compile 'com.facebook.fresco:animated-gif:0.10.0'** @param context* @param cacheSizeInM 磁盘缓存的大小,以M为单位*/public static void init(final Context context, final int cacheSizeInM) {AsyncTask.SERIAL_EXECUTOR.execute(new Runnable() {@Overridepublic void run() {DiskCacheConfig diskCacheConfig = DiskCacheConfig.newBuilder(context).setMaxCacheSize(cacheSizeInM * ByteConstants.MB).setBaseDirectoryName(PHOTO_FRESCO).setBaseDirectoryPathSupplier(new Supplier<File>() {@Overridepublic File get() {return context.getCacheDir();}}).build();MyImageCacheStatsTracker imageCacheStatsTracker = new MyImageCacheStatsTracker();ImagePipelineConfig config = ImagePipelineConfig.newBuilder(context).setMainDiskCacheConfig(diskCacheConfig).setImageCacheStatsTracker(imageCacheStatsTracker).setDownsampleEnabled(true)//Downsampling,它处理图片的速度比常规的裁剪更快,// 并且同时支持PNG,JPG以及WEP格式的图片,非常强大,与ResizeOptions配合使用.setBitmapsConfig(Bitmap.Config.RGB_565)//如果不是重量级图片应用,就用这个省点内存吧.默认是RGB_888.build();Fresco.initialize(context, config);}});}   
 public static void load(Uri uri,SimpleDraweeView draweeView,BasePostprocessor processor,int width,int height,BaseControllerListener listener){ImageRequest request =ImageRequestBuilder.newBuilderWithSource(uri).setPostprocessor(processor).setResizeOptions(new ResizeOptions(width,height))//缩放,在解码前修改内存中的图片大小, 配合Downsampling可以处理所有图片,否则只能处理jpg,// 开启Downsampling:在初始化时设置.setDownsampleEnabled(true).setProgressiveRenderingEnabled(true)//支持图片渐进式加载.setAutoRotateEnabled(true) //如果图片是侧着,可以自动旋转.build();PipelineDraweeController controller =(PipelineDraweeController) Fresco.newDraweeControllerBuilder().setImageRequest(request).setControllerListener(listener).setOldController(draweeView.getController()).setAutoPlayAnimations(true) //自动播放gif动画.build();draweeView.setController(controller);}

补充

图片上传(推荐使用鲁班,最接近微信的图片压缩方式)https://github.com/Curzibn/Luban

文件下载(推荐FileDownloader)https://github.com/lingochamp/FileDownloader

参考博客:Fresco的封装以及优化https://blog.csdn.net/hss01248/article/details/51757989

android 图片优化相关推荐

  1. Android图片优化--使用webp

    在炎热的七月,偶然被邻桌的同事喊了一下.嘿,过来看个东西.于是我伸着脖子过去看了一下. 他说"我发现一个androidStuido很屌的功能,可以把500kb的图片压缩到22kb" ...

  2. Android 系统性能优化(55)---Android 性能优化之内存优化

    Android 性能优化之内存优化 前言 Android App优化这个问题,我相信是Android开发者一个永恒的话题.本篇文章也不例外,也是来讲解一下Android内存优化.那么本篇文章有什么不同 ...

  3. Android性能优化之图片压缩优化

    1 分类 Android图片压缩结合多种压缩方式,常用的有尺寸压缩.质量压缩.采样率压缩以及通过JNI调用libjpeg库来进行压缩. 参考此方法:Android-BitherCompress 备注: ...

  4. 【Android 内存优化】Android 工程中使用 libjpeg-turbo 压缩图片 ( 初始化压缩对象 | 打开文件 | 设置压缩参数 | 写入压缩图像数据 | 完成压缩 | 释放资源 )

    文章目录 一.使用 libjpeg-turbo 压缩图片流程 二.初始化 JPEG 压缩对象 三.打开文件 四.设置压缩参数 五.开始压缩 六.循环写入压缩数据 七.完成图片压缩及收尾 八.libjp ...

  5. 【Android 内存优化】Android 工程中使用 libjpeg-turbo 压缩图片 ( JNI 传递 Bitmap | 获取位图信息 | 获取图像数据 | 图像数据过滤 | 释放资源 )

    文章目录 一.Bitmap 图像数据处理 二.Java 层 Bitmap 对象转为 JNI 层 bitmap 对象 三.获取 bitmap 中的图像数据 四.过滤 bitmap 中的图像数据 ( 获取 ...

  6. 【Android 内存优化】Android 原生 API 图片压缩原理 ( 哈夫曼编码开关 | 哈夫曼编码原理 | libjpeg-turbo 函数库 )

    文章目录 一. 哈夫曼编码开关 二. 哈夫曼编码原理 三. libjpeg-turbo 函数库 四. libjpeg-turbo 函数库下载 [Android 内存优化]图片文件压缩 ( Androi ...

  7. 【Android 内存优化】Android 原生 API 图片压缩原理 ( Bitmap_compress 方法解析 | Skia 二维图形库 | libjpeg 函数库 | libpng 函数库 )

    文章目录 一. 图片质量压缩方法 二. Skia 二维图形库 三. libjpeg.libpng 函数库引入 在博客 [Android 内存优化]图片文件压缩 ( Android 原生 API 提供的 ...

  8. 【Android 内存优化】Android 原生 API 图片压缩原理 ( 图片质量压缩方法 | 查找 Java 源码中的 native 方法对应的 C++ 源码 )

    文章目录 一. 图片质量压缩方法 二. 查找对应的 Native 方法源码 三. 分析 Bitmap.cpp 中动态注册 Native 方法 在博客 [Android 内存优化]图片文件压缩 ( An ...

  9. 【Android 内存优化】Android 原生 API 图片压缩代码示例 ( PNG 格式压缩 | JPEG 格式压缩 | WEBP 格式压缩 | 动态权限申请 | Android10 存储策略 )

    文章目录 一. 图片质量压缩 二. 图片尺寸压缩 三. Android 10 文件访问 四. 完整源码示例 上一篇博客 [Android 内存优化]图片文件压缩 ( Android 原生 API 提供 ...

最新文章

  1. 嵌入式linux和嵌入式android系统有什么区别和联系?
  2. python中打开文件提示编码当时错误_Python:文件编码错误
  3. mysql url格式,关于MySql链接url参数的设置
  4. python 完全面向对象_Python面向对象
  5. 经典高清C语言 The C Programming Language
  6. window下安装mysql
  7. C#中奇怪的Queue T 行为!
  8. 高质量发展-协调发展指标体系构建及测算
  9. sai笔记5-详细上色教程(适合有耐心的观众)
  10. 06MyBatis Plus
  11. Octotree在GitHub中出错(已解决)
  12. 【简易搭建个人博客】------- 基于BT面板的个人博客搭建
  13. flink 消费 kafka offset 自动提交
  14. 计算机收藏夹位于哪个磁盘,电脑浏览器收藏夹保存在哪里
  15. nyoj 1的个数 514 (数学)
  16. 安利一个在线画UML图的网址
  17. 【微电网优化】基于matlab粒子群算法求解综合能源系统优化问题【含Matlab源码 1969期】
  18. input type=number 禁止输入E
  19. 操作系统实验四-LRU算法的模拟
  20. 赵文婧:深入了解 Azure 云平台容器技术服务

热门文章

  1. 服务器返回的响应数据无效,Ant Design Pro 5 网络请求和错误处理
  2. 016 Java中 int、Integer和 new Integer() 使用==比较
  3. 前后端配合实现密码找回功能
  4. 动画程序时长缩放是什么意思_看《魔法少女伊莉雅》学知识:动画中所说的“轴线”是什么意思?...
  5. 如何用adb命令启动你的Android程序
  6. mysql 查看僵死的进程_如何查看并杀死僵死进程
  7. 什么才是好的企业云盘
  8. C++特色家政服务管理系统
  9. 【新闻资讯】HackRF SuperCluster:用八个HackRF接收星链的信标信号
  10. git报错:Permission denied (publickey).