Added in API level 19

ImageReader


open class ImageReader : AutoCloseable
kotlin.Any
   ↳ android.media.ImageReader

The ImageReader class allows direct application access to image data rendered into a android.view.Surface

Several Android media API classes accept Surface objects as targets to render to, including MediaPlayer, MediaCodec, android.hardware.camera2.CameraDevice, ImageWriter and RenderScript Allocations. The image sizes and formats that can be used with each source vary, and should be checked in the documentation for the specific API.

The image data is encapsulated in Image objects, and multiple such objects can be accessed at the same time, up to the number specified by the maxImages constructor parameter. New images sent to an ImageReader through its Surface are queued until accessed through the acquireLatestImage or acquireNextImage call. Due to memory limits, an image source will eventually stall or drop Images in trying to render to the Surface if the ImageReader does not obtain and release Images at a rate equal to the production rate.

Summary

Nested classes

Builder class for ImageReader objects.

abstract

Callback interface for being notified that a new image is available.

Public methods
open Image!

Acquire the latest Image from the ImageReader's queue, dropping older images.

open Image!

Acquire the next Image from the ImageReader's queue.

open Unit

Free up all the resources associated with this ImageReader.

open Unit

Discard any free buffers owned by this ImageReader.

open Int

The default dataspace of Images.

open Int

The default HardwareBuffer format of Images.

open Int

The default height of Images, in pixels.

open Int

The default image format of Images.

open Int

Maximum number of images that can be acquired from the ImageReader by any time (for example, with acquireNextImage).

open Surface!

Get a Surface that can be used to produce Images for this ImageReader.

open Long

The usage flag of images that can be produced by the ImageReader.

open Int

The default width of Images, in pixels.

open static ImageReader
newInstance(width: Int, height: Int, format: Int, maxImages: Int)

Create a new reader for images of the desired size and format.

open static ImageReader
newInstance(width: Int, height: Int, format: Int, maxImages: Int, usage: Long)

Create a new reader for images of the desired size, format and consumer usage flag.

open Unit

Register a listener to be invoked when a new image becomes available from the ImageReader.

Protected methods
open Unit

Public methods

acquireLatestImage

Added in API level 19
open fun acquireLatestImage(): Image!

Acquire the latest Image from the ImageReader's queue, dropping older images. Returns null if no new image is available.

This operation will acquire all the images possible from the ImageReader, but close all images that aren't the latest. This function is recommended to use over acquireNextImage for most use-cases, as it's more suited for real-time processing.

Note that maxImages should be at least 2 for acquireLatestImage to be any different than acquireNextImage - discarding all-but-the-newest Image requires temporarily acquiring two Images at once. Or more generally, calling acquireLatestImage with less than two images of margin, that is (maxImages - currentAcquiredImages < 2) will not discard as expected.

This operation will fail by throwing an IllegalStateException if maxImages have been acquired with acquireLatestImage or acquireNextImage. In particular a sequence of acquireLatestImage calls greater than getMaxImages without calling Image.close in-between will exhaust the underlying queue. At such a time, IllegalStateException will be thrown until more images are released with Image.close.

Return
Image! latest frame of image data, or null if no image data is available.
Exceptions
java.lang.IllegalStateException if too many images are currently acquired

acquireNextImage

Added in API level 19
open fun acquireNextImage(): Image!

Acquire the next Image from the ImageReader's queue. Returns null if no new image is available.

Warning: Consider using acquireLatestImage() instead, as it will automatically release older images, and allow slower-running processing routines to catch up to the newest frame. Usage of acquireNextImage is recommended for batch/background processing. Incorrectly using this function can cause images to appear with an ever-increasing delay, followed by a complete stall where no new images seem to appear.

This operation will fail by throwing an IllegalStateException if maxImages have been acquired with acquireNextImage or acquireLatestImage. In particular a sequence of acquireNextImage or acquireLatestImage calls greater than maxImages without calling Image.close in-between will exhaust the underlying queue. At such a time, IllegalStateException will be thrown until more images are released with Image.close.

Return
Image! a new frame of image data, or null if no image data is available.
Exceptions
java.lang.IllegalStateException if maxImages images are currently acquired

close

Added in API level 19
open fun close(): Unit

Free up all the resources associated with this ImageReader.

After calling this method, this ImageReader can not be used. Calling any methods on this ImageReader and Images previously provided by acquireNextImage or acquireLatestImage will result in an IllegalStateException, and attempting to read from ByteBuffers returned by an earlier Plane#getBuffer call will have undefined behavior.

Exceptions
java.lang.Exception if this resource cannot be closed

discardFreeBuffers

