打印手机摄像头的支持参数+将预览帧转换为位图+获取最佳预览

简介: 打印手机摄像头的支持参数+将预览帧转换为位图
public class SecondActivity extends Activity implements SurfaceHolder.Callback,
    PreviewCallback
{
  // 定义对象
  private SurfaceView mSurfaceview = null; // SurfaceView对象:(视图组件)视频显示
  private SurfaceHolder mSurfaceHolder = null; // SurfaceHolder对象:(抽象接口)SurfaceView支持类
  private Camera mCamera = null; // Camera对象,相机预览
  private String TAG = "SnapCamera";
  private boolean bIfPreview = false;
  private int mPreviewWidth;
  private int mPreviewHeight;
  Bitmap mBitmap = null;
  @Override
  protected void onCreate(Bundle savedInstanceState)
  {
    // TODO Auto-generated method stub
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    initSurfaceView();
  }
  // InitSurfaceView
  private void initSurfaceView()
  {
    mSurfaceview = (SurfaceView) this.findViewById(R.id.CameraView);
    mSurfaceHolder = mSurfaceview.getHolder(); // 绑定SurfaceView,取得SurfaceHolder对象
    mSurfaceHolder.addCallback(SecondActivity.this); // SurfaceHolder加入回调接口
    // mSurfaceHolder.setFixedSize(176, 144); // 预览大小設置
    mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);// 设置显示器类型,setType必须设置
  }
  /* 【2】【相机预览】 */
  private void initCamera()// surfaceChanged中调用
  {
    Log.i(TAG, "going into initCamera");
    if (bIfPreview)
    {
      mCamera.stopPreview();// stopCamera();
    }
    if (null != mCamera)
    {
      try
      {
        /* Camera Service settings */
        Camera.Parameters parameters = mCamera.getParameters();
        // parameters.setFlashMode("off"); // 无闪光灯
        parameters.setPictureFormat(PixelFormat.JPEG); // Sets the image format for picture 设定相片格式为JPEG,默认为NV21
        parameters.setPreviewFormat(PixelFormat.YCbCr_420_SP); // Sets the image format for preview picture,默认为NV21
        /*
         * 【ImageFormat】JPEG/NV16(YCrCb format,used for
         * Video)/NV21(YCrCb format,used for Image)/RGB_565/YUY2/YU12
         */
        // 【调试】获取camera支持的PictrueSize,看看能否设置
        List<Size> pictureSizes = mCamera.getParameters()
            .getSupportedPictureSizes();
        List<Size> previewSizes = mCamera.getParameters()
            .getSupportedPreviewSizes();
        List<Integer> previewFormats = mCamera.getParameters()
            .getSupportedPreviewFormats();
        List<Integer> previewFrameRates = mCamera.getParameters()
            .getSupportedPreviewFrameRates();
        Log.i(TAG + "initCamera", "  support parameters is ");
        Size psize = null;
        for (int i = 0; i < pictureSizes.size(); i++)
        {
          psize = pictureSizes.get(i);
          Log.i(TAG + "initCamera", "PictrueSize,width: "
              + psize.width + " height:" + psize.height);
        }
        for (int i = 0; i < previewSizes.size(); i++)
        {
          psize = previewSizes.get(i);
          Log.i(TAG + "initCamera", "PreviewSize,width: "
              + psize.width + " height:" + psize.height);
        }
        Integer pf = null;
        for (int i = 0; i < previewFormats.size(); i++)
        {
          pf = previewFormats.get(i);
          Log.i(TAG + "initCamera", "PreviewFormats:" + pf);
        }
        Iterator<Integer> it = previewFrameRates.iterator();
        while (it.hasNext())
        {
          Log.i(TAG + "initCamera", "PreviewFrameRates:" + it.next());
        }
        // 设置拍照和预览图片大小
        parameters.setPictureSize(640, 480); // 指定拍照图片的大小
        parameters.setPreviewSize(mPreviewWidth, mPreviewHeight); // 指定preview的大小
        // 这两个属性 如果这两个属性设置的和真实手机的不一样时,就会报错
        // 横竖屏镜头自动调整
        if (this.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE)
        {
          parameters.set("orientation", "portrait"); //
          parameters.set("rotation", 90); // 镜头角度转90度(默认摄像头是横拍)
          mCamera.setDisplayOrientation(90); // 在2.2以上可以使用
        } else
        // 如果是横屏
        {
          parameters.set("orientation", "landscape"); //
          mCamera.setDisplayOrientation(0); // 在2.2以上可以使用
        }
        /* 视频流编码处理 */
        // 添加对视频流处理函数
        // 设定配置参数并开启预览
        mCamera.setParameters(parameters); // 将Camera.Parameters设定予Camera
        mCamera.startPreview(); // 打开预览画面
        bIfPreview = true;
        // 【调试】设置后的图片大小和预览大小以及帧率
        Camera.Size csize = mCamera.getParameters().getPreviewSize();
        mPreviewHeight = csize.height;
        mPreviewWidth = csize.width;
        Log.i(TAG + "initCamera", "After setting, PreviewSize:width: "
            + csize.width + " height: " + csize.height);
        csize = mCamera.getParameters().getPictureSize();
        Log.i(TAG + "initCamera", "After setting, PictrueSize:width: "
            + csize.width + " height: " + csize.height);
        Log.i(TAG + "initCamera", "After setting, PreviewFormat is "
            + mCamera.getParameters().getPreviewFormat());
        Log.i(TAG + "initCamera", "After setting, PreviewFrameRate is "
            + mCamera.getParameters().getPreviewFrameRate());
      } catch (Exception e)
      {
        e.printStackTrace();
      }
    }
  }
  /* 【SurfaceHolder.Callback 回调函数】 */
  public void surfaceCreated(SurfaceHolder holder)
  // SurfaceView启动时/初次实例化,预览界面被创建时,该方法被调用。
  {
    // TODO Auto-generated method stub
    mCamera = Camera.open();// 开启摄像头(2.3版本后支持多摄像头,需传入参数)
    try
    {
      Log.i(TAG, "SurfaceHolder.Callback:surface Created");
      mCamera.setPreviewDisplay(mSurfaceHolder);// set the surface to be
      // used for live preview
      mCamera.setPreviewCallback(SecondActivity.this);
    } catch (Exception ex)
    {
      if (null != mCamera)
      {
        mCamera.release();
        mCamera = null;
      }
      Log.i(TAG + "initCamera", ex.getMessage());
    }
  }
  public void surfaceChanged(SurfaceHolder holder, int format, int width,
      int height)
  // 当SurfaceView/预览界面的格式和大小发生改变时,该方法被调用
  {
    // TODO Auto-generated method stub
    Log.i(TAG, "SurfaceHolder.Callback: Surface Changed");
    mPreviewHeight = height;
    mPreviewWidth = width;
    initCamera();
  }
  public void surfaceDestroyed(SurfaceHolder holder)
  // SurfaceView销毁时,该方法被调用
  {
    // TODO Auto-generated method stub
    Log.i(TAG, "SurfaceHolder.Callback:Surface Destroyed");
    if (null != mCamera)
    {
      mCamera.setPreviewCallback(null); // !!这个必须在前,不然退出出错
      mCamera.stopPreview();
      bIfPreview = false;
      mCamera.release();
      mCamera = null;
    }
  }
  @Override
  public void onPreviewFrame(byte[] data, Camera camera)
  {
    // TODO Auto-generated method stub
    Camera.Parameters parameters = camera.getParameters();
    int format = parameters.getPreviewFormat();
    if (mBitmap != null)
    {
      mBitmap.recycle();
      mBitmap = null;
    }
    // YUV formats require more conversion
    if (format == PixelFormat.YCbCr_420_SP
        || format == PixelFormat.YCbCr_422_I)
    {
      int w = 100/* parameters.getPreviewSize().width */;
      int h = 100/* parameters.getPreviewSize().height */;
      // Get the YuV image 由于此方法适用于android 2.2版本,所以此处不能用。
      // YuvImage yuv_image = new YuvImage(data, format, w, h, null);
      // // Convert YuV to Jpeg
      // Rect rect = new Rect(0, 0, w, h);
      // ByteArrayOutputStream output_stream = new
      // ByteArrayOutputStream();
      // yuv_image.compressToJpeg(rect, 100, output_stream);
      // // Convert from Jpeg to Bitmap
      // bitmap2 = BitmapFactory.decodeByteArray(output_stream
      // .toByteArray(), 0, output_stream.size());
      int[] i = new int[data.length];
      decodeYUV420SP(i, data, w, h);
      mBitmap = Bitmap.createBitmap(i, w, h, Bitmap.Config.RGB_565);
      // mBitmap = renderCroppedGreyscaleBitmap(data, w, h);
      // Log.e(TAG, "Image format is YUV:" + format);
    }
    // Jpeg and RGB565 are supported by BitmapFactory.decodeByteArray
    else if (format == PixelFormat.JPEG || format == PixelFormat.RGB_565)
    {
      // Log.e(TAG, "Image format is JPEG/RGB:" + format);
      mBitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
    }
  }
  private void decodeYUV420SP(int[] rgb, byte[] yuv420sp, int width,
      int height)
  {
    // TODO Auto-generated method stub
    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);
      }
    }
  }
}

