Как выбрать тип буфера ImageReader для приложения камеры Android?

У меня есть приложение с функцией камеры. Я использую Android Camera2 API. Я обнаружил, что некоторые устройства Android (например, Nexus 6p, Nexus 5) работают лучше, если ImageReader настроен на предоставление файлов JPEG:

imageReader = ImageReader.NewInstance(width, height, ImageFormatType.Jpeg, 2);

И некоторые устройства Android (например, Nexus 7 2013) работают лучше, если ImageReader настроен на предоставление, скажем, RGBA_8888:

imageReader = ImageReader.NewInstance(width, height, (ImageFormatType)1 /* PixelFormat.RGBA_8888 */, 2);

Устройство, которое лучше работает с JPEG, выдает эту ошибку, если я использую RGBA_8888:

[ImageReader_JNI] Producer output buffer format: 0x22, ImageReader configured format: 0x1

Устройство, которое лучше работает с буферами RGBA, выдает это предупреждение, если я использую JPEG: (оно все еще работает, но достаточно медленно, чтобы захваченное изображение было темным).

[ImageReader_JNI] ImageReader_lockedImageSetup: Receiving JPEG in HAL_PIXEL_FORMAT_RGBA_8888 buffer.

Мне нужно немного обработать то, что я получаю, поэтому в конечном итоге было бы лучше, если бы я мог настроить камеру так, чтобы она просто выдавала какое-то растровое изображение, а не JPEG, поскольку мне нужно преобразовать JPEG в Bitmap, прежде чем продолжить.

Как мне выбрать, какой тип буфера передать ImageReader?


person Anthony Mills    schedule 08.02.2017    source источник
comment
Каков ваш вариант использования? Одиночные снимки (не много снимков в секунду) или непрерывный захват (~30 кадров в секунду)?   -  person Eddy Talvala    schedule 09.02.2017
comment
У меня есть поверхность предварительного просмотра, которая выполняет непрерывный захват до тех пор, пока вы не нажмете кнопку «Сделать снимок», после чего она выполняет одиночный захват до ImageReader.   -  person Anthony Mills    schedule 09.02.2017


Ответы (1)


Единственными гарантированными форматами, которые должны поддерживать все камеры, являются YUV_420_888 и JPEG; даже при этом устройства уровня LEGACY обычно поддерживают только JPEG с максимальным разрешением (и YUV_420_888 с разрешением предварительного просмотра, как правило, не выше 1080p).

Вы должны проверить список поддерживаемых форматов в StreamConfigurationMap вместо того, чтобы просто слепо пробовать некоторые из них — хотя некоторые устройства могут поддерживать произвольные форматы, не указанные в их официальном списке, нет большой гарантии того, насколько хорошо они будут это делать.

Захват JPEG, как правило, происходит медленнее, потому что устройства уровня LEGACY предполагают, что если вам нужен JPEG, вам нужно максимальное качество захвата неподвижных изображений, что требует больше постобработки, чем просто кадр предварительного просмотра; кроме того, устройства LEGACY могут выполнять замер и срабатывание вспышки. Устройства LIMITED или лучше позволяют контролировать качество постобработки, поэтому оно не привязано к выходному формату, а также обычно поддерживают более высокие разрешения захвата YUV.

Обычно я бы держался подальше от RGBA, если вам нужна широкая поддержка — работа с LEGACY-устройствами немного странная, а LIMITED и лучшие устройства вряд ли будут ее поддерживать.

Когда вы говорите, что JPEG работает, но достаточно медленно, чтобы захваченное изображение было темным, я немного смущен — почему медлительность означает темное изображение? Или вы просто имеете в виду, что изображения получаются темными?

person Eddy Talvala    schedule 09.02.2017
comment
На большинстве моих устройств захват в JPEG работает нормально. Но на этом Nexus 7 2013 года, если я снимаю в YUV, цвета в порядке, но если я снимаю в JPEG, иногда получается темно. Сначала я думал, что это случай остановки повторения кадров предварительного просмотра или что-то в этом роде, но, похоже, это не так. - person Anthony Mills; 10.02.2017