Android Camera setPictureFormat и массив данных в onPictureTaken

Здравствуйте, я как раз писал небольшое приложение для Android, которое берет изображение с камеры, и мне было интересно, что на самом деле делает метод параметра камеры setPictureFormat() и какое влияние он оказывает. Насколько я знаю, camera.takePicture() на самом деле предоставляет данные только в обратном вызове JPEG. Итак, я бы подумал, что массив данных, который поступает в onPictureTaken(), в любом случае является данными JPEG? Так почему я должен установить этот параметр, например, на PixelFormat.RGB_565? И есть ли способ напрямую интерпретировать массив данных непосредственно в onPictureTaken() без, например, BitmapFactory.decodeByteArray? Что я нахожу довольно странным, так это то, что у меня есть результирующее изображение с разрешением 2448 * 3264, что соответствует в общей сложности 7990272 пикселям. Однако базовый массив данных, который создал это изображение, имеет длину всего около 2000000 пикселей. Если бы кто-нибудь мог прояснить это для меня, это было бы очень признательно.


person Christian    schedule 18.11.2011    source источник


Ответы (1)


Метод setPictureFormat() применяет формат пикселей для массивов байтов, возвращаемых в необработанных обратных вызовах и обратных вызовах postView, которые вы передаете takePicture(). Как упоминается в документах, эти обратные вызовы МОГУТ даже не происходить на оборудовании, у которого нет буферов для их поддержки, но если они происходят, данные будут отформатированы в соответствии с этим параметром. Вы правы в том, что обратный вызов JPEG передает данные обратно, уже сжатые в формат JPEG.

В вашем примере размер необработанного массива байтов будет варьироваться в зависимости от выбранного формата пикселей. Вы правы, что 2448 * 3264 = 7 990 272 пикселя, но каждый пиксель представлен количеством байтов в массиве. Например, такие форматы, как NV16 или RGB_565, имеют 16 бит (2 байта) для представления каждого пикселя. Это означает, что фактическая длина массива необработанных байтов будет составлять 15 980 554 (~ 15 МБ), что является очень большим объемом данных для одновременного хранения в памяти (это почти весь размер кучи исходного G1). Вот почему не все устройства буферизуют и возвращают необработанные данные изображения.

Когда вы проверяете длину данных, возвращаемых в обратном вызове JPEG, вы просматриваете сжатые данные изображения JPEG, которые больше не являются необработанным растровым изображением. По этой причине результат будет намного меньше. Если бы вы увеличили эти данные изображения JPEG обратно в растровое изображение (например, с помощью BitmapFactory), размер снова увеличился бы. Имейте это в виду, так как изображение такого размера, загруженное в память как растровое изображение ARGB_8888 (4 байта на пиксель), будет потреблять ~ 32 МБ. Это простой путь к OutOfMemoryException в вашем коде.

Надеюсь, это поможет!

person devunwired    schedule 18.11.2011