BitmapFactory.decodeByteArray() возвращает NULL
Я использую 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 возвращается как null. Я также попытался изменить формат предварительного просмотра на формат JPEG. Я даже получаю отладку в ddms, вот что я получаю
"D/skia (14391): --- SkImageDecoder:: Factory возвращает null"
Ответы
Ответ 1
Хорошо, надеюсь, это поможет.
Выбрал интернет, ища быстрое решение, и нашел отличную вещь.
Работает с 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).
Ответ 2
вы можете попробовать это, и он работает...
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
Я пытаюсь сделать то же самое. На основе обсуждений здесь и здесь, это звучит как люди не успели получить 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
, поэтому я не могу рекомендовать этот маршрут.
Ответ 4
Обновление моего предыдущего ответа, но обратите внимание на ответ Qix, который выглядит проще
У меня действительно были приличные результаты с расшифровкой в чистой Java. Раздается около 10-15 кадров в секунду, пока размер предварительного просмотра не слишком большой. К сожалению, обновление Android 2.3 для моего Droid Inc, похоже, убрало некоторые из меньших параметров размера предварительного просмотра:( Я также пробовал делать это в собственном коде, который я вытащил из другого проекта, но это было ошибкой и не казалось более быстрым для относительно простой обработки, которую я делал, поэтому я не преследовал ее дальше. См. мой Github для источника (как Java, так и native).
Ответ 5
попробуйте сделать это следующим образом:
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;
}