2010-07-26 358 views
18

我正在使用来自相机的previewCallback尝试抓取图像。下面是我使用BitmapFactory.decodeByteArray()返回NULL

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"); 

     } 
}; 

的数据长度代码总是OTU一样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 ::厂返回null”

+0

我回去点击了checkmarks nex t我在这里得到的一些答案。感谢您的信息 – RyoxSinfar 2010-07-27 15:49:48

+0

可能的重复[在Android中从视频图像获取帧](http://stackoverflow.com/questions/1893072/getting-frames-from-video-image-in-android) – Tim 2016-04-07 02:38:36

回答

3

我试图做同样的事情。根据讨论herehere,听起来好像人们没有运气从decodeByteArray()处理Android 2.1/2.2版本的NV21格式。它绝对不适用于我的模拟器或我的Droid Incredible,尽管我认为这会调用本地代码,因此它可能在某些手机上工作,具体取决于驱动程序?

作为一种替代方法,您可以尝试在Java中自己解码NV21(参见上面的链接举例),但这显然太慢而无法在大多数情况下使用。我没有太多的运气试图让CameraPreview发送不同的格式,并且我认为这对于尝试编写可跨不同硬件移植的代码是有问题的。如果您在NDK中编写NV21解码方法,则可能会增加帧率。

显然由于竞争条件,在尝试处理CameraPreview时也存在稳定性问题,尽管我自己并未证实此问题。我认为你可以避免这种情况,并通过使用Android 2.1/2.2中添加的缓冲预览回调方法setPreviewCallbackWithBuffer()来提高帧率。这是在2.1中添加的,但被隐藏到2.2。 To use it in 2.1 you need to hack around the hiding.

有人建议使用MediaRecorder而不是CameraPreview。不幸的是,MediaRecorder似乎更少提供预览帧比CameraPreview,所以我不能推荐该路线。

+0

使用NV21解码上面的链接,我能够得到像素,但在HTC Droid Incredible上的帧速率约为1帧/ 10秒。但是,我认为对像素进行降采样可以将此帧速率提高到某些应用可能使用的速度。 – Chinasaur 2011-01-19 10:36:11

37

好的,希望这会有所帮助。

搜索互联网寻找快速解决方案,并找到了完美的东西。

此作品为Android 2.1的致谢

this page到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是最好的)。从我刚才的答复

+0

有趣;你可以发布帧率的比较吗? – Chinasaur 2011-09-24 19:58:55

+0

我可以,但在LG Optimus C上,FPS几乎相同。在HTC上,FPS是一样的。没有明显的滞后。 – Qix 2011-09-27 02:52:16

+1

很高兴知道;谢谢。我会试一试。 – Chinasaur 2011-09-27 22:32:40

1

更新,但要注意的Qix的答案,这看起来简单

我其实曾与纯Java解码像样的成绩。只要预览尺寸不太大,则帧速率大约为10-15 fps。可悲的是,我的Droid公司的Android 2.3更新似乎已经带走了一些较小的预览大小选项:(我也尝试在从另一个项目中抽取的本地代码中执行此操作,但这是bug,看起来并没有更快对于比较简单的处理我在做什么,所以我没有进一步追究其见my Github为源(包括Java和本机)

-1

尝试像如下:。

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; 
} 
+1

你会更详细地解释你的方法吗? – 2013-07-13 13:06:10

+0

你为什么吞咽异常?不要这样做。 – Qix 2015-03-27 14:23:50

9

你可以试试这个和它正在工作...

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 { 
         } 
        } 
       }