本人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();
}
}
}
http://blog.chinaunix.net/uid-26941022-id-3996501.html
我觉得大概是因为
FileOutputStream outputStream = new FileOutputStream(Environment.getExternalStorageDirectory().getPath() + UUID.randomUUID() + ".png");
这里是不是少了个“/”
Environment.getExternalStorageDirectory().getPath() +“/”+ UUID.randomUUID() + ".png"
文件目录是这个