Android 摄像头预览(Camera2)-- 拍照

75 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第11天,点击查看活动详情

点击参考整个相机预览,拍照 ,横屏竖屏的处理

  • 本文是在Camera的预览回调中 ,点击拍照,显示图片
  • 布局
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity2">
    <Button
        android:onClick="photograph"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="拍照"
        />
    <SurfaceView
        android:id="@+id/surface_view"
        android:layout_centerInParent="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <ImageView
        android:id="@+id/image"
        android:layout_alignParentBottom="true"
        android:layout_width="150dp"
        android:layout_height="150dp"
        />
</RelativeLayout>
  • 处理

设置摄像头参数

  • Camera.Parameters parameters = mCamera.getParameters();//得到摄像头的参数-
  • parameters.setPictureFormat(PixelFormat.JPEG);//设置照片的格式
  • parameters.setJpegQuality(85);//设置照片的质量
  • parameters.setPreviewSize(640, 480);
  • parameters.setPictureSize(640, 480);//设置照片的大小,默认是和屏幕一样大-
  • mCamera.setParameters(parameters);//设置需要预览的尺寸

获取预览的图像byte[] ( Camera.PreviewCallback)代码参考Android 实现相机(Camera)-- 预览参考

在这里插入图片描述

mCamera.setPreviewCallback(previewCallback);//预览相机

 //回调
 private Camera.PreviewCallback previewCallback=new Camera.PreviewCallback() {
        @Override
        public void onPreviewFrame(byte[] data, Camera camera) {
            if (MainActivity3.getMode()==0) {//后置
                bitmap = NV21ToBitmap.getInstance(MainActivity2.this).nv21ToBitmap(data, 640, 480, 90,false);
            }else {//前置
                bitmap = NV21ToBitmap.getInstance(MainActivity2.this).nv21ToBitmap(data, 640, 480, 0,true);
            }
        }
    };


  • 处理byte[]成图像的工具类 在这里插入图片描述 在这里插入图片描述

displayOrientation 角度

public class NV21ToBitmap {
    private RenderScript rs;
    private ScriptIntrinsicYuvToRGB yuvToRgbIntrinsic;
    private Type.Builder yuvType, rgbaType;
    private Allocation in, out;
    private static NV21ToBitmap nv21ToBitmap;

    public static NV21ToBitmap getInstance(Context context) {
        if (null == nv21ToBitmap) {
            synchronized (NV21ToBitmap.class) {
                nv21ToBitmap = new NV21ToBitmap(context);
            }
        }
        return nv21ToBitmap;
    }

    private NV21ToBitmap(Context context) {
        rs = RenderScript.create(context);
        yuvToRgbIntrinsic = ScriptIntrinsicYuvToRGB.create(rs, Element.U8_4(rs));
    }

    public Bitmap nv21ToBitmap(byte[] nv21, int width, int height , int displayOrientation,
                               boolean isMirror) {
        yuvType = new Type.Builder(rs, Element.U8(rs)).setX(nv21.length);
        in = Allocation.createTyped(rs, yuvType.create(), Allocation.USAGE_SCRIPT);

        rgbaType = new Type.Builder(rs, Element.RGBA_8888(rs)).setX(width).setY(height);
        out = Allocation.createTyped(rs, rgbaType.create(), Allocation.USAGE_SCRIPT);

        in.copyFrom(nv21);
        yuvToRgbIntrinsic.setInput(in);
        yuvToRgbIntrinsic.forEach(out);
        Bitmap bmpout = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        out.copyTo(bmpout);
        Matrix matrix = new Matrix();
        matrix.postRotate(displayOrientation, bmpout.getWidth() / 2, bmpout.getHeight() / 2);
        if (isMirror) {
            matrix.postScale(-1.0f, 1.0f);//前置的图像是镜像的
        }
        return Bitmap.createBitmap(bmpout, 0, 0, bmpout.getWidth(), bmpout.getHeight(), matrix, true);
    }
}

