【Android】一款常用的图像转换操作库

3,951 阅读9分钟

前言功能说明图像格式说明接口说明ImageFormat枚举类枚举类FilterModeImageInfoYuvUtils类2.1 Bitmap转换成其他图像格式2.2 各种格式的图像之间互相转换2.3 各种格式的图像转换成Bitmap2.4 各种格式图像的旋转和裁剪操作2.5 各种格式图像经过旋转和裁剪转换成相关Bitmap2.6 各种格式图像的镜面翻转操作2.7 各种格式图像的缩放操作ImageUtilsNV21 格式图像操作I420 格式图像操作


前言

日常开发中,当涉及到 AndroidCamera 或者图像相关的开发,或多或少都会接触一些图像格式,这些不同的格式之间会涉及到各种各样的操作,这里利用 Google 的开源框架 libyuv 封装了一个图像操作库,涉及到了 Android 中常用的图像转换操作。


功能说明

    支持 RGB_565ARGB_8888RGB24I420NV21 5中格式图像之间互相转换操作

    支持将 Bitmap 转换成以上五种图像格式操作

    支持将以上格式的图像转换成 Bitmap 操作

    支持以上格式图像之间互相旋转裁剪操作

    支持以上格式图像之间缩放操作

    支持以上格式图像之间镜像操作

    底层依赖 libyuv 框架,安全、稳定、高效


图像格式说明

关于图像格式说明可参见这里:Android中常用图像格式说明

接口说明

常用图像格式转换库地址:ImageUtils

ImageFormat枚举类

这个类主要用于说明目前支持的数据转换的格式,具体如下:

enum class ImageFormat(var format: Int) {
    NV21(1),
    I420(2),
    RGB_565(3),
    RGB_888(4),
    ARGB_8888(5)
}

关于以上数据格式详细说明,请参见:Android中常用图像格式说明


枚举类FilterMode

这个枚举类,主要说明对图像进行缩放的时候支持的过滤模式,具体如下:

enum class FilterMode(var filter: Int) {
    FilterNone(0),
    FilterLinear(1),
    FilterBilinear(2),
    FilterBox(3)
}

关于过滤模式的说明,请参见:filtering.md


ImageInfo

这个类主要用于辅助图像数据进行旋转裁剪,具体如下:

class ImageInfo(
    val data: ByteArray,
    val dataFormat: ImageFormat,
    val width: Int,
    val height: Int,
    @RotateDegree val degree: Int = 0,
    val rect: Rect? = null,
    val targetFormat: ImageFormat,
    val priorityClip: Boolean = true
)

具体参数说明如下:

  • data:源图像数据
  • dataFormat:源图像数据格式,支持的格式参见 ImageFormat
  • width:源图像的宽
  • height:源图像的高
  • degree:需要旋转的角度
  • rect:需要裁剪的矩形坐标 Rect,可以为 null ,表示不进行裁剪
  • targetFormat:处理后的图像格式,支持的格式参见 ImageFormat
  • priorityClip:使用优先裁剪,默认为 ture,这个参数很重要,后面会说

YuvUtils类

此类为该库的核心类

2.1 Bitmap转换成其他图像格式

主要有5个接口:

external fun bitmapToNV21(bitmap: Bitmap?): ByteArray?
external fun bitmapToRgb565(bitmap: Bitmap?): ByteArray?
external fun bitmapToRgb24(bitmap: Bitmap?): ByteArray?
external fun bitmapToRgba(bitmap: Bitmap?): ByteArray?
external fun bitmapToI420(bitmap: Bitmap?): ByteArray?
  • 关于参数 bitmap ,目前仅支持 RGB_565RGBA_8888 两种类型的位图转换

2.2 各种格式的图像之间互相转换

external fun imageFormatConvert(
    dataByteArray,
    width: Int,
    height: Int,
    @SupportFormat dataFormat: Int,
    @SupportFormat targetFormat: Int
)
: ByteArray?

参数说明:

  • data:源图像数据

  • width:图像的宽

  • height:图像的高

  • dataFormat:源图像格式,支持的图像格式,可参见 ImageFormat 枚举类

  • targetFormat:需要转换成的图像格式,支持的图像格式,可参见 ImageFormat 枚举类

  • 返回值:返回转换后的数据

    例如一个分辨率为 640 * 480NV21 格式的数据,现在需要将它转换成 RGB24 格式,我们可以这么调用:

YuvUtils.imageFormatConvert(data64048014)

2.3 各种格式的图像转换成Bitmap

external fun imageToBitmap(
    dataByteArray,
    width: Int,
    height: Int,
    @SupportFormat dataFormat: Int,
    bitmapConfig: Int
)
:Bitmap?

参数说明:

  • data:源图像数据
  • width:图像的宽
  • height:图像的高
  • dataFormat:源图像格式,支持的图像格式,可参见 ImageFormat 枚举类
  • bitmapConfig:需要转换成的Bitmap格式,目前仅支持 RGB565ARGB_8888 两种格式的 Bitmap
  • 返回值:返回转换后的 Bitmap

2.4 各种格式图像的旋转和裁剪操作

external fun dataClipRotate(
    dataByteArray,
    @SupportFormat dataFormat: Int,
    width: Int,
    height: Int,
    @RotateDegree degree: Int,
    rect: Rect?,
    targetFormat: Int,
    priorityClip: Boolean
)
: ByteArray?

