Android Bitmap压缩方法的选择详解

刚刚修改Bug碰到了一个问题,先描述一下问题。

1.测试说分享文章到微信失败,QQ成功。

定位到微信分享接口。

2.分享其它文章到微信成功。

接口有问题!差点就找接口了,还好没

3.断点微信分享,发现突然压缩失败。

代码写法问题,下面会分解

4.找到原因,微信对分享缩略图大小有32k的限制,代码是对文章的第一张图片进行压缩,图片太大,压缩代码也有问题。

开始解决问题

这里有两种解决方法:
1.接口提供文章对应的分享内容,在编辑人员编辑文章的时候就对这些数据进行了限制。

{
  "title":"how to begain Android?",
  "content":"do it, do it, do it",
  "picture":"http://192.168.0.1/pic/2015/09/02/share_thumb.jpg"
  ...
  ...
}

picture字段是<32K的缩略图。

ps:就我现在的水平来说,个人觉得这种是最好的,不是说Android省事,而是对于今后的扩展和整体项目的扩展规划来说都是比较好的,当然,水平有限,也许我看得还不够远,希望指教。

2.对获取的文章图片进行压缩。

当前项目无法对接口进行修改(骆驼太大了),所以只能对图片进行压缩了,这就谈到上面的坑了。先看原来写的压缩代码:

----可能出错的代码----

int options = 100; 

ByteArrayOutputStream outputs = new ByteArrayOutputStream();
oBitmap.compress(Bitmap.CompressFormat.JPEG, options, outputs); //

while ( outputs.toByteArray().length / 1024 > 32 ) {
  outputs.reset();
  oBitmap.compress(Bitmap.CompressFormat.JPEG, options, outputs);
  options -= 10 ;
}

ByteArrayInputStream inputs = new ByteArrayInputStream(outputs.toByteArray());
Bitmap bitmap = BitmapFactory.decodeStream(inputs, null , null );

这里用了bitmap的compress()方法进行了所谓的'质量压缩',控制参数就是options的值,但是出问题的地方也就是这个options的值,当图片非常大的时候,即使options为0的时候,图片还是大于32K,这个时候在while中option就为负数了,再进行compress()操作就会抛出throw new IllegalArgumentException("quality must be 0..100");的错误。

原因:

使用compress()方法的options值进行压缩的方法是不会丢失像素的,只是通过修改图片的其它比如透明度等属性,使得图片大小变化而已,所以它就无法无限压缩,到达一个值之后就不会继续变小了。

解决:

第一时间想到的是进行质量压缩后,当options为0的时候,还是大于32K的话,就进行采样率压缩。

BitmapFactory.Options newOpts = new BitmapFactory.Options();
newOpts.inSampleSize = 2;
bitmap = BitmapFactory.decodeFile(picturePath, newOpts);

每次判断bitmap的大小,对BitmapFactory.Options的inSampleSize进行+1或者-1(不能小于1)操作就好。但是inSampleSize的值为int类型,当图片很大的时候,1/2, 1/3, 1/4的差距还是有些大。所以只能放弃,最后采用了缩放的方法,先上代码:

public static byte[] WeChatBitmapToByteArray(Bitmap bmp, boolean needRecycle) {

  // 首先进行一次大范围的压缩

  ByteArrayOutputStream output = new ByteArrayOutputStream();
  bmp.compress(Bitmap.CompressFormat.JPEG, 100, output);
  float zoom = (float)Math.sqrt(32 * 1024 / (float)output.toByteArray().length); //获取缩放比例

  // 设置矩阵数据
  Matrix matrix = new Matrix();
  matrix.setScale(zoom, zoom); 

  // 根据矩阵数据进行新bitmap的创建
  Bitmap resultBitmap = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), matrix, true);

  output.reset();

  resultBitmap.compress(Bitmap.CompressFormat.JPEG, 100, output);

  // 如果进行了上面的压缩后,依旧大于32K,就进行小范围的微调压缩
  while(output.toByteArray().length > 32 * 1024){
    matrix.setScale(0.9f, 0.9f);//每次缩小 1/10

    resultBitmap = Bitmap.createBitmap(
                  resultBitmap, 0, 0,
                  resultBitmap.getWidth(), resultBitmap.getHeight(), matrix,true);

    output.reset();
    resultBitmap.compress(Bitmap.CompressFormat.JPEG, 100, output);
  }

  return result;
}

至此,暂时补上了这个一开始不规范导致的问题。当然,以上的解释都是从书本和我大互联网中获取的方法,我进行了一些整合,如果你也遇到的这个问题,也有幸这篇文章被你看到,能帮到一二,就是我的本意了。

通过此文希望能帮助到有需要的同学,谢谢大家对本站的支持!

(0)

