BitmapFactory.decodeByteArray () возвращает NULL - PullRequest
20 голосов
/ 26 июля 2010

Я использую PreviewCallback с камеры, чтобы попытаться захватить изображения.Вот код, который я использую

private Camera.PreviewCallback mPrevCallback = new Camera.PreviewCallback() 
{
        public void onPreviewFrame( byte[] data, Camera Cam ) {
                Log.d("CombineTestActivity", "Preview started");
                Log.d("CombineTestActivity", "Data length = " 
                        + data.length );
                currentprev = BitmapFactory.decodeByteArray( data, 0, 
                        data.length );

               if( currentprev == null )
                   Log.d("CombineTestActivity", "currentprev is null" );

                Log.d("CombineTestActivity", "Preview Finished" );

        }
};

длина данных всегда совпадает с 576000.

Также я попытался изменить параметры камеры, чтобы изображение возвращалоськак разные форматы.Вот как это выглядит, когда я это делаю.

mCamera = Camera.open();
camParam = mCamera.getParameters();
camParam.setPreviewFormat( ImageFormat.RGB_565 );
mCamera.setParameters( camParam );
    mCamera.setPreviewCallback( mPrevCallback );

Однако, когда я меняю формат предварительного просмотра и оставляю его по умолчанию для NV21, BitmapFactory.decodeByteArray возвращается как ноль.Я также попытался изменить формат предварительного просмотра на тип JPEG.Я даже получаю оператор отладки в ddms, вот что я получаю

"D / skia (14391): --- SkImageDecoder :: Factory вернул null"

Ответы [ 6 ]

41 голосов
/ 24 сентября 2011

Хорошо, надеюсь, это поможет.

Поискал в интернете в поисках быстрого решения и нашел идеальную вещь.

Работает с Android 2.1

Благодаря off3nsiv3 с этой страницы .

// Convert to JPG
Size previewSize = camera.getParameters().getPreviewSize(); 
YuvImage yuvimage=new YuvImage(data, ImageFormat.NV21, previewSize.width, previewSize.height, null);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
yuvimage.compressToJpeg(new Rect(0, 0, previewSize.width, previewSize.height), 80, baos);
byte[] jdata = baos.toByteArray();

// Convert to Bitmap
Bitmap bmp = BitmapFactory.decodeByteArray(jdata, 0, jdata.length);

Просто небольшая модификация кода off3nsiv3, и все готово. FPS все еще невероятно высок по сравнению с ручным декодированием.

Для приведенного выше кода 80 - это качество JPEG (0 из 100, 100 - лучшее).

7 голосов
/ 31 октября 2013

Вы можете попробовать это, и это работает ...

