получение изображения jpg из необработанных данных кадрового буфера

Я могу получить кадровый буфер Android. Но я не знаю, как преобразовать эти необработанные байты в файл изображения jpg. Если я попытаюсь нарисовать изображение на своем ноутбуке с помощью метода java bufferedImage.setpixel. Я получаю неправильное цветное изображение

Process sh = Runtime.getRuntime().exec("su", null,null);    
OutputStream  os = sh.getOutputStream();
os.write("/system/bin/cat /dev/graphics/fb0 > /sdcard/img.raw".getBytes());
os.flush();          
os.close();
sh.waitFor();`

person WSS    schedule 05.03.2013    source источник
comment
Я просто укажу, что пытаться захватить содержимое экрана таким образом не рекомендуется. Даже если вы root, есть устройства, на которых это просто может не поддерживаться. См., например. это сообщение одного из разработчиков NDK в Google   -  person Michael    schedule 09.03.2013


Ответы (1)


На Android в буфере кадров есть 2 или более буферизованных изображения. Поэтому, когда вы копируете, как указано выше, файл fb0, в нем есть как минимум 2 изображения экрана. Вы можете разделить их, выполнив что-то вроде:

dd if=/sdcard/img.raw bs=<width_of_your_screen> \
   count=<height_of_your_screen> of=/sdcard/img-1.raw
dd if=/sdcard/img.raw bs=<width_of_your_screen> \
   count=<times height_of_your_screen> skip=<previous count> of=/sdcard/img-2.raw

Так, например, если ваше устройство имеет разрешение 480x320 и пиксель закодирован в 4 байта, вы можете извлечь 2 последовательных кадра следующим образом:

dd if=/sdcard/img.raw bs=1920 count=320 of=/sdcard/img-1.raw
dd if=/sdcard/img.raw bs=1920 count=320 skip=320 of=/sdcard/img-2.raw

Если в буфере кадров fb0 было 3 изображения:

dd if=/sdcard/img.raw bs=1920 count=320 skip=640 of=/sdcard/img-3.raw

Где:

  • dd — это утилита Linux для копирования и преобразования необработанных файлов с параметрами:

    • if is for 'input file'
    • of для «выходного файла»
    • bs означает «размер блока». В примере 480x4=1920 (480 пикселей в высоту, 4 байта на пиксель)
    • count - подсчитать, сколько «размера блока» нужно прочитать из if и записать в of (т.е. здесь мы читаем/записываем размер ширины)
    • skip для второго изображения — это номер "размера блока", который нужно пропустить (т. е. пропустить номер count из первого изображения).

Вы можете использовать более простую команду, установив размер блока 480x320x4=614400 и count=1, но если вам нужно динамически поддерживать разные размеры экрана, я обнаружил, что разделение bs и count, как в моем примере, проще программировать с параметрами.

Также обратите внимание, что если вы запустите вышеуказанное из оболочки устройства, на вашем устройстве может не быть команды dd. Если вы установили busybox, вы можете заменить dd на busybox dd

Изображения кодируются в зависимости от вашего устройства в формате RGB32, BGR32,... пикселей. Вам нужно перекодировать их, чтобы получить JPG или PNG... В Stackoverflow есть примеры использования ffmpeg. что вы, вероятно, можете найти. Быстрый пример (для устройства RGB32, экран шесть 480x320):

ffmpeg -vframes 1 -vcodec rawvideo -f rawvideo -pix_fmt rgb32 -s 480x320 -i img-1.raw -f image2 -vcodec mjpeg img-1.jpg

Если вы используете ffmpeg, в stackoverflow также есть сообщения о том, как создать его для Android (т.е. https://stackoverflow.com/a/9681231/1012381 )

person JScoobyCed    schedule 09.03.2013
comment
спасибо за ваш драгоценный ответ. Но я не понял ваш приведенный выше четырехстрочный код, например: -keywords (dd, bs, count). Не могли бы вы объяснить это проще? И также эти 2 или более изображения буфера кадра одного и того же время экрана устройства или последовательно? И как узнать длину каждого изображения кадрового буфера? - person WSS; 19.03.2013