## 本节引言:
> 在上一节中我们对Android中的13种类型的Drawable的类型进行了讲解,有没有应用到自己的 项目当中呢?而本节我们来探讨的是Bitmap(位图)的一些使用,而在开始本节的内容之前我们 先来区分几个名词的概念:
>
> * **Drawable**:通用的图形对象,用于装载常用格式的图像,既可以是PNG,JPG这样的图像, 也是前面学的那13种Drawable类型的可视化对象!我们可以理解成一个用来放画的——**画框**!
> * **Bitmap(位图)**:我们可以把他看作一个**画架**,我们先把画放到上面,然后我们可以 进行一些处理,比如获取图像文件信息,做旋转切割,放大缩小等操作!
> * **Canvas(画布)**:如其名,**画布**,我们可以在上面作画(绘制),你既可以用**Paint(画笔)**, 来画各种形状或者写字,又可以用**Path(路径)**来绘制多个点,然后连接成各种图形!
> * **Matrix(矩阵)**:用于图形特效处理的,颜色矩阵(ColorMatrix),还有使用Matrix进行图像的 平移,缩放,旋转,倾斜等!
>
> 而上述的这些都是Android中的底层图形类:**android.graphics**给我们提供的接口! 嗯,话不多说开始本节内容! PS:官方文档:[Bitmap](http://androiddoc.qiniudn.com/reference/android/graphics/Bitmap.html)
* * *
## 1.了解Bitmap,BitmapFactory,BitmapFacotry.Options
> 如题,本来可以直接说着三个东东的关系的,但是我就是要**傲娇**,就要看代码!![](https://box.kancloud.cn/2015-12-02_565e7981bc76f.jpg) 如果你打开Bitmap类的源码,你会看到Bitmap的构造方法上有这样一段东东:
>
> ![](https://box.kancloud.cn/2015-12-02_565e7981cf2b1.jpg)
>
> 大概想说的就是:Bitmap的构造方法是私有的,外面不能实例化,只能通过JNI实例化! 当然,肯定也会给我们提供一个接口给我们来创建Bitmap的,而这个接口类就是:**BitmapFactory**! 来来来,打开BitmapFactory类,我们点下左边的Structure可以看到BitmapFactory给我们 提供了这些方法,大部分都是decodeXxx,通过各种形式来创建Bitmap的!
>
> ![](https://box.kancloud.cn/2015-12-02_565e7981e0373.jpg)
>
> 接着我们又发现了,每一种方法,都会有一个Options类型的参数,点进去看看: 于是乎我们发现了这货是一个静态内部类:**BitmapFacotry.Options**! 而他是用来设置decode时的选项的!
>
> ![](https://box.kancloud.cn/2015-12-02_565e7982002d0.jpg)
>
> 我们对这里的某些参数的值进行设置,比如inJustDecodeBounds设置为true避免OOM(内存溢出), 什么,不知道OOM,没事,等下一点点跟你说清楚!最后回到我们的Bitmap!嗯,Bitmap中的 方法比较多,就不一一进行讲解了,我们从中挑几个用得较多的来讲解! 中文文档:[Android中文API(136) —— Bitmap](http://www.cnblogs.com/over140/archive/2011/11/21/2256727.html)
* * *
## 2.Bitmap常用方法
> **普通方法**
>
> * public boolean **compress** (Bitmap.CompressFormat format, int quality, OutputStream stream) 将位图的压缩到指定的OutputStream,可以理解成将Bitmap保存到文件中! **format**:格式,PNG,JPG等; **quality**:压缩质量,0-100,0表示最低画质压缩,100最大质量(PNG无损,会忽略品质设定) **stream**:输出流 返回值代表是否成功压缩到指定流!
> * void **recycle**():回收位图占用的内存空间,把位图标记为Dead
> * boolean **isRecycled**():判断位图内存是否已释放
> * int **getWidth**():获取位图的宽度
> * int **getHeight**():获取位图的高度
> * boolean **isMutable**():图片是否可修改
> * int **getScaledWidth**(Canvas canvas):获取指定密度转换后的图像的宽度
> * int **getScaledHeight**(Canvas canvas):获取指定密度转换后的图像的高度
>
> **静态方法**:
>
> * Bitmap **createBitmap**(Bitmap src):以src为原图生成不可变得新图像
> * Bitmap **createScaledBitmap**(Bitmap src, int dstWidth,int dstHeight, boolean filter):以src为原图,创建新的图像,指定新图像的高宽以及是否变。
> * Bitmap **createBitmap**(int width, int height, Config config):创建指定格式、大小的位图
> * Bitmap **createBitmap**(Bitmap source, int x, int y, int width, int height)以source为原图,创建新的图片,指定起始坐标以及新图像的高宽。
> * public static Bitmap **createBitmap**(Bitmap source, int x, int y, int width, int height, Matrix m, boolean filter)
**BitmapFactory.Option**可设置参数:
> * boolean **inJustDecodeBounds**——如果设置为true,不获取图片,不分配内存,但会返回图片的高宽度信息。
> * int **inSampleSize**——图片缩放的倍数。如果设为4,则宽和高都为原来的1/4,则图是原来的1/16。
> * int **outWidth**——获取图片的宽度值
> * int **outHeight**——获取图片的高度值
> * int **inDensity**——用于位图的像素压缩比
> * int **inTargetDensity**——用于目标位图的像素压缩比(要生成的位图)
> * boolean **inScaled**——设置为true时进行图片压缩,从inDensity到inTargetDensity。
好吧,就贴这么多吧,要用自己查文档~
* * *
## 3.获取Bitmap位图
> 从资源中获取位图的方式有两种:通过BitmapDrawable或者BitmapFactory,下面演示下: 我们首先得获得这个
**BitmapDrawable方法**:
你可以创建一个构造一个BitmapDrawable对象,比如通过流构建BitmapDrawable:
~~~
BitmapDrawable bmpMeizi = new BitmapDrawable(getAssets().open("pic_meizi.jpg"));
Bitmap mBitmap = bmpMeizi.getBitmap();
img_bg.setImageBitmap(mBitmap);
~~~
**BitmapFactory方法**:
都是静态方法,直接调,可以通过资源ID、路径、文件、数据流等方式来获取位图!
~~~
//通过资源ID
private Bitmap getBitmapFromResource(Resources res, int resId) {
return BitmapFactory.decodeResource(res, resId);
}
//文件
private Bitmap getBitmapFromFile(String pathName) {
return BitmapFactory.decodeFile(pathName);
}
//字节数组
public Bitmap Bytes2Bimap(byte[] b) {
if (b.length != 0) {
return BitmapFactory.decodeByteArray(b, 0, b.length);
} else {
return null;
}
}
//输入流
private Bitmap getBitmapFromStream(InputStream inputStream) {
return BitmapFactory.decodeStream(inputStream);
}
~~~
* * *
## 4.获取Bitmap的相关信息:
这个,只要我们获取了Bitmap对象,就可以调用相关方法来获取对应的参数了,getByteCount获得大小, getHeight和getWidth这些~这里就不写了,自己查文档!
* * *
## 5.抠图片上的某一角下来
有时,可能你想把图片上的某一角扣下来,直接通过Bitmap的createBitmap()扣下来即可 参数依次为:处理的bitmap对象,起始x,y坐标,以及截取的宽高
~~~
Bitmap bitmap1 = BitmapFactory.decodeResource(getResources(), R.mipmap.pic_meizi);
Bitmap bitmap2 = Bitmap.createBitmap(bitmap1,100,100,200,200);
img_bg = (ImageView) findViewById(R.id.img_bg);
img_bg.setImageBitmap(bitmap2);
~~~
**运行效果图**:
原图:
![](https://box.kancloud.cn/2015-12-02_565e79821635d.jpg)
切下来的一角:
![](https://box.kancloud.cn/2015-12-02_565e798231deb.jpg)
* * *
## 6.对Bitmap进行缩放
我们这里不用Matrix来对Bitmap,而是直接使用Bitmap给我们提供的**createScaledBitmap**来实现, 参数依次是:处理的bitmap对象,缩放后的宽高,
![](https://box.kancloud.cn/2015-12-02_565e798247099.jpg)
* * *
## 7.使用Bitmap进行截屏
**运行效果图**:
![](https://box.kancloud.cn/2015-12-02_565e7982639c6.jpg)
**实现代码**:
~~~
public class MainActivity extends AppCompatActivity {
static ByteArrayOutputStream byteOut = null;
private Bitmap bitmap = null;
private Button btn_cut;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn_cut = (Button) findViewById(R.id.btn_cut);
btn_cut.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
captureScreen();
}
});
}
public void captureScreen() {
Runnable action = new Runnable() {
@Override
public void run() {
final View contentView = getWindow().getDecorView();
try{
Log.e("HEHE",contentView.getHeight()+":"+contentView.getWidth());
bitmap = Bitmap.createBitmap(contentView.getWidth(),
contentView.getHeight(), Bitmap.Config.ARGB_4444);
contentView.draw(new Canvas(bitmap));
ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, byteOut);
savePic(bitmap, "sdcard/short.png");
}catch (Exception e){e.printStackTrace();}
finally {
try{
if (null != byteOut)
byteOut.close();
if (null != bitmap && !bitmap.isRecycled()) {
// bitmap.recycle();
bitmap = null;
}
}catch (IOException e){e.printStackTrace();}
}
}
};
try {
action.run();
} catch (Exception e) {
e.printStackTrace();
}
}
private void savePic(Bitmap b, String strFileName) {
FileOutputStream fos = null;
try {
fos = new FileOutputStream(strFileName);
if (null != fos) {
boolean success= b.compress(Bitmap.CompressFormat.PNG, 100, fos);
fos.flush();
fos.close();
if(success)
Toast.makeText(MainActivity.this, "截屏成功", Toast.LENGTH_SHORT).show();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
~~~
**代码分析**:
> 代码非常简单,final View contentView = getWindow().getDecorView();这句代码是获取当前XML 根节点的View!然后设置截屏的大小,调用下contentView.draw(new Canvas(bitmap));好了,然后 bitmap转换成流,接着写入SD卡,没了~当然从结果我们也可以看出,截图截取的是改APP的内容而已! 如果要截全屏,自行谷歌~!
* * *
## 本节小结:
> 本节给大家讲解下Bitmap,BitmapFactory和他的静态内部类Options,以及BitmapDrawable的 基本使用,其实Bitmap我们知道怎么创建就好了,他的扩展一般是通过Matrix和Canvas来实现的, Bitmap,我们更多的时候关注的是OOM问题,下一节我们就来学习下如何避免Bitmap的OOM问题! 谢谢~![](https://box.kancloud.cn/2015-12-02_565e7982b403f.jpg)
- 第一章——环境搭建和开发相关
- 1.0 Android基础入门教程
- 1.1 背景相关与系统架构分析
- 1.2 开发环境搭建
- 1.2.1 使用Eclipse + ADT + SDK开发Android APP
- 1.2.2 使用Android Studio开发Android APP
- 1.3 SDK更新不了问题解决
- 1.4 Genymotion模拟器安装
- 1.5 GIT教程
- 1.5.1 Git使用教程之本地仓库的基本操作
- 1.5.2 Git之使用GitHub搭建远程仓库
- 1.6 .9(九妹)图片怎么玩
- 1.7 界面原型设计
- 1.8 工程相关解析(各种文件,资源访问)
- 1.9 Android程序签名打包
- 1.11 反编译APK获取代码&资源
- 第二章——Android中的UI组件的详解
- 2.1 View与ViewGroup的概念
- 2.2 布局
- 2.2.1 LinearLayout(线性布局)
- 2.2.2 RelativeLayout(相对布局)
- 2.2.3 TableLayout(表格布局)
- 2.2.4 FrameLayout(帧布局)
- 2.2.5 GridLayout(网格布局)
- 2.2.6 AbsoluteLayout(绝对布局)
- 2.3 表单
- 2.3.1 TextView(文本框)详解
- 2.3.2 EditText(输入框)详解
- 2.3.3 Button(按钮)与ImageButton(图像按钮)
- 2.3.4 ImageView(图像视图)
- 2.3.5.RadioButton(单选按钮)&Checkbox(复选框)
- 2.3.6 开关按钮ToggleButton和开关Switch
- 2.3.7 ProgressBar(进度条)
- 2.3.8 SeekBar(拖动条)
- 2.3.9 RatingBar(星级评分条)
- 2.4 控件
- 2.4.1 ScrollView(滚动条)
- 2.4.2 Date & Time组件(上)
- 2.4.3 Date & Time组件(下)
- 2.4.4 Adapter基础讲解
- 2.4.5 ListView简单实用
- 2.4.6 BaseAdapter优化
- 2.4.7ListView的焦点问题
- 2.4.8 ListView之checkbox错位问题解决
- 2.4.9 ListView的数据更新问题
- 2.5 Adapter类控件
- 2.5.0 构建一个可复用的自定义BaseAdapter
- 2.5.1 ListView Item多布局的实现
- 2.5.2 GridView(网格视图)的基本使用
- 2.5.3 Spinner(列表选项框)的基本使用
- 2.5.4 AutoCompleteTextView(自动完成文本框)的基本使用
- 2.5.5 ExpandableListView(可折叠列表)的基本使用
- 2.5.6 ViewFlipper(翻转视图)的基本使用
- 2.5.7 Toast(吐司)的基本使用
- 2.5.8 Notification(状态栏通知)详解
- 2.5.9 AlertDialog(对话框)详解
- 2.6 对话框控件
- 2.6.0 其他几种常用对话框基本使用
- 2.6.1 PopupWindow(悬浮框)的基本使用
- 2.6.2 菜单(Menu)
- 2.6.3 ViewPager的简单使用
- 2.6.4 DrawerLayout(官方侧滑菜单)的简单使用
- 第三章——Android的事件处理机制
- 3.1.1 基于监听的事件处理机制
- 3.2 基于回调的事件处理机制
- 3.3 Handler消息传递机制浅析
- 3.4 TouchListener PK OnTouchEvent + 多点触碰
- 3.5 监听EditText的内容变化
- 3.6 响应系统设置的事件(Configuration类)
- 3.7 AnsyncTask异步任务
- 3.8 Gestures(手势)
- 第四章——Android的四大组件
- 4.1.1 Activity初学乍练
- 4.1.2 Activity初窥门径
- 4.1.3 Activity登堂入室
- 4.2.1 Service初涉
- 4.2.2 Service进阶
- 4.2.3 Service精通
- 4.3.1 BroadcastReceiver牛刀小试
- 4.3.2 BroadcastReceiver庖丁解牛
- 4.4.1 ContentProvider初探
- 4.4.2 ContentProvider再探——Document Provider
- 4.5.1 Intent的基本使用
- 4.5.2 Intent之复杂数据的传递
- 第五章——Fragment(碎片)
- 5.1 Fragment基本概述
- 5.2.1 Fragment实例精讲——底部导航栏的实现(方法1)
- 5.2.2 Fragment实例精讲——底部导航栏的实现(方法2)
- 5.2.3 Fragment实例精讲——底部导航栏的实现(方法3)
- 5.2.4 Fragment实例精讲——底部导航栏+ViewPager滑动切换页面
- 5.2.5 Fragment实例精讲——新闻(购物)类App列表Fragment的简单实现
- 第六章——Android数据存储与访问
- 6.1 数据存储与访问之——文件存储读写
- 6.2 数据存储与访问之——SharedPreferences保存用户偏好参数
- 6.3.1 数据存储与访问之——初见SQLite数据库
- 6.3.2 数据存储与访问之——又见SQLite数据库
- 第七章——Android网络编程
- 7.1.1 Android网络编程要学的东西与Http协议学习
- 7.1.2 Android Http请求头与响应头的学习
- 7.1.3 Android HTTP请求方式:HttpURLConnection
- 7.1.4 Android HTTP请求方式:HttpClient
- 7.2.1 Android XML数据解析
- 7.2.2 Android JSON数据解析
- 7.3.1 Android 文件上传
- 7.3.2 Android 文件下载(1)
- 7.3.3 Android 文件下载(2)
- 7.4 Android 调用 WebService
- 7.5.1 WebView(网页视图)基本用法
- 7.5.2 WebView和JavaScrip交互基础
- 7.5.3 Android 4.4后WebView的一些注意事项
- 7.5.4 WebView文件下载
- 7.5.5 WebView缓存问题
- 7.5.6 WebView处理网页返回的错误码信息
- 7.6.1 Socket学习网络基础准备
- 7.6.2 基于TCP协议的Socket通信(1)
- 7.6.3 基于TCP协议的Socket通信(2)
- 7.6.4 基于UDP协议的Socket通信
- 第八章——Android绘图与动画基础
- 8.1.1 Android中的13种Drawable小结 Part 1
- 8.1.2 Android中的13种Drawable小结 Part 2
- 8.1.3 Android中的13种Drawable小结 Part 3
- 8.2.1 Bitmap(位图)全解析 Part 1
- 8.2.2 Bitmap引起的OOM问题
- 8.3.1 三个绘图工具类详解
- 8.3.2 绘图类实战示例
- 8.3.3 Paint API之—— MaskFilter(面具)
- 8.3.4 Paint API之—— Xfermode与PorterDuff详解(一)
- 8.3.5 Paint API之—— Xfermode与PorterDuff详解(二)
- 8.3.6 Paint API之—— Xfermode与PorterDuff详解(三)
- 8.3.7 Paint API之—— Xfermode与PorterDuff详解(四)
- 8.3.8 Paint API之—— Xfermode与PorterDuff详解(五)
- 8.3.9 Paint API之—— ColorFilter(颜色过滤器)(1/3)
- 8.3.10 Paint API之—— ColorFilter(颜色过滤器)(2-3)
- 8.3.11 Paint API之—— ColorFilter(颜色过滤器)(3-3)
- 8.3.12 Paint API之—— PathEffect(路径效果)
- 8.3.13 Paint API之—— Shader(图像渲染)
- 8.3.14 Paint几个枚举/常量值以及ShadowLayer阴影效果
- 8.3.15 Paint API之——Typeface(字型)
- 8.3.16 Canvas API详解(Part 1)
- 8.3.17 Canvas API详解(Part 2)剪切方法合集
- 8.3.18 Canvas API详解(Part 3)Matrix和drawBitmapMash
- 8.4.1 Android动画合集之帧动画
- 8.4.2 Android动画合集之补间动画
- 8.4.3 Android动画合集之属性动画-初见
- 8.4.4 Android动画合集之属性动画-又见
- 第九章——Android中的多媒体开发
- 9.1 使用SoundPool播放音效(Duang~)
- 9.2 MediaPlayer播放音频与视频
- 9.3 使用Camera拍照
- 9.4 使用MediaRecord录音
- 第十章——系统服务
- 10.1 TelephonyManager(电话管理器)
- 10.2 SmsManager(短信管理器)
- 10.3 AudioManager(音频管理器)
- 10.4 Vibrator(振动器)
- 10.5 AlarmManager(闹钟服务)
- 10.6 PowerManager(电源服务)
- 10.7 WindowManager(窗口管理服务)
- 10.8 LayoutInflater(布局服务)
- 10.9 WallpaperManager(壁纸管理器)
- 10.10 传感器专题(1)——相关介绍
- 10.11 传感器专题(2)——方向传感器
- 10.12 传感器专题(3)——加速度/陀螺仪传感器
- 10.12 传感器专题(4)——其他传感器了解
- 10.14 Android GPS初涉
- 第十一章——由来、答疑和资源
- 11.0《2015最新Android基础入门教程》完结散花~