文档处理控制栏:
* [x] 选题收集:
* [ ] 初稿整理:
* [ ] 补充校对:
* [ ] 入库存档:
---
版权信息
原文链接:[Android Bitmap最全面详解](http://www.jianshu.com/p/ade293a49cd7)
---
## 1.Bitmap类
> Bitmap图像处理的最重要类之一。用它可以获取图像文件信息,进行图像颜色变换、剪切、旋转、缩放等操作,并可以指定格式保存图像文件
#### 1.1Bitmap常用的方法
![](//upload-images.jianshu.io/upload_images/7508328-70e6027e705ce809.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
![](//upload-images.jianshu.io/upload_images/7508328-f42a7c5238b4ea90.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
#### 1.2Bitmap的颜色配置信息与压缩方式信息
Bitmap中有两个内部枚举类:Config和CompressFormat,
Config是用来设置颜色配置信息的,
CompressFormat是用来设置压缩方式的。
![](//upload-images.jianshu.io/upload_images/7508328-6f3c5d3e622fd0cc.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
**Config解析:**
* Bitmap.Config.ALPHA_8:颜色信息只由透明度组成,占8位。
* Bitmap.Config.ARGB_4444:颜色信息由透明度与R(Red),G(Green),B(Blue)四部分组成,每个部分都占4位,总共占16位。
* Bitmap.Config.ARGB_8888:颜色信息由透明度与R(Red),G(Green),B(Blue)四部分组成,每个部分都占8位,总共占32位。是Bitmap默认的颜色配置信息,也是最占空间的一种配置。
* Bitmap.Config.RGB_565:颜色信息由R(Red),G(Green),B(Blue)三部分组成,R占5位,G占6位,B占5位,总共占16位。
> 通常我们优化Bitmap时,当需要做性能优化或者防止OOM(Out Of Memory),我们通常会使用Bitmap.Config.RGB_565这个配置,因为Bitmap.Config.ALPHA_8只有透明度,显示一般图片没有意义,Bitmap.Config.ARGB_4444显示图片不清楚,Bitmap.Config.ARGB_8888占用内存最多。
**CompressFormat解析:**
* Bitmap.CompressFormat.JPEG:表示以JPEG压缩算法进行图像压缩,压缩后的格式可以是".jpg"或者".jpeg",是一种有损压缩。
* Bitmap.CompressFormat.PNG:表示以PNG压缩算法进行图像压缩,压缩后的格式可以是".png",是一种无损压缩。
* Bitmap.CompressFormat.WEBP:表示以WebP压缩算法进行图像压缩,压缩后的格式可以是".webp",是一种有损压缩,质量相同的情况下,WebP格式图像的体积要比JPEG格式图像小40%。美中不足的是,WebP格式图像的编码时间“比JPEG格式图像长8倍”。
#### 1.3Bitmap对图像进行操作
###### 1)Bitmap裁剪图像
`itmap.createBitmap(Bitmap source, int x, int y, int width, int height)`
根据源Bitmap对象source,创建出source对象裁剪后的图像的Bitmap。x,y分别代表裁剪时,x轴和y轴的第一个像素,width,height分别表示裁剪后的图像的宽度和高度。
注意:x+width要小于等于source的宽度,y+height要小于等于source的高度。
`Bitmap.createBitmap(Bitmap source, int x, int y, int width, int height,Matrix m, boolean filter)`
这个方法只比上面的方法多了m和filter这两个参数,m是一个Matrix(矩阵)对象,可以进行缩放,旋转,移动等动作,filter为true时表示source会被过滤,仅仅当m操作不仅包含移动操作,还包含别的操作时才适用。其实上面的方法本质上就是调用这个方法而已。
~~~
public static Bitmap createBitmap(Bitmap source, int x, int y, int width, int height) {
return createBitmap(source, x, y, width, height, null, false);
}
~~~
###### 2 )Bitmap缩放,旋转,移动图像
Bitmap缩放,旋转,移动,倾斜图像其实就是通过`Bitmap.createBitmap(Bitmap source, int x, int y, int width, int height,Matrix m, boolean filter)`方法实现的,只是在实现这些功能的同时还可以实现图像的裁剪。
~~~
// 定义矩阵对象
Matrix matrix = new Matrix();
// 缩放图像
matrix.postScale(0.8f, 0.9f);
// 向左旋转(逆时针旋转)45度,参数为正则向右旋转(顺时针旋转)
matrix.postRotate(-45);
//移动图像
//matrix.postTranslate(100,80);
Bitmap bitmap = Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(),
matrix, true);
~~~
Matrix的postScale和postRotate方法还有多带两个参数的重载方法postScale(float sx, float sy, float px, float py)和postRotate(float degrees, float px, float py),后两个参数px和py都表示以该点为中心进行操作。
**注意:虽然Matrix还可以调用postSkew方法进行倾斜操作,但是却不可以在此时创建Bitmap时使用。**
###### 3) Bitmap保存图像与释放资源
~~~
bitmap=BitmapFactory.decodeResource(getResources(),R.drawable.feng);
File file=new File(getFilesDir(),"lavor.jpg");
if(file.exists()){
file.delete();
}
try {
FileOutputStream outputStream=new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG,90,outputStream);
outputStream.flush();
outputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
bitmap.recycle();//释放bitmap的资源,这是一个不可逆转的操作
~~~
###### 3)Matrix拓展类
| 方法 | 介绍 |
| --- | --- |
| setRotate(float degrees, float px, float py) | 对图片进行旋转 |
| setScale(float sx, float sy) | 对图片进行缩放 |
| setTranslate(float dx, float dy) | 对图片进行平移 |
| postTranslate(centerX, centerY) | 在上一次修改的基础上进行再次修改 set 每次操作都是最新的 会覆盖上次的操作 |
~~~
//显示原图
ImageView iv_src = (ImageView) findViewById(R.id.iv_src);
//显示副本
ImageView iv_copy = (ImageView) findViewById(R.id.iv_copy);
//[1]先把tomcat.png 图片转换成bitmap 显示到iv_src
Bitmap srcBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.tomcat);
//[1.1]操作图片
// srcBitmap.setPixel(20, 30, Color.RED);
iv_src.setImageBitmap(srcBitmap);
//[2]创建原图的副本
//[2.1]创建一个模板 相当于 创建了一个大小和原图一样的 空白的白纸
Bitmap copybiBitmap = Bitmap.createBitmap(srcBitmap.getWidth(), srcBitmap.getHeight(), srcBitmap.getConfig());
//[2.2]想作画需要一个画笔
Paint paint = new Paint();
//[2.3]创建一个画布 把白纸铺到画布上
Canvas canvas = new Canvas(copybiBitmap);
//[2.4]开始作画
Matrix matrix = new Matrix();
//[2.5]对图片进行旋转
//matrix.setRotate(20, srcBitmap.getWidth()/2, srcBitmap.getHeight()/2);
//[2.5]对图片进行
// matrix.setScale(0.5f, 0.5f);
//[2.6]对图片进行平移
// matrix.setTranslate(30, 0);
//[2.7]镜面效果 如果2个方法一起用
// matrix.setScale(-1.0f, 1);
//post是在上一次修改的基础上进行再次修改 set 每次操作都是最新的 会覆盖上次的操作
// matrix.postTranslate(srcBitmap.getWidth(), 0);
//[2,7]倒影效果
matrix.setScale(1.0f, -1);
//post是在上一次修改的基础上进行再次修改 set 每次操作都是最新的 会覆盖上次的操作
matrix.postTranslate(0, srcBitmap.getHeight());
canvas.drawBitmap(srcBitmap,matrix , paint);
//[3]把copybimap显示到iv_copy上
iv_copy.setImageBitmap(copybiBitmap);
~~~
## 2.BitmapFactory类
> 创建位图对象从不同的来源,包括文件、流, 和字节数组。
###### 2.1BitmapFactory常用方法
| 方法 | 说明 |
| --- | --- |
| decodeFile(String pathName, Options opts) | 从文件读取图片 |
| decodeFile(String pathName) | 从文件读取图片 |
| decodeFileDescriptor(FileDescriptor fd) | 从文件读取文件 与decodeFile不同的是这个直接调用JNI函数进行读取 效率比较高 |
| decodeFileDescriptor(FileDescriptor fd, Rect outPadding, Options opts) | 同上 |
| decodeStream(InputStream is) | 从输入流读取图片 |
| decodeStream(InputStream is, Rect outPadding, Options opts) | 从输入流读取图片 |
| decodeStream(InputStream is, Rect outPadding, Options opts) | 从资源文件读取图片 |
| decodeResource(Resources res, int id) | 从资源文件读取图片 |
| decodeResource(Resources res, int id, Options opts) | 从资源文件读取图片 |
| decodeByteArray(byte[] data, int offset, int length) | 从数组读取图片 |
| decodeByteArray(byte[] data, int offset, int length, Options opts) | 从数组读取图片 |
> BitmapFactory.decodeResource 加载的图片可能会经过缩放,该缩放目前是放在 java 层做的,效率比较低,而且需要消耗 java 层的内存。因此,如果大量使用该接口加载图片,容易导致OOM错误
> BitmapFactory.decodeStream 不会对所加载的图片进行缩放,相比之下占用内存少,效率更高。
> 这两个接口各有用处,如果对性能要求较高,则应该使用 decodeStream;如果对性能要求不高,且需要 Android 自带的图片自适应缩放功能,则可以使用 decodeResource。
#### 2.2BitmapFactory三种加载图片
* 1)从资源文件读取图片
~~~
Bitmap bitmap= BitmapFactory.decodeResource(getResources(),R.drawable.after19);
iv.setImageBitmap(bitmap);
~~~
* 2)从输入流中读取图片
~~~
FileInputStream fis=new FileInputStream(new File(getFilesDir()+"/psb.jpg"));
Bitmap bitmap= BitmapFactory.decodeStream(fis);
iv.setImageBitmap(bitmap);
~~~
* 3)从数组中读取图片
~~~
public static Bitmap readBitmapFromByteArray(byte[] data, int width, int height) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeByteArray(data, 0, data.length, options);
float srcWidth = options.outWidth;
float srcHeight = options.outHeight;
int inSampleSize = 1;
if (srcHeight > height || srcWidth > width) {
if (srcWidth > srcHeight) {
inSampleSize = Math.round(srcHeight / height);
} else {
inSampleSize = Math.round(srcWidth / width);
}
}
options.inJustDecodeBounds = false;
options.inSampleSize = inSampleSize;
return BitmapFactory.decodeByteArray(data, 0, data.length, options);
}
~~~
#### 2.3BitmapFactory常用操作
* 1)保存本地图片
~~~
public static void writeBitmapToFile(String filePath, Bitmap b, int quality) {
try {
File desFile = new File(filePath);
FileOutputStream fos = new FileOutputStream(desFile);
BufferedOutputStream bos = new BufferedOutputStream(fos);
b.compress(Bitmap.CompressFormat.JPEG, quality, bos);
bos.flush();
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
~~~
* 2)图片缩放
~~~
public static Bitmap bitmapScale(Bitmap bitmap, float scale) {
Matrix matrix = new Matrix();
matrix.postScale(scale, scale); // 长和宽放大缩小的比例
Bitmap resizeBmp = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
return resizeBmp;
}
~~~
* 3)对 bitmap 进行裁剪
~~~
public Bitmap bitmapClip(Context context , int id , int x , int y){
Bitmap map = BitmapFactory.decodeResource(context.getResources(), id);
map = Bitmap.createBitmap(map, x, y, 120, 120);
return map;
}
~~~
## 3.BitmapFactory.option常用方法
| Option参数类方法 | 说明 |
| --- | --- |
| public boolean inJustDecodeBounds | 如果设置为true,不获取图片,不分配内存,但会返回图片的高度宽度信息 |
| public int inSampleSize | 图片缩放的倍数 |
| public int outWidth | 获取图片的宽度值 |
| public int outHeight | 获取图片的高度值 |
| public int inDensity | 用于位图的像素压缩比 |
| public int inTargetDensity | 用于目标位图的像素压缩比(要生成的位图) |
| public byte[] inTempStorage | 创建临时文件,将图片存储 |
| public boolean inScaled | 设置为true时进行图片压缩,从inDensity到inTargetDensity |
| public boolean inDither | 如果为true,解码器尝试抖动解码 |
| public Bitmap.Config inPreferredConfig | 设置解码器这个值是设置色彩模式,默认值是ARGB_8888,在这个模式下,一个像素点占用4bytes空间,一般对透明度不做要求的话,一般采用RGB_565模式,这个模式下一个像素点占用2bytes |
| public String outMimeType | 设置解码图像 |
| public boolean inPurgeable | 当存储Pixel的内存空间在系统内存不足时是否可以被回收 |
| public boolean inInputShareable | inPurgeable为true情况下才生效,是否可以共享一个InputStream |
| public boolean inPreferQualityOverSpeed | 为true则优先保证Bitmap质量其次是解码速度 |
| public boolean inMutable | 配置Bitmap是否可以更改,比如:在Bitmap上隔几个像素加一条线段 |
| public int inScreenDensity | 当前屏幕的像素密度 |
- 0-发现
- AndroidInterview-Q-A
- Android能让你少走弯路的干货整理
- LearningNotes
- temp
- temp11
- 部分地址
- 0-待办任务
- 待补充列表
- 0-未分类
- AndroidView事件分发与滑动冲突处理
- Spannable
- 事件分发机制详解
- 1-Java
- 1-Java-01基础
- 未归档
- 你应该知道的JDK知识
- 集合框架
- 1-Java-04合集
- Java之旅0
- Java之旅
- JAVA之旅01
- JAVA之旅02
- JAVA之旅03
- JAVA之旅04
- JAVA之旅05
- JAVA之旅06
- JAVA之旅07
- JAVA之旅08
- JAVA之旅09
- java之旅1
- JAVA之旅10
- JAVA之旅11
- JAVA之旅12
- JAVA之旅13
- JAVA之旅14
- JAVA之旅15
- JAVA之旅16
- JAVA之旅17
- JAVA之旅18
- JAVA之旅19
- java之旅2
- JAVA之旅20
- JAVA之旅21
- JAVA之旅22
- JAVA之旅23
- JAVA之旅24
- JAVA之旅25
- JAVA之旅26
- JAVA之旅27
- JAVA之旅28
- JAVA之旅29
- java之旅3
- JAVA之旅30
- JAVA之旅31
- JAVA之旅32
- JAVA之旅33
- JAVA之旅34
- JAVA之旅35
- 1-Java-05辨析
- HashMapArrayMap
- Java8新特性
- Java8接口默认方法
- 图解HashMap(1)
- 图解HashMap(2)
- 2-Android
- 2-Android-1-基础
- View绘制流程
- 事件分发
- AndroidView的事件分发机制和滑动冲突解决
- 自定义View基础
- 1-安卓自定义View基础-坐标系
- 2-安卓自定义View基础-角度弧度
- 3-安卓自定义View基础-颜色
- 自定义View进阶
- 1-安卓自定义View进阶-分类和流程
- 10-安卓自定义View进阶-Matrix详解
- 11-安卓自定义View进阶-MatrixCamera
- 12-安卓自定义View进阶-事件分发机制原理
- 13-安卓自定义View进阶-事件分发机制详解
- 14-安卓自定义View进阶-MotionEvent详解
- 15-安卓自定义View进阶-特殊形状控件事件处理方案
- 16-安卓自定义View进阶-多点触控详解
- 17-安卓自定义View进阶-手势检测GestureDetector
- 2-安卓自定义View进阶-绘制基本图形
- 3-安卓自定义View进阶-画布操作
- 4-安卓自定义View进阶-图片文字
- 5-安卓自定义View进阶-Path基本操作
- 6-安卓自定义View进阶-贝塞尔曲线
- 7-安卓自定义View进阶-Path完结篇伪
- 8-安卓自定义View进阶-Path玩出花样PathMeasure
- 9-安卓自定义View进阶-Matrix原理
- 通用类介绍
- Application
- 2-Android-2-使用
- 2-Android-02控件
- ViewGroup
- ConstraintLayout
- CoordinatorLayout
- 2-Android-03三方使用
- Dagger2
- Dagger2图文完全教程
- Dagger2最清晰的使用教程
- Dagger2让你爱不释手-终结篇
- Dagger2让你爱不释手-重点概念讲解、融合篇
- dagger2让你爱不释手:基础依赖注入框架篇
- 阅读笔记
- Glide
- Google推荐的图片加载库Glide:最新版使用指南(含新特性)
- rxjava
- 这可能是最好的RxJava2.x入门教程完结版
- 这可能是最好的RxJava2.x入门教程(一)
- 这可能是最好的RxJava2.x入门教程(三)
- 这可能是最好的RxJava2.x入门教程(二)
- 这可能是最好的RxJava2.x入门教程(五)
- 这可能是最好的RxJava2.x入门教程(四)
- 2-Android-3-优化
- 优化概况
- 各种优化
- Android端秒开优化
- apk大小优化
- 内存分析
- 混淆
- 2-Android-4-工具
- adb命令
- 一键分析Android的BugReport
- 版本控制
- git
- git章节简述
- 2-Android-5-源码
- HandlerThread 源码分析
- IntentService的使用和源码分析
- 2-Android-9-辨析
- LRU算法
- 什么是Bitmap
- 常见图片压缩方式
- 3-Kotlin
- Kotlin使用笔记1-草稿
- Kotlin使用笔记2
- kotlin特性草稿
- Kotlin草稿-Delegation
- Kotlin草稿-Field
- Kotlin草稿-object
- 4-JavaScript
- 5-Python
- 6-Other
- Git
- Gradle
- Android中ProGuard配置和总结
- gradle使用笔记
- Nexus私服搭建
- 编译提速最佳实践
- 7-设计模式与架构
- 组件化
- 组件化探索(OKR)
- 1-参考列表
- 2-1-组件化概述
- 2-2-gradle配置
- 2-3-代码编写
- 2-4-常见问题
- 2-9-值得一读
- 8-数据结构与算法
- 0临时文件
- 汉诺塔
- 8-数据-1数据结构
- HashMap
- HashMap、Hashtable、HashSet 和 ConcurrentHashMap 的比较
- 迟到一年HashMap解读
- 8-数据-2算法
- 1个就够了
- Java常用排序算法(必须掌握的8大排序算法)
- 常用排序算法总结(性能+代码)
- 必须知道的八大种排序算法(java实现)
- 9-职业
- 阅读
- 书单
- 面试
- 面试-01-java
- Java面试题全集骆昊(上)
- Java面试题全集骆昊(下)
- Java面试题全集骆昊(中)
- 面试-02-android
- 40道Android面试题
- 面试-03-开源源码
- Android图片加载框架最全解析(二),从源码的角度理解Glide的执行流程
- 面试-07-设计模式
- 面试-08-算法
- 面试-09-其他
- SUMMARY
- 版权说明
- temp111