wang_xin_1992 2014-03-31 15:50 采纳率: 0%
浏览 11916

从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();
        }
    }

}

  • 写回答

2条回答 默认 最新

  • shiter 人工智能领域优质创作者 2015-01-19 14:12
    关注
    评论

报告相同问题?

悬赏问题

  • ¥15 如何用stata画出文献中常见的安慰剂检验图
  • ¥15 c语言链表结构体数据插入
  • ¥40 使用MATLAB解答线性代数问题
  • ¥15 COCOS的问题COCOS的问题
  • ¥15 FPGA-SRIO初始化失败
  • ¥15 MapReduce实现倒排索引失败
  • ¥15 ZABBIX6.0L连接数据库报错,如何解决?(操作系统-centos)
  • ¥15 找一位技术过硬的游戏pj程序员
  • ¥15 matlab生成电测深三层曲线模型代码
  • ¥50 随机森林与房贷信用风险模型