zoukankan      html  css  js  c++  java
  • Bitmap 的几种压缩方式

    微信的缩略图要求是不大于32k,这就需要对我的图片进行压缩。试了几种方法,一一道来。

    代码如下

    1.         ByteArrayOutputStream baos =  new  ByteArrayOutputStream();  
    2.         image.compress(Bitmap.CompressFormat.JPEG,  100 , baos);
    3.          int  options =  100 ;  
    4.          while  ( baos.toByteArray().length /  1024 > 32 ) {  
    5.             baos.reset();
    6.             image.compress(Bitmap.CompressFormat.JPEG, options, baos);
    7.             options -=  10 ;
    8.         }  
    9.         ByteArrayInputStream isBm =  new  ByteArrayInputStream(baos.toByteArray());  
    10.         Bitmap bitmap = BitmapFactory.decodeStream(isBm,  null ,  null );

    最开始使用这个来进行压缩,但是始终压缩不到32k这么小。后来看高手的解释才明白,这种压缩方法之所以称之为质量压缩,是因为它不会减少图片的像素。它 是在保持像素的前提下改变图片的位深及透明度等,来达到压缩图片的目的。进过它压缩的图片文件大小会有改变,但是导入成bitmap后占得内存是不变的。 因为要保持像素不变,所以它就无法无限压缩,到达一个值之后就不会继续变小了。显然这个方法并不适用与缩略图,其实也不适用于想通过压缩图片减少内存的适 用,仅仅适用于想在保证图片质量的同时减少文件大小的情况而已。

    2、采样率压缩法:

    代码如下

    1.         ByteArrayOutputStream out = new ByteArrayOutputStream();
    2. image.compress(Bitmap.CompressFormat.JPEG, 100, out);
    3. BitmapFactory.Options newOpts =  new  BitmapFactory.Options();  
    4. int be = 2;
    5.         newOpts.inSampleSize = be; 
    6.          ByteArrayInputStream isBm =  new  ByteArrayInputStream(out.toByteArray());   
    7. Bitmap bitmap = BitmapFactory.decodeStream(isBm,  null ,  null );

    第二个使用的是这个方法,可以将图片压缩到足够小,但是也有一些问题。因为采样率是整数,所以不能很好的保证图片的质量。如我们需要的是在2和 3采样率之间,用2的话图片就大了一点,但是用3的话图片质量就会有很明显的下降。这样也无法完全满足我的需要。不过这个方法的好处是大大的缩小了内存的 使用,在读存储器上的图片时,如果不需要高清的效果,可以先只读取图片的边,通过宽和高设定好取样率后再加载图片,这样就不会过多的占用内存。如下

    1.         BitmapFactory.Options newOpts =  new  BitmapFactory.Options();    
    2.         newOpts.inJustDecodeBounds =  true ;  
    3.         Bitmap bitmap = BitmapFactory.decodeFile(path,newOpts);
    4.         newOpts.inJustDecodeBounds =  false ;  
    5.          int  w = newOpts.outWidth;  
    6.          int  h = newOpts.outHeight;  
    7.         //计算出取样率
    8.         newOpts.inSampleSize = be;
    9.         bitmap = BitmapFactory.decodeFile(srcPath, newOpts);  

    这样的好处是不会先将大图片读入内存,大大减少了内存的使用,也不必考虑将大图片读入内存后的释放事宜。

    3、缩放法:

    以上俩个方法都无法满足要求,只好考虑用缩放来实现。本不想用这种方法来实现,不过网上看到的方法基本都是上面俩种。缩放法其实很简单,设定好 matrix,在createBitmap就可以了。但是我们并不知道缩放比例,而是要求了图片的最终大小。直接用大小的比例来做的话肯定是有问题的,用 大小比例的开方来做会比较接近,但是还是有差距。但是只要再做一下微调应该就可以了,微调的话就是修改过的图片大小比最终大小还大的话,就进行0.8的压 缩再比较,循环直到大小合适。这样就能得到合适大小的图片,而且也能比较保证质量。代码如下

    ByteArrayOutputStream out = new ByteArrayOutputStream();
            image.compress(Bitmap.CompressFormat.JPEG, 85, out);
            float zoom = (float)Math.sqrt(size * 1024 / (float)out.toByteArray().length);
    
            Matrix matrix = new Matrix();
            matrix.setScale(zoom, zoom);
    
            Bitmap result = Bitmap.createBitmap(image, 0, 0, image.getWidth(), image.getHeight(), matrix, true);
    
            out.reset();
            result.compress(Bitmap.CompressFormat.JPEG, 85, out);
            while(out.toByteArray().length > size * 1024){
                System.out.println(out.toByteArray().length);
                matrix.setScale(0.9f, 0.9f);
                result = Bitmap.createBitmap(result, 0, 0, result.getWidth(), result.getHeight(), matrix, true);
                out.reset();
                result.compress(Bitmap.CompressFormat.JPEG, 85, out);
            } 
  • 相关阅读:
    监控里的主码流和子码流是什么意思
    监控硬盘容量计算
    一个能让你了解所有函数调用顺序的Android库
    电工选线
    oracle linux dtrace
    list all of the Oracle 12c hidden undocumented parameters
    Oracle Extended Tracing
    window 驱动开发
    win7 x64 dtrace
    How to Use Dtrace Tracing Ruby Executing
  • 原文地址:https://www.cnblogs.com/BrightPoplar/p/5135439.html
Copyright © 2011-2022 走看看