mCamera.setOneShotPreviewCallback(new Camera.PreviewCallback() {
                @Override
                public void onPreviewFrame(byte[] data, Camera camera) {
                    Camera.Parameters parameters = camera.getParameters();
                    int format = parameters.getPreviewFormat();
                    //YUV formats require more conversion
                    if (format == ImageFormat.NV21 || format == ImageFormat.YUY2 || format == ImageFormat.NV16) {
                        int w = parameters.getPreviewSize().width;
                        int h = parameters.getPreviewSize().height;
                        // Get the YuV image
                        YuvImage yuv_image = new YuvImage(data, format, w, h, null);
                        // Convert YuV to Jpeg
                        Rect rect = new Rect(0, 0, w, h);
                        ByteArrayOutputStream output_stream = new ByteArrayOutputStream();
                        yuv_image.compressToJpeg(rect, 100, output_stream);
                        byte[] byt = output_stream.toByteArray();
                        FileOutputStream outStream = null;
                        try {
                            // Write to SD Card
                            File file = createFileInSDCard(FOLDER_PATH, "Image_"+System.currentTimeMillis()+".jpg");
                            //Uri uriSavedImage = Uri.fromFile(file);
                            outStream = new FileOutputStream(file);
                            outStream.write(byt);
                            outStream.close();
                        } catch (FileNotFoundException e) {
                            e.printStackTrace();
                        } catch (IOException e) {
                            e.printStackTrace();
                        } finally {
                        }
                    }
                }
3 голосов
/ 27 августа 2010

Я пытаюсь сделать то же самое.Исходя из обсуждений здесь и здесь , похоже, что людям не повезло, получив decodeByteArray() для обработки формата NV21 с Android 2.1 / 2.2.Это определенно не работает в моем эмуляторе или на моем Droid Incredible, хотя я думаю, что это вызывает нативный код, поэтому он может работать на некоторых телефонах в зависимости от драйверов?

В качестве альтернативы, вы можете попробовать декодироватьNV21 самостоятельно на Java (см. Ссылку выше для примера), хотя это, по-видимому, слишком медленно, чтобы быть полезным в большинстве случаев.Мне не очень повезло, пытаясь заставить CameraPreview отправлять другой формат, и я ожидаю, что это будет проблематично для попытки написания кода, переносимого на другое оборудование.Если вы написали методы декодирования NV21 в NDK, вы могли бы немного увеличить частоту кадров.

Очевидно, что есть проблемы со стабильностью из-за условий гонки при попытке обработать CameraPreview, хотя я этого не подтвердилвыдать себя.Я думаю, вы могли бы избежать этого, а также немного повысить частоту кадров, используя буферизованный метод обратного вызова предварительного просмотра setPreviewCallbackWithBuffer(), который был добавлен в Android 2.1 / 2.2.Это было добавлено в 2.1, но оставлено скрытым до 2.2. Чтобы использовать его в 2.1, вам нужно взломать укрытие.

Некоторые люди предлагают использовать MediaRecorder вместо CameraPreview.К сожалению, MediaRecorder, по-видимому, обеспечивает еще меньше возможностей для получения кадров предварительного просмотра, чем CameraPreview, поэтому я не могу рекомендовать этот маршрут.

1 голос
/ 24 сентября 2011

Обновление из моего предыдущего ответа, но обратите внимание на ответ Qix, который выглядит проще

У меня действительно были приличные результаты с декодированием на чистой Java.Частота кадров около 10-15 кадров в секунду, если размер предварительного просмотра не слишком велик.К сожалению, обновление Android 2.3 для моего Droid Inc, по-видимому, убрало некоторые из меньших вариантов размера предварительного просмотра :(. Я также пытался сделать это в нативном коде, который я извлек из другого проекта, но это было с ошибкой и, похоже, не быстреечто касается относительно простой обработки, которую я выполнял, поэтому я не стал ее преследовать. См. мой Github для источника (как Java, так и нативного).

0 голосов
/ 27 ноября 2018

Это работает для меня ...

 private Camera.PreviewCallback getPreviewCallback() {
    Log.d("TAG", "previewCallBack ==> " + "getPreviewCallback");
    Camera.PreviewCallback previewBitmap = new Camera.PreviewCallback() {
        @Override
        public void onPreviewFrame(byte[] data, Camera camera) {
            Camera.Size previewSize = camera.getParameters().getPreviewSize();
            YuvImage yuvimage=new YuvImage(data, ImageFormat.NV21, previewSize.width, previewSize.height, null);
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            yuvimage.compressToJpeg(new Rect(0, 0, previewSize.width, previewSize.height), 80, baos);
            byte[] jdata = baos.toByteArray();
            // Convert to Bitmap
            Bitmap bitmap = BitmapFactory.decodeByteArray(jdata, 0, jdata.length);
            Log.d("TAG", "BITMAP ==> " + bitmap);
            runModelInference(bitmap);
        }
    };

    return previewBitmap;
}
0 голосов
/ 13 июля 2013

попробуйте как следует:

    public Bitmap stringtoBitmap(String string) {
    Bitmap bitmap = null;
    try {
        YuvImage yuvimage = new YuvImage(base64.getBytes(),ImageFormat.YUY2, 120, 30, null);
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        yuvimage.compressToJpeg(new Rect(0, 0, 20, 20), 100, baos);
        byte[] jdata = baos.toByteArray();
        bitmap = BitmapFactory.decodeByteArray(jdata, 0, jdata.length);
    } catch (Exception e) {

    }
    return bitmap;
}
...