Added in API level 28
open fun discardFreeBuffers(): Unit

Discard any free buffers owned by this ImageReader.

Generally, the ImageReader caches buffers for reuse once they have been allocated, for best performance. However, sometimes it may be important to release all the cached, unused buffers to save on memory.

Calling this method will discard all free cached buffers. This does not include any buffers associated with Images acquired from the ImageReader, any filled buffers waiting to be acquired, and any buffers currently in use by the source rendering buffers into the ImageReader's Surface.

The ImageReader continues to be usable after this call, but may need to reallocate buffers when more buffers are needed for rendering.

getHeight

Added in API level 19
open fun getHeight(): Int

The default height of Images, in pixels.

The height may be overridden by the producer sending buffers to this ImageReader's Surface. If so, the actual height of the images can be found using Image.getHeight.

Return
Int the expected height of an Image

getImageFormat

Added in API level 19
open fun getImageFormat(): Int

The default image format of Images.

Some color formats may be overridden by the producer sending buffers to this ImageReader's Surface if the default color format allows. ImageReader guarantees that all Images acquired from ImageReader (for example, with acquireNextImage) will have a "compatible" format to what was specified in #newInstance. As of now, each format is only compatible to itself. The actual format of the images can be found using Image.getFormat.

Use this function if the ImageReader instance is created by factory method newInstance function or by builder pattern ImageReader.Builder and using Builder.setImageFormat.

Return
Int the expected format of an Image

getMaxImages

Added in API level 19
open fun getMaxImages(): Int

Maximum number of images that can be acquired from the ImageReader by any time (for example, with acquireNextImage).

An image is considered acquired after it's returned by a function from ImageReader, and until the Image is closed to release the image back to the ImageReader.

Attempting to acquire more than maxImages concurrently will result in the acquire function throwing a IllegalStateException. Furthermore, while the max number of images have been acquired by the ImageReader user, the producer enqueueing additional images may stall until at least one image has been released.

Return
Int Maximum number of images for this ImageReader.

getSurface

Added in API level 19
open fun getSurface(): Surface!

Get a Surface that can be used to produce Images for this ImageReader.

Until valid image data is rendered into this Surface, the acquireNextImage method will return null. Only one source can be producing data into this Surface at the same time, although the same Surface can be reused with a different API once the first source is disconnected from the Surface.

Please note that holding on to the Surface object returned by this method is not enough to keep its parent ImageReader from being reclaimed. In that sense, a Surface acts like a weak reference to the ImageReader that provides it.

Return
Surface! A Surface to use for a drawing target for various APIs.

getWidth

Added in API level 19
open fun getWidth(): Int

The default width of Images, in pixels.

The width may be overridden by the producer sending buffers to this ImageReader's Surface. If so, the actual width of the images can be found using Image.getWidth.

Return
Int the expected width of an Image

newInstance

Added in API level 19
open static fun newInstance(
    width: Int,
    height: Int,
    format: Int,
    maxImages: Int
): ImageReader

Create a new reader for images of the desired size and format.

The maxImages parameter determines the maximum number of Image objects that can be be acquired from the ImageReader simultaneously. Requesting more buffers will use up more memory, so it is important to use only the minimum number necessary for the use case.

The valid sizes and formats depend on the source of the image data.

If the format is PRIVATE, the created ImageReader will produce images that are not directly accessible by the application. The application can still acquire images from this ImageReader, and send them to the camera for reprocessing via ImageWriter interface. However, the getPlanes() will return an empty array for PRIVATE format images. The application can check if an existing reader's format by calling getImageFormat().

PRIVATE format ImageReaders are more efficient to use when application access to image data is not necessary, compared to ImageReaders using other format such as YUV_420_888.

