Bitmap是Android系统中的图像处理的最重要类之一。用它可以获取图像文件信息,进行图像剪切、旋转、缩放等操作,并可以指定格式保存图像文件。本文从应用的角度,着重介绍怎么用Bitmap来实现这些功能。

一、Bitmap的生成

1.1 BitmapFactory decode出Bitmap

Bitmap实现在android.graphics包中。但是Bitmap类的构造函数是私有的,外面并不能实例化,只能是通过JNI实例化。这必然是某个辅助类提供了创建Bitmap的接口,而这个类的实现通过JNI接口来实例化Bitmap的,这个类就是BitmapFactory。

图一、BitmapFactory主要方法及Options选项

利用BitmapFactory可以从一个指定文件中,利用decodeFile()解出Bitmap;也可以定义的图片资源中,利用decodeResource()解出Bitmap。

1.2 decode时的选项

在使用方法decodeFile()/decodeResource()时,都可以指定一个BitmapFacotry.Options。

利用Options的下列属性,可以指定decode的选项:

  • inPreferredConfig 指定decode到内存中,手机中所采用的编码,可选值定义在Bitmap.Config中。缺省值是ARGB_8888。
  • inJustDecodeBounds 如果设置为true,并不会把图像的数据完全解码,亦即decodeXyz()返回值为null,但是Options的outAbc中解出了图像的基本信息。
  • inSampleSize 设置decode时的缩放比例。

利用Options的这些值就可以高效的得到一幅缩略图。

图二、BitmapFactory.decodeFile()

