55. 【Android教程】位图:Bitmap

简介: 55. 【Android教程】位图:Bitmap

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

1. 什么是 Bitmap

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

我们在 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 来直接操作一张图片,在做图片裁剪和修改的场景非常适用。

相关文章
|
6月前
|
网络协议 Android开发 数据安全/隐私保护
Android手机上使用Socks5全局代理-教程+软件
Android手机上使用Socks5全局代理-教程+软件
5113 2
|
1月前
|
Android开发 数据安全/隐私保护 虚拟化
安卓手机远程连接登录Windows服务器教程
安卓手机远程连接登录Windows服务器教程
97 4
|
1月前
|
Android开发
布谷语音软件开发:android端语音软件搭建开发教程
语音软件搭建android端语音软件开发教程!
|
3月前
|
存储 缓存 编解码
Android经典面试题之图片Bitmap怎么做优化
本文介绍了图片相关的内存优化方法,包括分辨率适配、图片压缩与缓存。文中详细讲解了如何根据不同分辨率放置图片资源,避免图片拉伸变形;并通过示例代码展示了使用`BitmapFactory.Options`进行图片压缩的具体步骤。此外,还介绍了Glide等第三方库如何利用LRU算法实现高效图片缓存。
75 20
Android经典面试题之图片Bitmap怎么做优化
|
6月前
|
存储 Java Android开发
Android上在两个Activity之间传递Bitmap对象
Android上在两个Activity之间传递Bitmap对象
48 2
|
6月前
|
XML API 开发工具
Android Bitmap 加载与像素操作
Android Bitmap 加载与像素操作
56 2
|
6月前
|
XML 前端开发 API
Android中实现Bitmap在自定义View中的放大与拖动
Android中实现Bitmap在自定义View中的放大与拖动
160 1
|
6月前
|
存储 编解码 Android开发
58. 【Android教程】音频录制:MediaRecord
58. 【Android教程】音频录制:MediaRecord
71 2
|
6月前
|
Android开发
杨老师课堂_安卓教程第一篇之入门
杨老师课堂_安卓教程第一篇之入门
40 0
|
6月前
|
Java Linux 数据库
59. 【Android教程】多线程
59. 【Android教程】多线程
67 0