Parameters
width Int: The default width in pixels of the Images that this reader will produce. Value is 1 or greater
height Int: The default height in pixels of the Images that this reader will produce. Value is 1 or greater
format Int: The format of the Image that this reader will produce. This must be one of the android.graphics.ImageFormat or android.graphics.PixelFormat constants. Note that not all formats are supported, like ImageFormat.NV21. Value is android.graphics.ImageFormat#UNKNOWN, android.graphics.PixelFormat#RGBA_8888, android.graphics.PixelFormat#RGBX_8888, android.graphics.PixelFormat#RGB_888, android.graphics.ImageFormat#RGB_565, android.graphics.ImageFormat#YV12, android.graphics.ImageFormat#Y8, android.graphics.ImageFormat.Y16, android.graphics.ImageFormat#YCBCR_P010, android.graphics.ImageFormat#YCBCR_P210, android.graphics.ImageFormat#NV16, android.graphics.ImageFormat#NV21, android.graphics.ImageFormat#YUY2, android.graphics.ImageFormat#JPEG, android.graphics.ImageFormat#DEPTH_JPEG, android.graphics.ImageFormat#YUV_420_888, android.graphics.ImageFormat#YUV_422_888, android.graphics.ImageFormat#YUV_444_888, android.graphics.ImageFormat#FLEX_RGB_888, android.graphics.ImageFormat#FLEX_RGBA_8888, android.graphics.ImageFormat#RAW_SENSOR, android.graphics.ImageFormat#RAW_PRIVATE, android.graphics.ImageFormat#RAW10, android.graphics.ImageFormat#RAW12, android.graphics.ImageFormat#DEPTH16, android.graphics.ImageFormat#DEPTH_POINT_CLOUD, android.graphics.ImageFormat.RAW_DEPTH, android.graphics.ImageFormat.RAW_DEPTH10, android.graphics.ImageFormat#PRIVATE, android.graphics.ImageFormat#HEIC, android.graphics.ImageFormat.HEIC_ULTRAHDR, or android.graphics.ImageFormat#JPEG_R
maxImages Int: The maximum number of images the user will want to access simultaneously. This should be as small as possible to limit memory use. Once maxImages Images are obtained by the user, one of them has to be released before a new Image will become available for access through acquireLatestImage() or acquireNextImage(). Must be greater than 0. Value is 1 or greater
Return
ImageReader This value cannot be null.

newInstance

Added in API level 29
open static fun newInstance(
    width: Int,
    height: Int,
    format: Int,
    maxImages: Int,
    usage: Long
): ImageReader

Create a new reader for images of the desired size, format and consumer usage flag.

The maxImages parameter determines the maximum number of Image objects that can be be acquired from the ImageReader simultaneously. Requesting more buffers will use up more memory, so it is important to use only the minimum number necessary for the use case.

The valid sizes and formats depend on the source of the image data.

The format and usage flag combination describes how the buffer will be used by consumer end-points. For example, if the application intends to send the images to android.media.MediaCodec or android.media.MediaRecorder for hardware video encoding, the format and usage flag combination needs to be PRIVATE and HardwareBuffer.USAGE_VIDEO_ENCODE. When an ImageReader object is created with a valid size and such format/usage flag combination, the application can send the images to an ImageWriter that is created with the input android.view.Surface provided by the android.media.MediaCodec or android.media.MediaRecorder.

If the format is PRIVATE, the created ImageReader will produce images that are not directly accessible by the application. The application can still acquire images from this ImageReader, and send them to the camera for reprocessing, or to the android.media.MediaCodec / android.media.MediaRecorder for hardware video encoding via ImageWriter interface. However, the getPlanes() will return an empty array for PRIVATE format images. The application can check if an existing reader's format by calling getImageFormat().

PRIVATE format ImageReaders are more efficient to use when application access to image data is not necessary, compared to ImageReaders using other format such as YUV_420_888.

Note that not all format and usage flag combinations are supported by the ImageReader. Below are the supported combinations by the ImageReader (assuming the consumer end-points support the such image consumption, e.g., hardware video encoding).

Format Compatible usage flags
non-PRIVATE formats defined by ImageFormat or PixelFormat HardwareBuffer.USAGE_CPU_READ_RARELY or HardwareBuffer.USAGE_CPU_READ_OFTEN
android.graphics.ImageFormat#PRIVATE HardwareBuffer.USAGE_VIDEO_ENCODE or HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE, or combined
Using other combinations may result in IllegalArgumentException. Additionally, specifying HardwareBuffer.USAGE_CPU_WRITE_RARELY or HardwareBuffer.USAGE_CPU_WRITE_OFTEN and writing to the ImageReader's buffers might break assumptions made by some producers, and should be used with caution.

If the ImageReader is used as an output target for a , and if the usage flag contains HardwareBuffer.USAGE_VIDEO_ENCODE, the timestamps of the images produced by the ImageReader won't be in the same timebase as android.os.SystemClock#elapsedRealtimeNanos, even if android.hardware.camera2.CameraCharacteristics#SENSOR_INFO_TIMESTAMP_SOURCE is android.hardware.camera2.CameraCharacteristics#SENSOR_INFO_TIMESTAMP_SOURCE_REALTIME. Instead, the timestamps will be roughly in the same timebase as in android.os.SystemClock#uptimeMillis, so that A/V synchronization could work for video recording. In this case, the timestamps from the ImageReader with HardwareBuffer.USAGE_VIDEO_ENCODE usage flag may not be directly comparable with timestamps of other streams or capture result metadata.

