2012-07-04 31 views
1

我試圖實時保存相機預覽圖像,我的目標是保存至少1fps從預覽躺在表面視圖。 我卡在這個Android保存實時相機預覽圖像

mCamera.setPreviewCallbackWithBuffer(new Camera.PreviewCallback() { 
     private long timestamp=0; 
     public synchronized void onPreviewFrame(byte[] data, Camera camera) { 
      Log.v("CameraTest","Time Gap = "+(System.currentTimeMillis()-timestamp)); 
      timestamp=System.currentTimeMillis(); 
      try{ 
       FileOutputStream out; 
       try { 
        Bitmap bmp=BitmapFactory.decodeByteArray(data,0,data.length); 
        out = new FileOutputStream("/mnt/sdcard/data/pippo.png"); 
        bmp.compress(Bitmap.CompressFormat.PNG, 90, out); 
       } catch (FileNotFoundException e1) { 
        // TODO Auto-generated catch block 
        e1.printStackTrace(); 
       }   
       camera.addCallbackBuffer(data); 
      }catch (Exception e) { 
       Log.e("CameraTest", "addCallbackBuffer error"); 
       return; 
      } 
      return; 
     } 
    }); 

我想,在字節數組中

public synchronized void onPreviewFrame(byte[] data, Camera camera) 

通過包含原始數據圖像,所以我試圖將其轉換爲位圖,保存在SD卡。 我的問題是:

  1. 這是爲了實現我的目標而休業的正確途徑?
  2. 我在日誌中得到這個錯誤SkImageDecoder :: Factory返回null我想它是在位圖轉換相關的,是不是?

歡迎任何建議。 謝謝

到這裏的全部代碼:

import java.io.FileNotFoundException; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.util.Iterator; 
import java.util.List; 
import android.app.Activity; 

import android.graphics.Bitmap; 
import android.graphics.BitmapFactory; 
import android.graphics.ImageFormat; 
import android.hardware.Camera; 
import android.hardware.Camera.ErrorCallback; 
import android.hardware.Camera.Size; 
import android.os.Bundle; 
import android.util.Log; 
import android.view.SurfaceHolder; 
import android.view.SurfaceView; 
import android.view.SurfaceHolder.Callback; 

public class Demo extends Activity { 
    SurfaceView mVideoCaptureView; 
    private Camera mCamera; 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 
     mVideoCaptureView = (SurfaceView) findViewById(R.id.video_capture_surface); 
     SurfaceHolder videoCaptureViewHolder = mVideoCaptureView.getHolder(); 
     videoCaptureViewHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 
     videoCaptureViewHolder.addCallback(new Callback() { 
      public void surfaceDestroyed(SurfaceHolder holder) { 
      } 

      public void surfaceCreated(SurfaceHolder holder) { 
       startVideo(); 
      } 

      public void surfaceChanged(SurfaceHolder holder, int format, 
        int width, int height) { 
      } 
     }); 
    } 
    private void startVideo() { 
     SurfaceHolder videoCaptureViewHolder = null; 
     try { 
      mCamera = Camera.open(); 
     } catch (RuntimeException e) { 
      Log.e("CameraTest", "Camera Open filed"); 
      return; 
     } 
     mCamera.setErrorCallback(new ErrorCallback() { 
      public void onError(int error, Camera camera) { 
      } 
     }); 
     Camera.Parameters parameters = mCamera.getParameters(); 
     parameters.setPreviewFrameRate(30); 
     parameters.setPreviewFpsRange(15000,30000); 
     List<int[]> supportedPreviewFps=parameters.getSupportedPreviewFpsRange(); 
     Iterator<int[]> supportedPreviewFpsIterator=supportedPreviewFps.iterator(); 
     while(supportedPreviewFpsIterator.hasNext()){ 
      int[] tmpRate=supportedPreviewFpsIterator.next(); 
      StringBuffer sb=new StringBuffer(); 
      sb.append("supportedPreviewRate: "); 
      for(int i=tmpRate.length,j=0;j<i;j++){ 
       sb.append(tmpRate[j]+", "); 
      } 
      Log.v("CameraTest",sb.toString()); 
     } 

     List<Size> supportedPreviewSizes=parameters.getSupportedPreviewSizes(); 
     Iterator<Size> supportedPreviewSizesIterator=supportedPreviewSizes.iterator(); 
     while(supportedPreviewSizesIterator.hasNext()){ 
      Size tmpSize=supportedPreviewSizesIterator.next(); 
      Log.v("CameraTest","supportedPreviewSize.width = "+tmpSize.width+"supportedPreviewSize.height = "+tmpSize.height); 
     } 

     mCamera.setParameters(parameters); 
     if (null != mVideoCaptureView) 
      videoCaptureViewHolder = mVideoCaptureView.getHolder(); 
     try { 
      mCamera.setPreviewDisplay(videoCaptureViewHolder); 
     } catch (Throwable t) { 
     } 

     Log.v("CameraTest","Camera PreviewFrameRate = "+mCamera.getParameters().getPreviewFrameRate()); 
     Size previewSize=mCamera.getParameters().getPreviewSize(); 
     int dataBufferSize=(int)(previewSize.height*previewSize.width* 
           (ImageFormat.getBitsPerPixel(mCamera.getParameters().getPreviewFormat())/8.0)); 

     mCamera.addCallbackBuffer(new byte[dataBufferSize]); 
     mCamera.addCallbackBuffer(new byte[dataBufferSize]); 
     mCamera.addCallbackBuffer(new byte[dataBufferSize]); 

     mCamera.setPreviewCallbackWithBuffer(new Camera.PreviewCallback() { 
      private long timestamp=0; 
      public synchronized void onPreviewFrame(byte[] data, Camera camera) { 
       Log.v("CameraTest","Time Gap = "+(System.currentTimeMillis()-timestamp)); 
       timestamp=System.currentTimeMillis(); 
       try{ 
        FileOutputStream out; 
        try { 
         Bitmap bmp=BitmapFactory.decodeByteArray(data,0,data.length); 
         out = new FileOutputStream("/mnt/sdcard/data/pippo.png"); 
         bmp.compress(Bitmap.CompressFormat.PNG, 90, out); 
        } catch (FileNotFoundException e1) { 
         // TODO Auto-generated catch block 
         e1.printStackTrace(); 
        }   
        camera.addCallbackBuffer(data); 
       }catch (Exception e) { 
        Log.e("CameraTest", "addCallbackBuffer error"); 
        return; 
       } 
       return; 
      } 
     }); 
     try { 
      mCamera.startPreview(); 
     } catch (Throwable e) { 
      mCamera.release(); 
      mCamera = null; 
      return; 
     } 
    } 
    private void stopVideo() { 
     if(null==mCamera) 
      return; 
     try { 
      mCamera.stopPreview(); 
      mCamera.setPreviewDisplay(null); 
      mCamera.setPreviewCallbackWithBuffer(null); 
      mCamera.release(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
      return; 
     } 
     mCamera = null; 
    } 
    public void finish(){ 
     stopVideo(); 
     super.finish(); 
    }; 
} 

回答

3

BitmapFactory不知道如何預覽數據從相機進行解碼,因爲它是像素的原始排列,沒有標識信息。這就是爲什麼它拋出一個異常。

您必須自己將數據轉換/解釋爲RGB格式,並從中構建一個位圖。默認情況下,相機提供NV21格式的預覽數據。你可以找到更多關於NV21 here的信息。要創建全色RGB圖像,您需要上採樣兩個色度通道,然後將結果轉換爲RGB。

如果您還可以保存JPEG,您也可以使用YuvImage類。