Android保存实时相机预览图像
我正在尝试实时保存相机预览图像,我的目标是保存曲面视图上预览的至少1fps。 我被困在这上面了Android保存实时相机预览图像,android,android-camera,Android,Android Camera,我正在尝试实时保存相机预览图像,我的目标是保存曲面视图上预览的至少1fps。 我被困在这上面了 mCamera.setPreviewCallbackWithBuffer(new Camera.PreviewCallback() { private long timestamp=0; public synchronized void onPreviewFrame(byte[] data, Camera camera) { Log.v("Cam
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卡上。
我的问题是:
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();
};
}
import java.io.FileNotFoundException;
导入java.io.FileOutputStream;
导入java.io.IOException;
导入java.util.Iterator;
导入java.util.List;
导入android.app.Activity;
导入android.graphics.Bitmap;
导入android.graphics.BitmapFactory;
导入android.graphics.ImageFormat;
导入android.hardware.Camera;
导入android.hardware.Camera.ErrorCallback;
导入android.hardware.Camera.Size;
导入android.os.Bundle;
导入android.util.Log;
导入android.view.SurfaceHolder;
导入android.view.SurfaceView;
导入android.view.SurfaceHolder.Callback;
公共类演示扩展活动{
SurfaceView mVideoCaptureView;
私人摄像机麦卡梅拉;
@凌驾
创建时的公共void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mVideoCaptureView=(SurfaceView)findviewbyd(R.id.video\u capture\u surface);
SurfaceHolder videoCaptureViewHolder=mvideCaptureView.getHolder();
videoCaptureViewHolder.setType(SurfaceHolder.SURFACE类型推送缓冲区);
videoCaptureViewHolder.addCallback(新回调(){
公共空间表面覆盖(表面覆盖物持有人){
}
已创建的公共空白表面(表面持有人){
startVideo();
}
公共无效表面更改(表面文件夹持有者,整数格式,
整数宽度,整数高度){
}
});
}
私有void startVideo(){
SurfaceHolder videoCaptureViewHolder=null;
试一试{
mCamera=Camera.open();
}捕获(运行时异常e){
Log.e(“摄像机测试”、“摄像机开放文件”);
返回;
}
setErrorCallback(新的ErrorCallback(){
公共无效onError(内部错误,摄像头){
}
});
Camera.Parameters=mCamera.getParameters();
参数。setPreviewFrameRate(30);
参数。setPreviewFpsRange(1500030000);
列出supportedPreviewFps=参数。getSupportedPreviewFpsRange();
迭代器supportedPreviewfpsierator=supportedPreviewFps.Iterator();
while(supportedPreviewfpsierator.hasNext()){
int[]tmpRate=supportedPreviewFpsIterator.next();
StringBuffer sb=新的StringBuffer();
某人附加(“supportedPreviewRate:”);
对于(int i=tmpRate.length,j=0;jBitmapFactory不知道如何解码来自摄影机的预览数据,因为它是一个原始像素数组,没有标识信息。这就是它引发异常的原因
您必须自己将数据转换/解释为RGB格式,并从中构造位图。默认情况下,相机以该格式提供预览数据。您可以找到有关NV21的更多详细信息。要创建全彩RGB图像,您需要对两个色度通道进行上采样,然后将结果转换为RGB
如果您可以保存JPEG,也可以使用该类进行保存。BitmapFactory不知道如何解码来自相机的预览数据,因为它是一个原始像素数组,没有标识信息。这就是它引发异常的原因
您必须自己将数据转换/解释为RGB格式,并从中构造位图。默认情况下,相机以该格式提供预览数据。您可以找到有关NV21的更多详细信息。要创建全彩RGB图像,您需要对两个色度通道进行上采样,然后将结果转换为RGB
如果您同意保存JPEG,也可以使用该类来保存