参数说明:

  • data:源图像数据
  • dataFormat:源图像格式,支持的图像格式,可参见 ImageFormat 枚举类
  • width:图像的宽
  • height:图像的高
  • degree:图像旋转的角度,仅支持 090180270 四个角度
  • rect:裁剪的矩形坐标,可以为 null,表示不进行裁剪操作
  • targetFormat:需要转换成的目标图像格式,支持的图像格式,可参见 ImageFormat 枚举类
  • priorityClip:是否进行优先裁剪操作,先裁剪再旋转和先旋转再裁剪是两种不同的操作
  • 返回值:返回转换后的数据

例如:

YuvUtils.dataClipRotate(
            rgba_data, 5, width, height, 90,
            Rect(1000300300), 5false
        )
image
image

从上面的操作可以看出,priorityClip的选择其实还是很重要的!

2.5 各种格式图像经过旋转和裁剪转换成相关Bitmap

external fun dataClipRotateToBitmap(
    dataByteArray,
    @SupportFormat dataFormat: Int,
    width: Int,
    height: Int,
    @RotateDegree degree: Int,
    rect: Rect?,
    bitmapConfig: Int,
    priorityClip: Boolean
)
: Bitmap?

参数说明:

  • data:源图像数据
  • dataFormat:源图像格式,支持的图像格式,可参见 ImageFormat 枚举类
  • width:图像的宽
  • height:图像的高
  • degree:图像旋转的角度,仅支持 090180270 四个角度
  • rect:裁剪的矩形坐标,可以为 null,表示不进行裁剪操作
  • bitmapConfig:需要转换成的 Bitmap 格式,目前仅支持 RGB565ARGB_8888 两种格式的 Bitmap
  • priorityClip:是否进行优先裁剪操作,先裁剪再旋转和先旋转再裁剪是两种不同的操作
  • 返回值:返回转换后的 Bitmap

2.6 各种格式图像的镜面翻转操作

external fun dataMirror(
    dataByteArray,
    width: Int,
    height: Int,
    @SupportFormat dataFormat: Int,
    @SupportFormat targetFormat: Int,
    isVerticalMirror: Boolean = false
)
: ByteArray?

参数说明:

  • data:源图像数据
  • width:图像的宽
  • height:图像的高
  • dataFormat:源图像格式,支持的图像格式,可参见 ImageFormat 枚举类
  • targetFormat:需要转换成的图像格式,支持的图像格式,可参见 ImageFormat 枚举类
  • isVerticalMirror:是否执行垂直镜像操作,默认false,即水平翻转,若为true,即对图像进行了 180 旋转,而并非真正的垂直镜像
  • 返回值:返回转换后的数据

关于 isVerticalMirror 区别,请看下图:

image
image

2.7 各种格式图像的缩放操作

external fun dataScale(
    dataByteArray,
    width: Int,
    height: Int,
    dstWidth: Int,
    dstHeight: Int,
    @SupportFormat dataFormat: Int,
    @SupportFormat targetFormat: Int,
    @SupportFilter filterMode: Int = 0
)
: ByteArray?

参数说明:

  • data:源图像数据
  • width:图像的宽
  • height:图像的高
  • dstWidth:目标图像的宽
  • dstHeight:目标图像的高
  • dataFormat:源图像格式,支持的图像格式,可参见 ImageFormat 枚举类
  • targetFormat:需要转换成的图像格式,支持的图像格式,可参见 ImageFormat 枚举类

ImageUtils

ImageUtils 该类是对 YuvUtils 类的二次包装,以每种图像格式进行操作,方便外界更便捷的调用。

NV21 格式图像操作

关于 NV21 格式的图像相关操作方法如下:

方法 方法说明
nv21ToI420 NV21 格式图像数据转换成 I420 格式的数据
nv21ToRgb565 NV21 格式图像数据转换成 RGB_565 格式的数据
nv21ToRgb24 NV21 格式图像数据转换成 RGB24 格式的数据
nv21ToRgba NV21 格式图像数据转换成 ARGB_8888 格式的数据
nv21ToBitmap8888 NV21 格式图像数据转换成 ARGB_8888 格式的 Bitmap
nv21ToBitmap565 NV21 格式图像数据转换成 RGB_565 格式的 Bitmap
nv21Rotate NV21 格式图像数据旋转操作
nv21Clip NV21 格式图像数据裁剪操作
nv21Mirror NV21 格式图像数据水平镜像操作
nv21Scale NV21 格式图像数据缩放操作
bitmapToNV21 Bitmap 转换成 NV21 格式数据

I420 格式图像操作

关于 I420 格式的图像相关操作方法如下:

方法 方法说明
i420ToNV21 I420 格式图像数据转换成 NV21 格式的数据
i420ToRgb565 I420 格式图像数据转换成 RGB_565 格式的数据
i420ToRgb24 I420 格式图像数据转换成 RGB24 格式的数据
i420ToRgba I420 格式图像数据转换成 ARGB_8888 格式的数据
i420ToBitmap8888 I420 格式图像数据转换成 ARGB_8888 格式的 Bitmap
i420ToBitmap565 I420 格式图像数据转换成 RGB_565 格式的 Bitmap
i420Rotate I420 格式图像数据旋转操作
i420Clip I420 格式图像数据裁剪操作
i420Mirror I420 格式图像数据水平镜像操作
i420Scale I420 格式图像数据缩放操作
bitmapToI420 Bitmap 转换成 I420 格式数据

RGB24RGB_565 以及 ARGB_8888 这三种格式的数据操作跟上面的相关接口方法类似,这里不一一展示了;另外存在的一些接口均为对YuvUtils接口的包装,基本操作都类似,不再说明。