Parameters
width Int: The default width in pixels of the Images that this reader will produce. Value is 1 or greater
height Int: The default height in pixels of the Images that this reader will produce. Value is 1 or greater
format Int: The format of the Image that this reader will produce. This must be one of the android.graphics.ImageFormat or android.graphics.PixelFormat constants. Note that not all formats are supported, like ImageFormat.NV21. Value is android.graphics.ImageFormat#UNKNOWN, android.graphics.PixelFormat#RGBA_8888, android.graphics.PixelFormat#RGBX_8888, android.graphics.PixelFormat#RGB_888, android.graphics.ImageFormat#RGB_565, android.graphics.ImageFormat#YV12, android.graphics.ImageFormat#Y8, android.graphics.ImageFormat.Y16, android.graphics.ImageFormat#YCBCR_P010, android.graphics.ImageFormat#YCBCR_P210, android.graphics.ImageFormat#NV16, android.graphics.ImageFormat#NV21, android.graphics.ImageFormat#YUY2, android.graphics.ImageFormat#JPEG, android.graphics.ImageFormat#DEPTH_JPEG, android.graphics.ImageFormat#YUV_420_888, android.graphics.ImageFormat#YUV_422_888, android.graphics.ImageFormat#YUV_444_888, android.graphics.ImageFormat#FLEX_RGB_888, android.graphics.ImageFormat#FLEX_RGBA_8888, android.graphics.ImageFormat#RAW_SENSOR, android.graphics.ImageFormat#RAW_PRIVATE, android.graphics.ImageFormat#RAW10, android.graphics.ImageFormat#RAW12, android.graphics.ImageFormat#DEPTH16, android.graphics.ImageFormat#DEPTH_POINT_CLOUD, android.graphics.ImageFormat.RAW_DEPTH, android.graphics.ImageFormat.RAW_DEPTH10, android.graphics.ImageFormat#PRIVATE, android.graphics.ImageFormat#HEIC, android.graphics.ImageFormat.HEIC_ULTRAHDR, or android.graphics.ImageFormat#JPEG_R
maxImages Int: The maximum number of images the user will want to access simultaneously. This should be as small as possible to limit memory use. Once maxImages Images are obtained by the user, one of them has to be released before a new Image will become available for access through acquireLatestImage() or acquireNextImage(). Must be greater than 0. Value is 1 or greater
usage Long: The intended usage of the images produced by this ImageReader. See the usages on HardwareBuffer for a list of valid usage bits. See also HardwareBuffer.isSupported(int, int, int, int, long) for checking if a combination is supported. If it's not supported this will throw an IllegalArgumentException. Value is either 0 or a combination of android.hardware.HardwareBuffer#USAGE_CPU_READ_RARELY, android.hardware.HardwareBuffer#USAGE_CPU_READ_OFTEN, android.hardware.HardwareBuffer#USAGE_CPU_WRITE_RARELY, android.hardware.HardwareBuffer#USAGE_CPU_WRITE_OFTEN, android.hardware.HardwareBuffer#USAGE_GPU_SAMPLED_IMAGE, android.hardware.HardwareBuffer#USAGE_GPU_COLOR_OUTPUT, android.hardware.HardwareBuffer#USAGE_COMPOSER_OVERLAY, android.hardware.HardwareBuffer#USAGE_PROTECTED_CONTENT, android.hardware.HardwareBuffer#USAGE_VIDEO_ENCODE, android.hardware.HardwareBuffer#USAGE_GPU_DATA_BUFFER, android.hardware.HardwareBuffer#USAGE_SENSOR_DIRECT_DATA, android.hardware.HardwareBuffer#USAGE_GPU_CUBE_MAP, android.hardware.HardwareBuffer#USAGE_GPU_MIPMAP_COMPLETE, and android.hardware.HardwareBuffer#USAGE_FRONT_BUFFER
Return
ImageReader This value cannot be null.

setOnImageAvailableListener

Added in API level 19
open fun setOnImageAvailableListener(
    listener: ImageReader.OnImageAvailableListener!,
    handler: Handler!
): Unit

Register a listener to be invoked when a new image becomes available from the ImageReader.

Parameters
listener ImageReader.OnImageAvailableListener!: The listener that will be run.
handler Handler!: The handler on which the listener should be invoked, or null if the listener should be invoked on the calling thread's looper.
Exceptions
java.lang.IllegalArgumentException If no handler specified and the calling thread has no looper.

Protected methods

finalize

Added in API level 19
protected open fun finalize(): Unit
Exceptions
java.lang.Throwable the Exception raised by this method