相关推荐

  • Android中把bitmap存成BMP格式图片的方法

    最近的项目,做图片的另存为功能,需要把图片存成jpg,png,bmp.对于jpg和png来说相对简单,android提供了bitmap.compress()方法可以马上解决.但是对于BMP这种格式,没有很好的支持.我花了几天时间在网上找了很久,都没有找到有用的答案,同样也发了疑问,没有合适的解答. package com.test.bitmap; import java.io.FileNotFoundException; import java.io.FileOutputStream; impo

  • Android实现图片压缩(bitmap的六种压缩方式)

    Android中图片是以bitmap形式存在的,那么bitmap所占内存,直接影响到了应用所占内存大小,首先要知道bitmap所占内存大小计算方式: 图片长度 x 图片宽度 x 一个像素点占用的字节数 以下是图片的压缩格式: 其中,A代表透明度:R代表红色:G代表绿色:B代表蓝色. 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个

  • Android中使用Bitmap类将矩形图片转为圆形的方法

    一般要做正圆形图片,只能是正方形的基础上才能实现,否则就变成椭圆了,下面说说如何使长方形的图片生成正圆形图片 废话不多说,没图没真相,先上图吧: 原图: 变成正圆后: 下面上代码: public static Bitmap makeRoundCorner(Bitmap bitmap) { int width = bitmap.getWidth(); int height = bitmap.getHeight(); int left = 0, top = 0, right = width, bot

  • Android App开发中将View或Drawable转为Bitmap的方法

    View转换为Bitmap Android中经常会遇到把View转换为Bitmap的情形,比如,对整个屏幕视图进行截屏并生成图片:Coverflow中需要把一页一页的view转换为Bitmap.以便实现复杂的图形效果(阴影.倒影效果等):再比如一些动态的实时View为便于观察和记录数据.需要临时生成静态的Bitmap. 实现方法: 1)下面是笔者经常用的一个转换方法 public static Bitmap convertViewToBitmap(View view, int bitmapWid

  • Android利用BitMap获得图片像素数据的方法

    本文实例讲述了Android利用BitMap获得图片像素数据的方法.分享给大家供大家参考,具体如下: 网上看到的参考是: int[] pixels = new int[bit.getWidth()*bit.getHeight()];//保存所有的像素的数组,图片宽×高 bit.getPixels(pixels,0,bit.getWidth(),0,0,bit.getWidth(),bit.getHeight()); for(int i = 0; i < pixels.length; i++){

  • Android canvas drawBitmap方法详解及实例

     Android canvas drawBitmap方法详解及实例 之前自己在自定义view,用到canvas.drawBitmap(Bitmap, SrcRect, DesRect, Paint)的时候,对其中的第2和3个参数的含义含糊不清.看源码函数也没理解,然后看了一些其他的博客加上自己的理解,整理如下.首先,我们看一张图片,今天就要绘制这张图片. 然后将图片用红色的线条分成4个部分,如下: 我们自定义一个View,代码如下: public class PoterDuffLoadingVi

  • 解析Android中View转换为Bitmap及getDrawingCache=null的解决方法

    1.前言 Android中经常会遇到把View转换为Bitmap的情形,比如,对整个屏幕视图进行截屏并生成图片:Coverflow中需要把一页一页的view转换为Bitmap.以便实现复杂的图形效果(阴影.倒影效果等):再比如一些动态的实时View为便于观察和记录数据.需要临时生成静态的Bitmap. 2.实现方法 1)下面是笔者经常用的一个转换方法 public static Bitmap convertViewToBitmap(View view, int bitmapWidth, int

  • Android中将Bitmap对象以PNG格式保存在内部存储中的方法

    在Android中进行图像处理的任务时,有时我们希望将处理后的结果以图像文件的格式保存在内部存储空间中,本文以此为目的,介绍将Bitmap对象的数据以PNG格式保存下来的方法. 1.添加权限 由于是对SD card进行操作,必不可少的就是为你的程序添加读写权限,需要添加的内容如下: <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>

  • Android自定义view实现圆形、圆角和椭圆图片(BitmapShader图形渲染)

    一.前言 Android实现圆角矩形,圆形或者椭圆等图形,一般主要是个自定义View加上使用Xfermode实现的.实现圆角图片的方法其实不少,常见的就是利用Xfermode,Shader.本文直接继承ImageView,使用BitmapShader方法来实现圆形.圆角和椭圆的绘制,等大家看我本文的方法后,其他的类似形状也就都能举一反三来来画出来了. 二.效果图: 三.BitmapShader简介 BitmapShader是Shader的子类,可以通过Paint.setShader(Shader

  • Android Bitmap压缩方法的选择详解

    刚刚修改Bug碰到了一个问题,先描述一下问题. 1.测试说分享文章到微信失败,QQ成功. 定位到微信分享接口. 2.分享其它文章到微信成功. 接口有问题!差点就找接口了,还好没 3.断点微信分享,发现突然压缩失败. 代码写法问题,下面会分解 4.找到原因,微信对分享缩略图大小有32k的限制,代码是对文章的第一张图片进行压缩,图片太大,压缩代码也有问题. 开始解决问题 这里有两种解决方法: 1.接口提供文章对应的分享内容,在编辑人员编辑文章的时候就对这些数据进行了限制. { "title"

  • Eclipse工程转为兼容Android Studio模式的方法步骤图文详解

    方法/步骤 准备好需要转换的工程 , 最好是新建一个文件夹 , 然后将主工程和依赖工程放到同一个目录 屏幕快照 2016-12-24 12.43.02.png 在eclipse中导入主工程和依赖工程 , 导入之后最好先跑一遍 , 确定没有问题再继续操作 屏幕快照 2016-12-24 12.40.03.png 在主工程上右键导出 屏幕快照 2016-12-24 12.53.51.png 将工程导出为Generate Gradle build files , 这一步很重要哦 , 只有导出为这个模式

  • Android ListView里控件添加监听方法的实例详解

    Android ListView里控件添加监听方法的实例详解 关于ListView,算是android中比较常见的控件,在ListView我们通常需要一个模板,这个模板指的不是住模块,而是配置显示在ListView里面的东西,今天做项目的时候发现想要添加一个ImageView监听方法,发现崩了,也许是好久没有动ListView竟然忘了不能直接在主UI的xml文件里面调用其他xml文件的控件,哪怕ListView用的是这个xml文件. [错误示范]: 直接调用ImageView这个控件是ListV

  • Android性能优化大图治理示例详解

    目录 引言 1 自定义大图View 1.1 准备工作 1.2 图片宽高适配 1.3 BitmapRegionDecoder 2 大图View的手势事件处理 2.1 GestureDetector 2.2 双击放大效果处理 2.3 手指放大效果处理 引言 在实际的Android项目开发中,图片是必不可少的元素,几乎所有的界面都是由图片构成的:像列表页.查看大图页等,都是需要展示图片,而且这两者是有共同点的,列表展示的Item数量多,如果全部加载进来势必会造成OOM,因此列表页通常采用分页加载,加上

  • Android中mvp模式使用实例详解

    MVP 是从经典的模式MVC演变而来,它们的基本思想有相通的地方:Controller/Presenter负责逻辑的处理,Model提供数据,View负 责显示.作为一种新的模式,MVP与MVC有着一个重大的区别:在MVP中View并不直接使用Model,它们之间的通信是通过Presenter (MVC中的Controller)来进行的,所有的交互都发生在Presenter内部,而在MVC中View会从直接Model中读取数据而不是通过 Controller. 在MVC里,View是可以直接访问

  • Android Bluetooth蓝牙技术使用流程详解

    在上篇文章给大家介绍了Android Bluetooth蓝牙技术初体验相关内容,感兴趣的朋友可以点击了解详情. 一:蓝牙设备之间的通信主要包括了四个步骤 设置蓝牙设备 寻找局域网内可能或者匹配的设备 连接设备 设备之间的数据传输 二:具体编程实现 1. 启动蓝牙功能 首先通过调用静态方法getDefaultAdapter()获取蓝牙适配器BluetoothAdapter,如果返回为空,则无法继续执行了.例如: BluetoothAdapter mBluetoothAdapter = Blueto

  • Android 网络请求框架Volley实例详解

    Android 网络请求框架Volley实例详解 首先上效果图 Logcat日志信息on Reponse Volley特别适合数据量不大但是通信频繁的场景,像文件上传下载不适合! 首先第一步 用到的RequetQueue RequestQueue.Java RequestQueue请求队列首先得先说一下,ReuqestQueue是如何对请求进行管理的...RequestQueue是对所有的请求进行保存...然后通过自身的start()方法开启一个CacheDispatcher线程用于缓存调度,开

  • Android ListView之EfficientAdapte的使用详解

    Android ListView之EfficientAdapte的使用详解 在做Android手机应用开发时, ListView是一个非常常用的控件.如何更新的使用它呢?其实SDK中的例子已经非常的完整了,并且能满足大多数的需要. 如果大家刚开始学习ListView,我建议大家还是直接先看官方的例子好了,这样大家会学到更好的写法以及养成更好的习惯. 下面就以EfficientAdapter为例,看看官网例子是如何使用ListView的: 请大家格外注意getView的书写方法,大家可能从网上也能

  • Android Studio开发环境搭建教程详解

    对于移动端这块,笔者之前一直都是进行iOS开发的,也从来没用过Java.但是因为进入了Google Android全国大学生移动互联网创新挑战赛(进入官网)的总决赛(笔者"西部计算机教育提升计划"的项目被直接推荐进入决赛),这个比赛要求一定要提交apk程序,所以我不得不赶紧学习一下Android开发了. 下面就对自己学习的过程做一个记录. 一.安装Android Studio 笔者用的计算机配置如下: Mac下安装Android Studio应该更简单一些,只需要下载一个Android

  • Android常用的数据加密方式代码详解

    前言 Android 很多场合需要使用到数据加密,比如:本地登录密码加密,网络传输数据加密,等.在android 中一般的加密方式有如下: 亦或加密  AES加密  RSA非对称加密  MD5加密算法 当然还有其他的方式,这里暂且介绍以上四种加密算法的使用方式. 亦或加密算法 什么是亦或加密? 亦或加密是对某个字节进行亦或运算,比如字节 A^K = V,这是加密过程; 当你把 V^K得到的结果就是A,也就是 V^K = A,这是一个反向操作过程,解密过程. 亦或操作效率很高,当然亦或加密也是比较

随机推荐