问题描述
- 从camera preview获取数据流问题求教!
-
本人android开发新人,以下是我为了从预览数据流抓取图片并存储而编写的代码。网上说“从camera读取到的预览(preview)图像流一定要输出到一个可见的(Visible)SurfaceView上,然后通过Camera.PreviewCallback的public void onPreviewFrame(byte[] data, Camera camera)函数来获得图像帧数据的拷贝。”那么显示在SurfaceView上的数据流还是完整的吧,不会出现预览停顿的现象吧?为什么我的程序运行之后,预览一闪而过,然后程序重启,如此反复三遍,报出进程意外停止呢?而且也没有保存到图像。这个程序会以什么频率保存图片啊?onPreviewFrame(byte[] data, Camera camera)是每一帧都保存吗?如何控制保存频率?
求大神细心讲解,在线求教!或者QQ:851391489,隐身状态。拜谢!package com.android.silentcamera;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;import android.app.Activity;
import android.content.ContentValues;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.hardware.Camera;
import android.hardware.Camera.CameraInfo;
import android.hardware.Camera.PreviewCallback;
import android.media.AudioManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.provider.MediaStore.Images.Media;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;public class SilentCameraActivity extends Activity
implements Camera.PreviewCallback, SurfaceHolder.Callback
{SurfaceView mSurfaceView;
SurfaceHolder mSurfaceHolder;
Camera mCamera;public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mSurfaceView = (SurfaceView) this.findViewById(R.id.surfaceview); mSurfaceHolder = mSurfaceView.getHolder(); mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); mSurfaceHolder.addCallback(this); } @Override public void surfaceDestroyed(SurfaceHolder holder) { // TODO Auto-generated method stub mCamera.stopPreview(); mCamera.release(); } @Override public void surfaceCreated(SurfaceHolder holder) { // TODO Auto-generated method stub //打开前置摄像头 mCamera = Camera.open(CameraInfo.CAMERA_FACING_FRONT); //开始预览 try { //设置哪个surfaceView显示图片 mCamera.setPreviewDisplay(mSurfaceHolder); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } //设置预览帧的接口,就是通过这个接口,我们来获得预览帧的数据的 mCamera.setPreviewCallback(SilentCameraActivity.this); mCamera.startPreview(); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { // TODO Auto-generated method stub mCamera.startPreview(); } //拍照+退出 public void onPreviewFrame(byte[] data, Camera camera) { int w = camera.getParameters().getPreviewSize().width; int h = camera.getParameters().getPreviewSize().height; save(w,h,data); finish(); } static public void decodeYUV420SP(int[] rgb, byte[] yuv420sp, int width, int height) { final int frameSize = width * height; for (int j = 0, yp = 0; j < height; j++) { int uvp = frameSize + (j >> 1) * width, u = 0, v = 0; for (int i = 0; i < width; i++, yp++) { int y = (0xff & ((int) yuv420sp[yp])) - 16; if (y < 0) y = 0; if ((i & 1) == 0) { v = (0xff & yuv420sp[uvp++]) - 128; u = (0xff & yuv420sp[uvp++]) - 128; } int y1192 = 1192 * y; int r = (y1192 + 1634 * v); int g = (y1192 - 833 * v - 400 * u); int b = (y1192 + 2066 * u); if (r < 0) r = 0; else if (r > 262143) r = 262143; if (g < 0) g = 0; else if (g > 262143) g = 262143; if (b < 0) b = 0; else if (b > 262143) b = 262143; rgb[yp] = 0xff000000 | ((r << 6) & 0xff0000) | ((g >> 2) & 0xff00) | ((b >> 10) & 0xff); } } } //保存 public void save(int w,int h,byte[] data){ //预览编码为YUV420SP的视频流,需转换为RGB编码 int[] RGBData = new int[w* h]; byte[] mYUVData = new byte[data.length]; System.arraycopy(data,0, mYUVData, 0,data.length); decodeYUV420SP(RGBData,mYUVData,w,h); //图片保存到sdcard final Bitmap bitmap = Bitmap.createBitmap(w,h, Bitmap.Config.ARGB_8888); try { FileOutputStream outputStream = new FileOutputStream(Environment.getExternalStorageDirectory().getPath() + UUID.randomUUID() + ".png"); bitmap.compress(CompressFormat.PNG, 50, outputStream); outputStream.close(); } catch(Exception e) { e.printStackTrace(); } }
}
解决方案
楼主请问你的视频流的数据可以获取的到吗?
解决方案二:
请问楼主,上面的程序中 final Bitmap bitmap = Bitmap.createBitmap(w,h, Bitmap.Config.ARGB_8888); 在try{}块里, bitmap.compress(CompressFormat.PNG, 50, outputStream); 并没有保存图像的数据,请问该如何解决?
解决方案三:
请问楼主,上面的程序中 final Bitmap bitmap = Bitmap.createBitmap(w,h, Bitmap.Config.ARGB_8888); 在try{}块里, bitmap.compress(CompressFormat.PNG, 50, outputStream); 并没有保存图像的数据,请问该如何解决?
解决方案四:
请问楼主,上面的程序中 final Bitmap bitmap = Bitmap.createBitmap(w,h, Bitmap.Config.ARGB_8888); 在try{}块里, bitmap.compress(CompressFormat.PNG, 50, outputStream); 并没有保存图像的数据,请问该如何解决?
解决方案五:
请问楼主,上面的程序中 final Bitmap bitmap = Bitmap.createBitmap(w,h, Bitmap.Config.ARGB_8888); 在try{}块里, bitmap.compress(CompressFormat.PNG, 50, outputStream); 并没有保存图像的数据,请问该如何解决?
解决方案六:
http://blog.chinaunix.net/uid-26941022-id-3996501.html