点击拍照的处理事件

  //点击拍照的处理,拿到相机预览的图片 ,显示在布局上
  public void photograph(View view) {
        //点击拍照后,拿到相机预览的图片 ,显示在布局上
        image.setImageBitmap(bitmap);
    }

Android 实现相机(Camera)-- 预览参考

  • 本文是在Camera的预览回调中 ,点击拍照,显示图片
  • 布局
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity2">
    <Button
        android:onClick="photograph"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="拍照"
        />
    <SurfaceView
        android:id="@+id/surface_view"
        android:layout_centerInParent="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <ImageView
        android:id="@+id/image"
        android:layout_alignParentBottom="true"
        android:layout_width="150dp"
        android:layout_height="150dp"
        />
</RelativeLayout>
  • 处理

获取预览的图像byte[] ( Camera.PreviewCallback)代码参考Android 实现相机(Camera)-- 预览参考

在这里插入图片描述

mCamera.setPreviewCallback(previewCallback);//预览相机

 //回调
 private Camera.PreviewCallback previewCallback=new Camera.PreviewCallback() {
        @Override
        public void onPreviewFrame(byte[] data, Camera camera) {
            if (MainActivity3.getMode()==0) {//后置
                bitmap = NV21ToBitmap.getInstance(MainActivity2.this).nv21ToBitmap(data, 640, 480, 90,false);
            }else {//前置
                bitmap = NV21ToBitmap.getInstance(MainActivity2.this).nv21ToBitmap(data, 640, 480, 0,true);
            }
        }
    };


  • 处理byte[]成图像的工具类 在这里插入图片描述 在这里插入图片描述

displayOrientation 角度

public class NV21ToBitmap {
    private RenderScript rs;
    private ScriptIntrinsicYuvToRGB yuvToRgbIntrinsic;
    private Type.Builder yuvType, rgbaType;
    private Allocation in, out;
    private static NV21ToBitmap nv21ToBitmap;

    public static NV21ToBitmap getInstance(Context context) {
        if (null == nv21ToBitmap) {
            synchronized (NV21ToBitmap.class) {
                nv21ToBitmap = new NV21ToBitmap(context);
            }
        }
        return nv21ToBitmap;
    }

    private NV21ToBitmap(Context context) {
        rs = RenderScript.create(context);
        yuvToRgbIntrinsic = ScriptIntrinsicYuvToRGB.create(rs, Element.U8_4(rs));
    }

    public Bitmap nv21ToBitmap(byte[] nv21, int width, int height , int displayOrientation,
                               boolean isMirror) {
        yuvType = new Type.Builder(rs, Element.U8(rs)).setX(nv21.length);
        in = Allocation.createTyped(rs, yuvType.create(), Allocation.USAGE_SCRIPT);

        rgbaType = new Type.Builder(rs, Element.RGBA_8888(rs)).setX(width).setY(height);
        out = Allocation.createTyped(rs, rgbaType.create(), Allocation.USAGE_SCRIPT);

        in.copyFrom(nv21);
        yuvToRgbIntrinsic.setInput(in);
        yuvToRgbIntrinsic.forEach(out);
        Bitmap bmpout = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        out.copyTo(bmpout);
        Matrix matrix = new Matrix();
        matrix.postRotate(displayOrientation, bmpout.getWidth() / 2, bmpout.getHeight() / 2);
        if (isMirror) {
            matrix.postScale(-1.0f, 1.0f);//前置的图像是镜像的
        }
        return Bitmap.createBitmap(bmpout, 0, 0, bmpout.getWidth(), bmpout.getHeight(), matrix, true);
    }
}

点击拍照的处理事件

  //点击拍照的处理,拿到相机预览的图片 ,显示在布局上
  public void photograph(View view) {
        //点击拍照后,拿到相机预览的图片 ,显示在布局上
        image.setImageBitmap(bitmap);
    }