在给定最大范围的条件下获取最佳预览的方法:

private void getBestPreviewSize(Camera camera, Parameters parameters, SurfaceView cameraView)
  {
    int bestWidth=0;
    int bestHeight=0;
    List<Size> previewSizes=parameters.getSupportedPreviewSizes();
    if(previewSizes.size()>1)
    {
      Iterator<Size> cei=previewSizes.iterator();
      while(cei.hasNext())
      {
        Size aSize=cei.next();
        Log.v("snap shot","Checking "+aSize.width+"*"+aSize.height);
        if(aSize.width>bestWidth && aSize.width<=LARGETST_WIDTH 
            && aSize.height >bestHeight
            && aSize.height<=LARGETST_HEIGHT)
        {
          bestWidth=aSize.width;
          bestHeight=aSize.height;
        }
      }
      if(bestHeight!=0 && bestWidth!=0)
      {
        Log.v("snap shot","Using "+bestWidth+"*"+ bestHeight);
        parameters.setPreviewSize(bestWidth,bestHeight);
        cameraView.setLayoutParams(new LinearLayout.LayoutParams(bestWidth,bestHeight));
      }
    }
    camera.setParameters(parameters);
  }
目录
相关文章
手机网站支付quit_url参数详解
一、quit_url参数说明   quit_url参数是手机网站支付用于在H5页面收银台中添加返回按钮的,但是该参数只有在支付的时候唤起H5收银台才会生效,对于唤起支付宝钱包支付是不生效的。 二、传参以及调用示例   传值代码示例: AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.
2814 0
|
2月前
|
存储 物联网 计算机视觉
|
6月前
|
JavaScript 网络架构
如何在手机上预览vue项目
如何在手机上预览vue项目
115 1
|
机器学习/深度学习 人工智能 编解码
安卓手机上跑15亿参数大模型,12秒不到就推理完了
安卓手机上跑15亿参数大模型,12秒不到就推理完了
239 0
|
算法 数据安全/隐私保护 计算机视觉
基于Aidlux平台实现手机摄像头实时Canny检测
基于Aidlux平台实现手机摄像头实时Canny检测
|
Android开发 iOS开发
【资源共享】手机共享摄像头给电脑用
【资源共享】手机共享摄像头给电脑用
475 0
|
小程序 前端开发 安全
【C#】 MVC4 开发小程序-实现人脸识别-本地和手机预览使用IP测试
小程序Camera组件拍照上传图片到指定的服务器(本地或者外网的IP服务器),然后C# MVC后台调用百度人脸识别接口,实现人脸识别功能呢
289 0
|
传感器 机器学习/深度学习 编解码
为什么你的手机后置摄像头越来越丑?ECCV2022这篇论文告诉你
为什么你的手机后置摄像头越来越丑?ECCV2022这篇论文告诉你
291 0
|
编解码 5G UED
分辨率和刷新率达到峰值 手机屏幕参数PK还能玩什么?
分辨率和刷新率达到峰值 手机屏幕参数PK还能玩什么?
339 0
分辨率和刷新率达到峰值 手机屏幕参数PK还能玩什么?
|
小程序 开发者
小程序:开发者工具和真机调试能请求后台数据,手机预览请求不到数据,快速解决
小程序:开发者工具和真机调试能请求后台数据,手机预览请求不到数据,快速解决
996 0
小程序:开发者工具和真机调试能请求后台数据,手机预览请求不到数据,快速解决