一、Image概述
android.media.Image
与 MediaCodec 或 CameraDevice 等媒体源一起使用的单个完整图像缓冲区。
此类允许应用程序通过一个或多个 ByteBuffer 高效地直接访问图像的像素数据。 每个缓冲区都封装在 Image.Plane 中,描述该平面中像素数据的布局。 由于这种直接访问,与 Bitmap 类不同,图像不能直接用作 UI 资源。
由于图像通常由硬件组件直接生成或消耗,因此它们是整个系统共享的有限资源,一旦不再需要就应立即关闭。
例如,当使用 ImageReader 类从各种媒体源读取图像时,一旦达到最大未完成图像计数,不关闭旧的 Image 对象将阻止新图像的可用性。 发生这种情况时,获取新图像的函数通常会抛出 IllegalStateException。
二、方法
/**
获取该图像的格式。 该格式决定了表示图像所需的 ByteBuffer 的数量,以及每个 ByteBuffer 中像素数据的总体布局。
格式是 ImageFormat 中的值之一。 格式和平面之间的映射如下:
格式
平面数
布局细节
JPEG
1
压缩数据,因此行和像素步长为 0。要解压缩,请使用 BitmapFactory#decodeByteArray。
YUV_420_888
3
亮度平面后跟 Cb 和 Cr 色度平面。 色度平面的宽度和高度是亮度平面的一半(4:2:0 子采样)。 每个平面中的每个像素样本都有 8 位。 每个平面都有自己的行跨距和像素跨距。
YUV_422_888
3
亮度平面后跟 Cb 和 Cr 色度平面。 色度平面的宽度和高度是亮度平面的一半(4:2:2 子采样)。 每个平面中的每个像素样本都有 8 位。 每个平面都有自己的行跨距和像素跨距。
YUV_444_888
3
亮度平面后跟 Cb 和 Cr 色度平面。 色度平面与亮度平面具有相同的宽度和高度(4:4:4 子采样)。 每个平面中的每个像素样本都有 8 位。 每个平面都有自己的行跨距和像素跨距。
FLEX_RGB_888
3
R(红色)平面,后面是 G(绿色)和 B(蓝色)平面。 所有平面都具有相同的宽度和高度。 每个平面中的每个像素样本都有 8 位。 每个平面都有自己的行跨距和像素跨距。
FLEX_RGBA_8888
4
R(红色)平面,后面是 G(绿色)、B(蓝色)和 A(alpha)平面。 所有平面都具有相同的宽度和高度。 每个平面中的每个像素样本都有 8 位。 每个平面都有自己的行跨距和像素跨距。
RAW_传感器
1
原始传感器图像数据的单个平面,每个颜色样本 16 位。 布局的详细信息需要从原始传感器数据的来源查询,例如CameraDevice。
RAW_PRIVATE
1
私有布局的原始传感器图像数据的单个平面。 布局的细节是特定于实现的。 此格式未定义行跨距和像素跨距。 在 RAW_PRIVATE 图像上调用 Image.Plane.getRowStride() 或 Image.Plane.getPixelStride() 将导致抛出 UnSupportedOperationException。
HEIC
1
压缩数据,因此行和像素步长为 0。要解压缩,请使用 BitmapFactory#decodeByteArray。
YCBCR_P010
1
P010 是 4:2:0 YCbCr 半平面格式,由 WxH Y 平面和后面的 Wx(H/2) CbCr 平面组成。 每个样本都由一个 16 位小端值表示,其中低 6 位设置为零。
*/
public abstract int getFormat();
/**
图像的宽度(以像素为单位)。
对于对某些颜色通道进行二次采样的格式,这是最大分辨率平面的宽度。
*/
public abstract int getWidth();
/**
图像的高度(以像素为单位)。 对于对某些颜色通道进行二次采样的格式,这是最大分辨率平面的高度。
*/
public abstract int getHeight();
/**
获取与该帧关联的时间戳。
时间戳以纳秒为单位,通常单调递增。 来自不同来源的图像的时间戳可能具有不同的时基,因此可能不具有可比性。 时间戳的具体含义和时基取决于提供图像的来源。 有关更多详细信息,请参阅 Camera、CameraDevice、MediaPlayer 和 MediaCodec。
*/
public abstract long getTimestamp();
/**
获取与此框架关联的 SyncFence 对象。
在通过 ImageWriter.dequeueInputImage() 从 ImageWriter 出列的图像上执行 getPlanes() 后,此函数返回无效的 SyncFence。
Return:
此框架的 SyncFence。
Throw:
IOException – 如果 SyncFence 对象返回时出现错误。
*/
public @NonNull SyncFence getFence() throws IOException
/**
使用此框架设置栅栏文件描述符。
Param:
fence – 为此帧设置的 fence 文件描述符。
Throw:
IOException – 如果设置 SyncFence 时出现错误。
*/
public void setFence(@NonNull SyncFence fence) throws IOException
/**
获取用于 GPU 和/或硬件访问的输入图像的 HardwareBuffer 句柄。
调用 Image.close() 后,不得使用返回的 HardwareBuffer。
Return:
与此 Image 关联的 HardwareBuffer 或 null(如果此 Image 不支持此功能)。 (不支持的用例包括通过 MediaCodec 获取的 Image 实例,以及 Android P 之前的版本上的 ImageWriter)。
*/
@Nullable public HardwareBuffer getHardwareBuffer()
/**
设置与该帧关联的时间戳。
时间戳以纳秒为单位,通常单调递增。 来自不同来源的图像的时间戳可能具有不同的时基,因此可能不具有可比性。 时间戳的具体含义和时基取决于提供图像的来源。 有关更多详细信息,请参阅 Camera、CameraDevice、MediaPlayer 和 MediaCodec。
对于通过 ImageWriter.dequeueInputImage() 从 ImageWriter 出列的图像,应用程序需要在将它们发送回 ImageWriter 之前正确设置时间戳,否则时间戳将在调用queueInputImage() 时自动生成。
Param:
时间戳 – 要为此图像设置的时间戳。
*/
public void setTimestamp(long timestamp)
/**
获取与该帧关联的数据空间。
*/
public @NamedDataSpace int getDataSpace()
/**
设置与该帧关联的数据空间。
如果未设置图像的数据空间,则数据空间值取决于 ImageWriter 构造函数中提供的 android.view.Surface。
Param:
dataSpace – 要为此图像设置的数据空间
*/
public void setDataSpace(@NamedDataSpace int dataSpace)
/**
获取与该帧关联的裁剪矩形。
裁剪矩形使用最大分辨率平面中的坐标指定图像中有效像素的区域。
*/
public Rect getCropRect()
/**
设置与该帧关联的裁剪矩形。
裁剪矩形使用最大分辨率平面中的坐标指定图像中有效像素的区域。
*/
public void setCropRect(Rect cropRect)
/**
获取此图像的像素平面数组。 平面的数量由图像的格式决定。 如果图像格式为 PRIVATE,应用程序将得到一个空数组,因为图像像素数据无法直接访问。 应用程序可以通过调用getFormat()来检查图像格式。
*/
public abstract Plane[] getPlanes();
/**
释放此帧以供重复使用。
调用此方法后,在此 Image 上调用任何方法都将导致 IllegalStateException,并且尝试读取或写入早期 Image.Plane.getBuffer 调用返回的 ByteBuffer 将出现未定义的行为。 如果图像是通过 ImageWriter.dequeueInputImage() 从 ImageWriter 获取的,则调用此方法后,应用程序填充的任何图像数据都将丢失,并且图像将返回给 ImageWriter 以供重用。 提供给queueInputImage()的图像会自动关闭。
*/
public abstract void close();
/**
获取图像的所有者。
图像的所有者可以是 ImageReader、ImageWriter、MediaCodec 等。此方法返回生成该图像的所有者,如果图像是独立图像或所有者未知,则返回 null。
这是一个包私有方法,仅在内部使用。
Return:
图像的所有者。
*/
Object getOwner()
/**
获取与该图像关联的本机上下文(缓冲区指针)。
这是一个包私有方法,仅在内部使用。 它可用于获取本机缓冲区指针并传递给本机,该指针可传递给 ImageWriter.attachAndQueueInputImage 以避免反向 JNI 调用。
Return:
与此图像关联的本机上下文。
*/
long getNativeContext()
三、内部抽象类Plane
图像数据的单色平面。
图像中平面的数量和含义由图像的格式决定。
一旦 Image 被关闭,对平面 ByteBuffer 的任何访问都将失败。
/**
此颜色平面的行跨距(以字节为单位)。
这是图像中连续两行像素的起点之间的距离。 请注意,对于某些格式(例如 RAW_PRIVATE),行步幅未定义,并且对这些格式的图像调用 getRowStride 将导致抛出 UnsupportedOperationException。 对于行跨距定义明确的格式,行跨距始终大于 0。
*/
public abstract int getRowStride();
/**
相邻像素样本之间的距离(以字节为单位)。
这是一行像素中两个连续像素值之间的距离。 它可能大于单个像素的大小,以考虑交错图像数据或填充格式。 请注意,对于某些格式(例如 RAW_PRIVATE),像素步幅未定义,并且对这些格式的图像调用 getPixelStride 将导致抛出 UnsupportedOperationException。 对于像素跨度定义明确的格式,像素跨度始终大于 0。
*/
public abstract int getPixelStride();
/**
获取包含帧数据的直接 ByteBuffer。
特别是,返回的缓冲区将始终让 isDirect 返回 true,因此可以将底层数据映射为 JNI 中的指针,而无需使用 GetDirectBufferAddress 进行任何复制。
对于原始格式,每个平面仅保证包含直到最后一行最后一个像素的数据。 换句话说,最后一行之后的步长可能不会映射到缓冲区中。 这是任何交错格式的必要要求。
Return:
包含该平面的图像数据的字节缓冲区。
*/
public abstract ByteBuffer getBuffer();