Java BitmapFactory.decodeByteArray()返回NULL
我正在使用相机的预览回调来尝试抓取图像。这是我正在使用的代码Java BitmapFactory.decodeByteArray()返回NULL,java,android,image,format,camera,Java,Android,Image,Format,Camera,我正在使用相机的预览回调来尝试抓取图像。这是我正在使用的代码 private Camera.PreviewCallback mPrevCallback = new Camera.PreviewCallback() { public void onPreviewFrame( byte[] data, Camera Cam ) { Log.d("CombineTestActivity", "Preview started");
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”我也在尝试做同样的事情。根据讨论和讨论,从Android 2.1/2.2开始,人们似乎没有运气获得处理NV21格式的
decodeByteArray()
。它在我的模拟器或Droid上肯定不起作用,尽管我认为这会调用本机代码,所以它可能会在某些手机上工作,具体取决于驱动程序
作为替代方案,您可以尝试自己用Java对NV21进行解码(参见上面的链接中的示例),尽管这显然太慢了,对大多数情况下都没有用处。我在尝试让CameraPreview发送一种不同的格式时也没有太多运气,我认为这对于尝试编写跨不同硬件可移植的代码来说是有问题的。如果您在NDK中编写NV21解码方法,您可能会使帧速率提高一点
显然,在尝试处理CameraPreview
的过程中,由于比赛条件,也存在稳定性问题,尽管我自己还没有确认这个问题。我认为您可以通过使用Android 2.1/2.2中添加的缓冲预览回调方法setPreviewCallbackWithBuffer()
,避免这种情况,并提高帧速率。这是在2.1中添加的,但在2.2之前一直隐藏
一些人建议使用
MediaRecorder
而不是CameraPreview
。不幸的是,MediaRecorder
提供的预览帧似乎比CameraPreview
更少,所以我不能推荐这种方法。好吧,希望这会有所帮助
搜索互联网寻找快速解决方案,找到了完美的解决方案
从Android 2.1开始就可以使用
感谢来自的off3nsiv3
只需对off3nsiv3的代码稍加修改,就可以了。与手动解码相比,FPS仍然非常高
对于上面的代码,80是jpeg质量(从100中选择0,100是最好的)。根据我先前的答案进行更新,但请注意Qix的答案,它看起来更简单
事实上,我在纯Java的解码中获得了不错的结果。只要预览大小不太大,帧速率大约为10-15 fps。不幸的是,我的Droid Inc.的Android 2.3更新似乎已经取消了一些较小的预览大小选项:(。我也尝试了使用从另一个项目中提取的本机代码,但这是有缺陷的,对于我正在进行的相对简单的处理,似乎没有任何更快的速度,因此我没有进一步研究。有关源代码,请参阅(Java和本机均可)。尝试以下方法:
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;
}
你可以试试这个,它正在工作
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 {
}
}
}
这对我有用
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;
}
我返回并点击了我在这里得到的一些答案旁边的复选标记。感谢上面链接中使用NV21解码的可能重复信息,我能够获得像素,但在HTC Droid上的帧速率约为1帧/10秒。但是,我相信对像素进行下采样可以获得这帧在某些应用程序中可以使用的最高速度。有趣的是,你可以发布帧速率比较吗?我可以,但在LG Optimus C上,FPS几乎相同。在HTC上,FPS是相同的。没有明显的延迟。真的有必要编码为jpeg(相对较慢的操作)并解码回(同样较慢的操作)吗?@VioletGiraffe在撰写此答案时,确实没有更快的方法。此外,如果您尝试此操作,它是一个相对快速的操作;)没有其他方法将其转换为位图。@Qix我得到的图像更蓝。.我使用的是三星s4制表符。您能详细解释一下您的方法吗?为什么要吞下异常?不要这样做。
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;
}