先设置inJustDecodeBounds= true,调用decodeFile()得到图像的基本信息[Step#2~4];

利用图像的宽度(或者高度,或综合)以及目标的宽度,得到inSampleSize值,再设置inJustDecodeBounds= false,调用decodeFile()得到完整的图像数据[Step#5~8]。

先获取比例,再读入数据,如果欲读入大比例缩小的图,将显著的节约内容资源。有时候还会读入大量的缩略图,这效果就更明显了。

二、利用Bitmap和Matrix实现图像变换

Bitmap可以和Matrix结合实现图像的剪切、旋转、缩放等操作。

图三、Bitmap方法

用源Bitmap通过变换生成新的Bitmap的方法:

  1. public static Bitmap createBitmap(Bitmap source, int x, int y, intwidth, int height,
  2. Matrix m, boolean filter)
  3. public static Bitmap createBitmap(Bitmap source, int x, int y, intwidth, int height)
  4. public static Bitmap createScaledBitmap(Bitmap src, int dstWidth,
  5. int dstHeight,boolean filter)

第一个方法是最终的实现,后两种只是对第一种方法的封装。

第二个方法可以从源Bitmap中指定区域(x,y, width, height)中挖出一块来实现剪切;第三个方法可以把源Bitmap缩放为dstWidth x dstHeight的Bitmap。

设置Matrix的Rotate(通过setRotate())或者Scale(通过setScale()),传入第一个方法,可实现旋转或缩放。

图四、Bitmap实现旋转

三、保存图像文件

经过图像变换之后的Bitmap里的数据可以保存到图像压缩文件里(JPG/PNG)。

图五、保存Bitmap数据到文件

这个操作过程中,Bitmap.compress()方法的参数format可设置JPEG或PNG格式;quality可选择压缩质量;fOut是输出流(OutputStream),这里的FileOutputStream是OutputStream的一个子类。

总结一下,本文介绍Bitmap的使用方法——用Bitmap实现图像文件的读取和写入,并用Bitmap实现图像的剪切、旋转和缩放变换。

在开发图片浏览器等软件是,很多时候要显示图片的缩略图,而一般情况下,我们要将图片按照固定大小取缩略图,一般取缩略图的方法是使用BitmapFactory的decodeFile方法,然后通过传递进去 BitmapFactory.Option类型的参数进行取缩略图,在Option中,属性值inSampleSize表示缩略图大小为原始图片大小的几分之一,即如果这个值为2,则取出的缩略图的宽和高都是原始图片的1/2,图片大小就为原始大小的1/4。

  然而,如果我们想取固定大小的缩略图就比较困难了,比如,我们想将不同大小的图片去出来的缩略图高度都为200px,而且要保证图片不失真,那怎么办?我们总不能将原始图片加载到内存中再进行缩放处理吧,要知道在移动开发中,内存是相当宝贵的,而且一张100K的图片,加载完所占用的内存何止 100K?

  经过研究,发现,Options中有个属性inJustDecodeBounds,研究了一下,终于明白是什么意思了,SDK中的E文是这么说的

  If set to true, the decoder will return null (no bitmap), but the out... fields will still be set, allowing the caller to query the bitmap without having to allocate the memory for its pixels.

  意思就是说如果该值设为true那么将不返回实际的bitmap不给其分配内存空间而里面只包括一些解码边界信息即图片大小信息,那么相应的方法也就出来了,通过设置inJustDecodeBounds为true,获取到outHeight(图片原始高度)和 outWidth(图片的原始宽度),然后计算一个inSampleSize(缩放值),然后就可以取图片了,这里要注意的是,inSampleSize 可能小于0,必须做判断。
具体代码如下:
FrameLayout fr=(FrameLayout)findViewById(R.id.FrameLayout01);
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        // 获取这个图片的宽和高
        Bitmap bitmap = BitmapFactory.decodeFile("/sdcard/test.jpg", options); //此时返回bm为空
        options.inJustDecodeBounds = false;
         //计算缩放比
        int be = (int)(options.outHeight / (float)200);
        if (be <= 0)
            be = 1;
        options.inSampleSize = be;
        //重新读入图片,注意这次要把options.inJustDecodeBounds 设为 false哦
        bitmap=BitmapFactory.decodeFile("/sdcard/test.jpg",options);
        int w = bitmap.getWidth();
        int h = bitmap.getHeight();
        System.out.println(w+"   "+h);
        ImageView iv=new ImageView(this);
        iv.setImageBitmap(bitmap);

这样我们就可以读取较大的图片而不会内存溢出了。如果你想把压缩后的图片保存在Sdcard上的话就很简单了:
File file=new File("/sdcard/feng.png");
        try {
            FileOutputStream out=new FileOutputStream(file);
            if(bitmap.compress(Bitmap.CompressFormat.PNG, 100, out)){
                out.flush();
                out.close();
            }
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
ok,这样就把图片保存在/sdcard/feng.png这个文件里面了,呵呵。

Bitmap是Android系统中的图像处理的最重要类之一。用它可以获取图像文件信息,进行图像剪切、旋转、缩放等操作,并可以指定格式保存图像文件。本文从应用的角度,着重介绍怎么用Bitmap来实现这些功能。

一、Bitmap的生成

1.1 BitmapFactory decode出Bitmap

Bitmap实现在android.graphics包中。但是Bitmap类的构造函数是私有的,外面并不能实例化,只能是通过JNI实例化。这必然是某个辅助类提供了创建Bitmap的接口,而这个类的实现通过JNI接口来实例化Bitmap的,这个类就是BitmapFactory。


图一、BitmapFactory主要方法及Options选项

利用BitmapFactory可以从一个指定文件中,利用decodeFile()解出Bitmap;也可以定义的图片资源中,利用decodeResource()解出Bitmap。

1.2 decode时的选项

在使用方法decodeFile()/decodeResource()时,都可以指定一个BitmapFacotry.Options

利用Options的下列属性,可以指定decode的选项:

  • inPreferredConfig 指定decode到内存中,手机中所采用的编码,可选值定义在Bitmap.Config中。缺省值是ARGB_8888。
  • inJustDecodeBounds 如果设置为true,并不会把图像的数据完全解码,亦即decodeXyz()返回值为null,但是Options的outAbc中解出了图像的基本信息。
  • inSampleSize 设置decode时的缩放比例。

利用Options的这些值就可以高效的得到一幅缩略图。


图二、BitmapFactory.decodeFile()

先设置inJustDecodeBounds= true,调用decodeFile()得到图像的基本信息[Step#2~4];

利用图像的宽度(或者高度,或综合)以及目标的宽度,得到inSampleSize值,再设置inJustDecodeBounds= false,调用decodeFile()得到完整的图像数据[Step#5~8]。

先获取比例,再读入数据,如果欲读入大比例缩小的图,将显著的节约内容资源。有时候还会读入大量的缩略图,这效果就更明显了。

二、利用Bitmap和Matrix实现图像变换

Bitmap可以和Matrix结合实现图像的剪切、旋转、缩放等操作。


图三、Bitmap方法

用源Bitmap通过变换生成新的Bitmap的方法:

  1. public static Bitmap createBitmap(Bitmap source, int x, int y, intwidth, int height,
  2. Matrix m, boolean filter)
  3. public static Bitmap createBitmap(Bitmap source, int x, int y, intwidth, int height)
  4. public static Bitmap createScaledBitmap(Bitmap src, int dstWidth,
  5. int dstHeight,boolean filter)

第一个方法是最终的实现,后两种只是对第一种方法的封装。

第二个方法可以从源Bitmap中指定区域(x,y, width, height)中挖出一块来实现剪切;第三个方法可以把源Bitmap缩放为dstWidth x dstHeight的Bitmap。

设置Matrix的Rotate(通过setRotate())或者Scale(通过setScale()),传入第一个方法,可实现旋转或缩放。


图四、Bitmap实现旋转

三、保存图像文件

经过图像变换之后的Bitmap里的数据可以保存到图像压缩文件里(JPG/PNG)。

图五、保存Bitmap数据到文件

这个操作过程中,Bitmap.compress()方法的参数format可设置JPEG或PNG格式;quality可选择压缩质量;fOut是输出流(OutputStream),这里的FileOutputStream是OutputStream的一个子类。

总结一下,本文介绍Bitmap的使用方法——用Bitmap实现图像文件的读取和写入,并用Bitmap实现图像的剪切、旋转和缩放变换。

在开发图片浏览器等软件是,很多时候要显示图片的缩略图,而一般情况下,我们要将图片按照固定大小取缩略图,一般取缩略图的方法是使用BitmapFactory的decodeFile方法,然后通过传递进去 BitmapFactory.Option类型的参数进行取缩略图,在Option中,属性值inSampleSize表示缩略图大小为原始图片大小的几分之一,即如果这个值为2,则取出的缩略图的宽和高都是原始图片的1/2,图片大小就为原始大小的1/4。

  然而,如果我们想取固定大小的缩略图就比较困难了,比如,我们想将不同大小的图片去出来的缩略图高度都为200px,而且要保证图片不失真,那怎么办?我们总不能将原始图片加载到内存中再进行缩放处理吧,要知道在移动开发中,内存是相当宝贵的,而且一张100K的图片,加载完所占用的内存何止 100K?

  经过研究,发现,Options中有个属性inJustDecodeBounds,研究了一下,终于明白是什么意思了,SDK中的E文是这么说的

  If set to true, the decoder will return null (no bitmap), but the out... fields will still be set, allowing the caller to query the bitmap without having to allocate the memory for its pixels.

  意思就是说如果该值设为true那么将不返回实际的bitmap不给其分配内存空间而里面只包括一些解码边界信息即图片大小信息,那么相应的方法也就出来了,通过设置inJustDecodeBounds为true,获取到outHeight(图片原始高度)和 outWidth(图片的原始宽度),然后计算一个inSampleSize(缩放值),然后就可以取图片了,这里要注意的是,inSampleSize 可能小于0,必须做判断。
具体代码如下:
FrameLayout fr=(FrameLayout)findViewById(R.id.FrameLayout01);
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        // 获取这个图片的宽和高
        Bitmap bitmap = BitmapFactory.decodeFile("/sdcard/test.jpg", options); //此时返回bm为空
        options.inJustDecodeBounds = false;
         //计算缩放比
        int be = (int)(options.outHeight / (float)200);
        if (be <= 0)
            be = 1;
        options.inSampleSize = be;
        //重新读入图片,注意这次要把options.inJustDecodeBounds 设为 false哦
        bitmap=BitmapFactory.decodeFile("/sdcard/test.jpg",options);
        int w = bitmap.getWidth();
        int h = bitmap.getHeight();
        System.out.println(w+"   "+h);
        ImageView iv=new ImageView(this);
        iv.setImageBitmap(bitmap);

这样我们就可以读取较大的图片而不会内存溢出了。如果你想把压缩后的图片保存在Sdcard上的话就很简单了:
File file=new File("/sdcard/feng.png");
        try {
            FileOutputStream out=new FileOutputStream(file);
            if(bitmap.compress(Bitmap.CompressFormat.PNG, 100, out)){
                out.flush();
                out.close();
            }
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
ok,这样就把图片保存在/sdcard/feng.png这个文件里面了,呵呵。

Android 图片压缩也即生成缩略图方法相关推荐

  1. Android图片压缩(质量压缩和尺寸压缩)

    在网上调查了图片压缩的方法并实装后,大致上可以认为有两类压缩:质量压缩(不改变图片的尺寸)和尺寸压缩(相当于是像素上的压缩):质量压缩一般可用于上传大图前的处理,这样就可以节省一定的流量,毕竟现在的手 ...

  2. android 图片压缩总结1

    在网上调查了图片压缩的方法并实装后,大致上可以认为有两类压缩:质量压缩(不改变图片的尺寸)和尺寸压缩(相当于是像素上的压缩):质量压缩一般可用于上传大图前的处理,这样就可以节省一定的流量,毕竟现在的手 ...

  3. 最详细的Android图片压缩攻略

    Mr.Louis的博客地址: https://blog.csdn.net/weixin_44005563 最近在研究图片压缩原理,看了大量资料,从上层尺寸压缩.质量压缩原理到下层的哈夫曼压缩,走成华大 ...

  4. Android图片压缩(质量压缩和尺寸压缩)Bitmap转成字符串上传

    在网上调查了图片压缩的方法并实装后,大致上可以认为有两类压缩:质量压缩(不改变图片的尺寸)和尺寸压缩(相当于是像素上的压缩):质量压缩一般可用于上传大图前的处理,这样就可以节省一定的流量,毕竟现在的手 ...

  5. 最详细的Android图片压缩攻略,让你一次过足瘾

    /   今日科技快讯   / 近日,微软已经通知业务合作伙伴,将从明年开始上调Office办公套件逐月订购的价格,选择逐年订购服务的客户则不会受到影响. 微软宣布将于2022年推出Office全新企业 ...

  6. [Android]Android图片压缩(质量压缩和尺寸压缩)

    原文地址:http://blog.csdn.net/jdsjlzx/article/details/44228935 在网上调查了图片压缩的方法并实装后,大致上可以认为有两类压缩:质量压缩(不改变图片 ...

  7. Android 图片压缩器

    概述 Android 图片压缩器:一款高效的图片压缩器库,支持批量压缩,异步压缩.多线程多任务压缩,压缩比设置等特性. 详细 代码下载:http://www.demodashi.com/demo/12 ...

  8. Android图片压缩尺寸和质量

    Android在处理图片时,如果不进行压缩处理,很容易就出现OOM内存溢出(OutOfMemory)问题,所以无论是第三方图片加载还是自己在处理图片时,都要进行压缩处理. Android系统中,一张图 ...

  9. Android图片压缩库——libjpeg-turbo

    为何Android图片压缩效率比IOS低质量差 为什么Android的图片压缩质量要比iPhone的压缩质量差很多,这是因为Android底层犯的一个小错误:libjpeg.并且这个错误一直持续到了今 ...

  10. 可能是最详细的Android图片压缩原理分析(二)—— 鲁班压缩算法解析

    本篇文章已授权微信公众号guolin_blog(郭霖)独家发布 稀土掘金链接 前言 通过上一篇,我们了解了一些关于图片压缩的基础知识,这篇文章我们主要讲解一下鲁班压缩的算法逻辑,很多博客都是从Gith ...

最新文章

  1. 烂泥:ubuntu下配置msmtp+mutt发送邮件
  2. JZOJ 5107. 【GDSOI2017】 中学生数据结构题
  3. 【转】Python-面向对象进阶
  4. 例子代码:web.xml
  5. maven项目在eclipse中debug
  6. Spring AOP 性能监控器
  7. 互联时代如何真正支持与实现数据经济
  8. day6Linux命令-设置别名
  9. BZOJ5218[Lydsy2017省队十连测] 友好城市
  10. 如何从PDF文件中提取几页为一个PDF文件?
  11. 项目管理 之四 常用的项目管理工具(Github、Gitlab、Gitea、Gitee、Worktile、Teambition)
  12. 烽火2640路由器命令行手册-01-基础配置命令
  13. 大数据审计的发展_大数据时代对审计发展的影响
  14. 消息队列之取消会议和自动退款处理
  15. c语言中void和define,C语言里面的内联函数(inline)与宏定义(#define)探讨
  16. 费曼技巧:学习任何东西的最佳方法
  17. 一个人竟然撸了一个网易云音乐云村
  18. git问题:head detached at xxxx
  19. 怎么判断安卓解锁是否成功
  20. 研发组织该如何设计绩效体系?

热门文章

  1. JAVA泛型_泛型类、接口、通配符、方法、上下边界
  2. bam文件flag的含义
  3. 马小云:利用信息差赚钱的暴利创业项目 ,批量开店月入3万
  4. 如何改变图片大小-前端入门
  5. QT入门学习(一):什么是QT
  6. 又涨了?2021年6月程序员平均薪资15052元!高薪还能持续多久?
  7. 2021暑期学习之旅
  8. 汇编语言(十二)颜色搭配显示+BIOS功能调用表+INT 10H功能详细列表
  9. png转icon java,PNG转ICO - steambap的个人空间 - OSCHINA - 中文开源技术交流社区
  10. day12【Lambda,函数式接口】Lamd