章节索引 :

位图:Bitmap

在上一节学习 Drawable 图像资源的时候我们在很多地方用到了 bitmap,bitmap 其实就是真实图片在 Android 中最直接的表现形式,这一节我们来仔细学习一下 Bitmap 的使用。

1. 什么是 Bitmap

Bitmap 在 Android 中对应一张图片文件,它是一个二位系统,通过编码记录了一张图片的完整形式。以左上角为原点,向右和向下建立一个(X , Y)坐标系,坐标系中的每一个点都成为一个“像素”。在不同编码格式的 Bitmap 里一个像素占的 bit 数有所不同,这些 bit 共同表征了当前像素的色值,可能是8 bit、16 bit 或者 24 bit 等等,最后将这些所有的色值组合起来就成了一张完整的原始图片。

bitmap

我们在 Android 中绘制的一切图像都是一个 Bitmap,我们可以创建一个 Bitmap 示例或者使用 Bitamp 工具来修改、优化一个图像资源。

2. Bitmap 的常用 API

  • createBitmap(int width, int height, Bitmap.Config config):
    根据传入的宽高、创建一个可修改的 Bitmap 对象
  • createBitmap(DisplayMetrics display, int width, int height, Bitmap.Config config):
    相比上一个接口,这个可以在创建的时候传入一些参数
  • createBitmap(Bitmap src):
    根据传入的 Bitamp 创建一个新的 Bitamp
  • copy(Bitmap.Config config, boolean isMutable):
    将 Bitamp 对象的所有像素复制到一个新的 Bitmap 当中
  • extractAlpha():
    提取原始 Bitmap 的透明度并返回一个新的 Bitamp
  • getConfig():
    获取 Bitamp 的配置信息
  • getDensity():
    返回 Bitamp 的图片像素密度
  • getRowBytes():
    返回 Bitamp 图片的像素字节数组
  • setPixel(int x, int y, int color):
    设置图片的(x, y)坐标点上的色值
  • setDensity(int density):
    设置图片像素密度

3. 获取 Bitamp 实例

Android 提供了多种方法获取 Bitamp 实例,我们可以直接从 ImageView 上拿到当前设置的图片的 Bitamp 对象:

private Bitmap bmp;
private ImageView img;
img = (ImageView)findViewById(R.id.imageView);
BitmapDrawable  drawable = (BitmapDrawable)img.getDrawable();
bmp = drawable.getBitmap();

从上面的代码中也可以看到我们可以通过 Drawable 的getBitmap()方法从 Drawable 对象中提取出 Bitamp。
Android 还提供了一个 BitampFractory 工厂对象,专门让我们去获取 Bitmap 实例,主要有以下几种常用方法:

// 从资源文件中解码出 Bitmap
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 使用示例

通过这两节的学习,我们知道 Drawable 和 Bitmap 可以相互转换,接下来编写一个示例完成将 ImageView 中的 Drawable 对象保存到本地的示例程序。

4.1 MainActivity 截图功能

package com.emercy.myapplication;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class MainActivity extends Activity {
    static ByteArrayOutputStream byteOut = null;
    private Bitmap bitmap = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button btn_cut = (Button) findViewById(R.id.button);
        btn_cut.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                capture();
            }
        });
    }

    public void capture() {
        Runnable action = new Runnable() {
            @Override
            public void run() {
                final View contentView = getWindow().getDecorView();
                try {
                    bitmap = Bitmap.createBitmap(contentView.getWidth(),
                            contentView.getHeight(), Bitmap.Config.ALPHA_8);
                    contentView.draw(new Canvas(bitmap));
                    ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
                    bitmap.compress(Bitmap.CompressFormat.JPEG, 100, byteOut);
                    save(bitmap);
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    try {
                        if (null != byteOut)
                            byteOut.close();
                        if (null != bitmap && !bitmap.isRecycled()) {
                            bitmap = null;
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }

                }
            }
        };
        try {
            action.run();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void save(Bitmap b) {
        FileOutputStream fos;
        try {
            fos = new FileOutputStream("sdcard/short.png");
            boolean success = b.compress(Bitmap.CompressFormat.PNG, 80, fos);
            fos.flush();
            fos.close();
            if (success) {
                Toast.makeText(MainActivity.this, "截图完成", Toast.LENGTH_SHORT).show();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

capture()方法中,我们获取当前 Activity 的“DecorView”(Activtiy 的顶层 View,我们设置的 CotentView 是其子 View),然后获取 DecorView 的输入流并会转化成 Bitmap,最后直接输出到文件中即可。

4.2 布局文件

这一节的布局文件可以任意,你可以尝试写出各种复杂的 UI 样式,因为上面的capture()方法是从“DecorView”中获取 Bitmap,所以无论你写了多少 View,最终都会通过setContentView()设置到“ContentView”中,而 ContentView 也是在 DecorView 中的,所以无论怎么写都逃离不开截图范围,最后记得加一个 Button 用于触发截屏。

5. 小结

本节进一步讲述了 Andorid 图像相关的内容,相比 Drawable,Bitmap 直接对应一张图片,更加具体。它可以与 Drawable 相互转化,并提供了多种 API 来直接操作一张图片,在做图片裁剪和修改的场景非常适用。

环境搭建,开发相关
Android 系统背景及结构概述 Android 开发环境搭建 Genymotion 的安装与使用 Android 工程解析及使用 Android 程序签名打包
常用 UI 布局
Android 的 UI 根基 View与View Android 线性布局 LinearLayout Android相对布局RelativeLayout Android 表格布局 TableLayout Android 网格布局 GridLayout Android 帧布局 FrameLayout Android绝对布局AbsoluteLayout
基础控件
Android 文本框 TextView Android 文本输入框 EditText 按钮 Button/ImageButton 选择框 RadioButton/Check 开关控件ToggleButton/Switch Android 图片控件 ImageView Android 进度条 ProgressBar Android 拖动条 SeekBar Android 评分条 RatingBar Android 滚动条 ScrollView 轮播滚动视图 ViewFlipper
Adapter 相关控件
Android 适配器 Adapter Android 列表控件 ListView Android 网格视图 GridView Android 下拉选择框 Spinner 自动补全文本框 AutoCompleteText 折叠列表 ExpandableListView
提示类控件
吐司提示:Toast 的使用方法 状态栏通知:Notification 对话框:AlertDialog 悬浮窗:PopupWindow
菜单类控件
菜单:Menu
其他控件
视频页面:ViewPager 侧滑菜单:DrawerLayout
事件处理机制
基于监听的事件处理机制 Handler 消息传递机制 触摸事件分发处理 AsyncTask:异步任务 Android 手势处理
Android 四大组件
活动:Activity 服务:Service 广播接收器:Broadcast Receiver 内容提供者 - Content Provider
数据存储
文件存储 SharedPreferences 存储 数据库:SQLite 的使用
网络编程
HTTP 使用详解 xml 数据解析 JSON 数据解析 网页视图:WebView Socket 网络接口
绘图与动画
图片资源:Drawable 位图:Bitmap
多媒体开发
媒体播放器:MediaPlayer 相机:Camera 音频录制:MediaRecorder
并发编程
多线程