Как преобразовать необработанные данные камеры в растровое изображение на Android

Я получаю необработанные данные камеры rawData типа byte[], формат RGBA, размер 640x480, 4 байта на пиксель, из библиотечной функции. И мне нужно преобразовать его в растровое изображение и отобразить в ImageView на экране.

Я делаю следующее:

byte[] JPEGData = convertToJpeg(rawData, 640, 480, 80);
Bitmap bitmap = BitmapFactory.decodeByteArray(JPEGData , 0, JPEGData .length);    
imageView.setImageBitmap(bitmap);

где функция convertToJpeg():

    public static byte[] convertToJpeg(byte[] buffer, int w, int h, int quality) {
        YuvImage yuv_image = new YuvImage(buffer, ImageFormat.NV21, w, h, null);

        Rect rect = new Rect(0, 0, w, h);
        ByteArrayOutputStream output_stream = new ByteArrayOutputStream();
        yuv_image.compressToJpeg(rect, quality, output_stream);

        Bitmap sourceBmp = BitmapFactory.decodeByteArray(output_stream.toByteArray(), 0, output_stream.size());
        Bitmap destBmp = Bitmap.createScaledBitmap(sourceBmp, (int) (w * 0.75), (int) (h * 0.75), true);

        ByteArrayOutputStream pictureStream = new ByteArrayOutputStream();
        destBmp.compress(CompressFormat.JPEG, quality, pictureStream);
        byte[] pictureByteArray = pictureStream.toByteArray();

        return pictureByteArray;
    }

После decodeByteArray() звонка у меня bitmap.getConfig() == ARGB_8888.

Однако то, что я вижу на экране, представляет собой хаотичную картинку с размытыми зелеными формами того, что было на исходной картинке.

Что с этим не так?


person Alexander Shmuratko    schedule 26.08.2014    source источник
comment
Никто не знает решения?   -  person Alexander Shmuratko    schedule 27.08.2014
comment
Это кажется размытым просто потому, что содержимое растрового изображения закодировано (я думаю, формат NV21). Поэтому, если вы попытаетесь просмотреть его как файл png или jpg, это не сработает. Сначала вам нужно расшифровать его, прежде чем сохранять.   -  person Simon Marquis    schedule 27.08.2014
comment
@ Саймон, не понял тебя. Растровое изображение далее отображается в ImageView следующим образом: (imageView.setBitmap(bitmap));. Что я должен делать?   -  person Alexander Shmuratko    schedule 27.08.2014
comment
Вы должны расшифровать его раньше. Используя эту инструкцию для ImageView, он попытается декодировать его как обычное растровое изображение ARGB. Но byte[] не в формате ARGB. (может быть что-то вроде ЮЫВ)   -  person Simon Marquis    schedule 27.08.2014
comment
@Simon, я делаю: 1) byte[] JPEGData = convertToJpeg(rawData, ...);, где convertToJpeg указано выше. И 2) Bitmap bitmap = BitmapFactory.decodeByteArray(JPEGData , 0, JPEGData .length); Должен ли я декодировать данные, как вы говорите, на шаге 1 или после шага 3?   -  person Alexander Shmuratko    schedule 27.08.2014
comment
Вы должны сделать это в самом начале. В вашем примере byte[] buffer следует преобразовать в формат ARGB. Я думаю, что compressToJpeg ожидает формат ARGB   -  person Simon Marquis    schedule 27.08.2014
comment
Давайте продолжим обсуждение в чате.   -  person Alexander Shmuratko    schedule 27.08.2014
comment
@ Саймон, я только что проверил формат rawData - это RGBA.   -  person Alexander Shmuratko    schedule 27.08.2014


Ответы (2)


Решение оказалось простым. И не нужно конвертировать в JPEG.

Bitmap bm = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
bm.copyPixelsFromBuffer(ByteBuffer.wrap(rawData));
person Alexander Shmuratko    schedule 28.08.2014
comment
Я просто пробую ваш код. Но я получаю сообщение об ошибке java.lang.RuntimeException: буфер недостаточно велик для пикселей @Александр Шмуратко - person Jigar Shekh; 06.11.2015
comment
@JigarShekh Пожалуйста, проверьте правильность ширины и высоты. :) - person Sipty; 15.12.2015
comment
@Sipty Интересно, где можно найти высоту и ширину? - person Pat Marx; 16.03.2016
comment
Если у вас есть доступ к настройкам камеры, вы можете выбрать разрешение захвата напрямую из настроек. Или вы можете попробовать получить его из ImageReader, если вы используете его в качестве вывода для данных камеры. - person Sipty; 17.03.2016

ByteBuffer().rewind, чтобы сбросить позицию буфера до 0, чем решить проблему «буфер недостаточно велик для пикселей»

person Dante    schedule 17.12.2019