2010-07-26 300 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 { 
         } 
        } 
       }