【Android】操作Camera对象采集图像


package com.example.duanjiwei.caremaapp;

import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.ImageFormat;
import android.graphics.Rect;
import android.graphics.YuvImage;
import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.ShutterCallback;
import android.hardware.Camera.Size;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.view.WindowManager;
import android.widget.ImageView;

public class MainActivity extends Activity implements SurfaceHolder.Callback {

    private Camera mCamera;// Camera对象
    private ImageView mButton;// 右侧条框,点击出发保存图像(拍照)的事件
    private SurfaceView mSurfaceView;// 显示图像的surfaceView
    private SurfaceHolder holder;// SurfaceView的控制器
    private AutoFocusCallback mAutoFocusCallback = new AutoFocusCallback();// AutoFocusCallback自动对焦的回调对象
    private ImageView sendImageIv;// 发送图片的imageview,位于右侧条框

    private String strCaptureFilePath = Environment.getExternalStorageDirectory() + "/DCIM/Camera/";// 保存图像的路径

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (checkCameraHardware(this)) {
            Log.e("============", "摄像头存在");// 验证摄像头是否存在
        }
        /* 隐藏状态栏 */
        this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);
        /* 隐藏标题栏 */
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        /* 设定屏幕显示为横向 */
        // this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

        setContentView(R.layout.activity_main);// ----------------------
        /* SurfaceHolder设置 */
        mSurfaceView = (SurfaceView) findViewById(R.id.mSurfaceView);
        holder = mSurfaceView.getHolder();
        holder.addCallback(this);
        // holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        /* 设置拍照Button的OnClick事件处理 */

        mButton = (ImageView) findViewById(R.id.myButton);
        mButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View arg0) {
                /* 自动对焦后拍照 */
                mCamera.autoFocus(mAutoFocusCallback);// 调用mCamera的
                takePicture();
            }
        });

        sendImageIv = (ImageView) findViewById(R.id.send_image);
        sendImageIv.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent i = new Intent();
                i.setType("image/*");
                i.setAction(Intent.ACTION_GET_CONTENT);
                startActivityForResult(i, Activity.DEFAULT_KEYS_SHORTCUT);
            }
        });

    }

    // ///----------重写SurfaceHolder.Callback接口的方法,
    // 在创建面板的时候调用的方法
    @Override
    public void surfaceCreated(SurfaceHolder surfaceholder) {

        try {
            mCamera = null;
            try {
                mCamera = Camera.open(0);//打开相机;在低版本里,只有open()方法;高级版本加入此方法的意义是具有打开多个
                //摄像机的能力,其中输入参数为摄像机的编号
                //在manifest中设定的最小版本会影响这里方法的调用,如果最小版本设定有误(版本过低),在ide里将不允许调用有参的
                //open方法;
                //如果模拟器版本较高的话,无参的open方法将会获得null值!所以尽量使用通用版本的模拟器和API;
            } catch (Exception e) {
                Log.e("============", "摄像头被占用");
            }
            if (mCamera == null) {
                Log.e("============", "摄像机为空");
                System.exit(0);
            }
            mCamera.setPreviewDisplay(holder);//设置显示面板控制器
            priviewCallBack pre = new priviewCallBack();//建立预览回调对象
            mCamera.setPreviewCallback(pre); //设置预览回调对象
            //mCamera.getParameters().setPreviewFormat(ImageFormat.JPEG);
            mCamera.startPreview();//开始预览,这步操作很重要
        } catch (IOException exception) {
            mCamera.release();
            mCamera = null;
        }

        // 不添加显示面板的代码:
        /*
         * 打开相机, mCamera = null; try { mCamera = Camera.open(0); } catch
         * (Exception e) { Log.e("============", "摄像头被占用"); } if (mCamera ==
         * null) { Log.e("============", "返回结果为空"); System.exit(0); } //
         * mCamera.setPreviewDisplay(holder); priviewCallBack pre = new
         * priviewCallBack(); mCamera.setPreviewCallback(pre); Log.w("wwwwwwww",
         * mCamera.getParameters().getPreviewFormat() + "");
         * mCamera.startPreview();
         */
    }

    // 在面板改变的时候调用的方法
    @Override
    public void surfaceChanged(SurfaceHolder surfaceholder, int format, int w, int h) {
        /* 相机初始化 */
        initCamera();
    }

    // 销毁面板时的方法
    @Override
    public void surfaceDestroyed(SurfaceHolder surfaceholder) {
        stopCamera();
        mCamera.release();
        mCamera = null;
    }

    /* 拍照的method */
    private void takePicture() {
        if (mCamera != null) {
            mCamera.takePicture(shutterCallback, rawCallback, jpegCallback);
        }
    }

    private ShutterCallback shutterCallback = new ShutterCallback() {
        public void onShutter() {
            /* 按下快门瞬间会调用这里的程序 */
        }
    };

    private PictureCallback rawCallback = new PictureCallback() {
        public void onPictureTaken(byte[] _data, Camera _camera) {
            /* 要处理raw data?写?否 */
        }
    };

    //在takepicture中调用的回调方法之一,接收jpeg格式的图像
    private PictureCallback jpegCallback = new PictureCallback() {
        public void onPictureTaken(byte[] _data, Camera _camera) {

            /*
             * if (Environment.getExternalStorageState().equals(
             * Environment.MEDIA_MOUNTED)) // 判断SD卡是否存在,并且可以可以读写 {
             *
             * } else { Toast.makeText(EX07_16.this, "SD卡不存在或写保护",
             * Toast.LENGTH_LONG) .show(); }
             */
            // Log.w("============", _data[55] + "");

            try {
                /* 取得相片 */
                Bitmap bm = BitmapFactory.decodeByteArray(_data, 0,  _data.length);

                /* 创建文件 */
                File myCaptureFile = new File(strCaptureFilePath, "1.jpg");
                BufferedOutputStream bos = new BufferedOutputStream(
                        new FileOutputStream(myCaptureFile));
                /* 采用压缩转档方法 */
                bm.compress(Bitmap.CompressFormat.JPEG, 100, bos);

                /* 调用flush()方法,更新BufferStream */
                bos.flush();

                /* 结束OutputStream */
                bos.close();

                /* 让相片显示3秒后圳重设相机 */
                // Thread.sleep(2000);
                /* 重新设定Camera */
                stopCamera();
                initCamera();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    };

    /* 自定义class AutoFocusCallback */
    public final class AutoFocusCallback implements
            android.hardware.Camera.AutoFocusCallback {
        public void onAutoFocus(boolean focused, Camera camera) {

            /* 对到焦点拍照 */
            if (focused) {
                takePicture();
            }
        }
    };

    /* 相机初始化的method */
    private void initCamera() {
        if (mCamera != null) {
            try {
                Camera.Parameters parameters = mCamera.getParameters();
                /*
                 * 设定相片大小为1024*768, 格式为JPG
                 */
                // parameters.setPictureFormat(PixelFormat.JPEG);
                parameters.setPictureSize(1024, 768);
                mCamera.setParameters(parameters);
                /* 打开预览画面 */
                mCamera.startPreview();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /* 停止相机的method */
    private void stopCamera() {
        if (mCamera != null) {
            try {
                /* 停止预览 */
                mCamera.stopPreview();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    // 检测摄像头是否存在的私有方法
    private boolean checkCameraHardware(Context context) {
        if (context.getPackageManager().hasSystemFeature(
                PackageManager.FEATURE_CAMERA)) {
            // 摄像头存在
            return true;
        } else {
            // 摄像头不存在
            return false;
        }
    }

    // 每次cam采集到新图像时调用的回调方法,前提是必须开启预览
    class priviewCallBack implements Camera.PreviewCallback {

        @Override
        public void onPreviewFrame(byte[] data, Camera camera) {
            // TODO Auto-generated method stub
            // Log.w("wwwwwwwww", data[5] + "");
            // Log.w("支持格式", mCamera.getParameters().getPreviewFormat()+"");
            decodeToBitMap(data, camera);

        }
    }

    public void decodeToBitMap(byte[] data, Camera _camera) {
        Size size = mCamera.getParameters().getPreviewSize();
        try {
            YuvImage image = new YuvImage(data, ImageFormat.NV21, size.width, size.height, null);
            Log.w("wwwwwwwww", size.width + " " + size.height);
            if (image != null) {
                ByteArrayOutputStream stream = new ByteArrayOutputStream();
                image.compressToJpeg(new Rect(0, 0, size.width, size.height), 80, stream);
                Bitmap bmp = BitmapFactory.decodeByteArray( stream.toByteArray(), 0, stream.size());
                Log.w("wwwwwwwww", bmp.getWidth() + " " + bmp.getHeight());
                Log.w("wwwwwwwww", (bmp.getPixel(100, 100) & 0xff) + "  " + ((bmp.getPixel(100, 100) >> 8) & 0xff) + "  " + ((bmp.getPixel(100, 100) >> 16) & 0xff));

                stream.close();
            }
        } catch (Exception ex) {
            Log.e("Sys", "Error:" + ex.getMessage());
        }
    }

}

----------------------------------------------------------------------

package com.example.duanjiwei.mycamera;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

import android.hardware.Camera;
import android.hardware.Camera.PreviewCallback;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
import android.widget.RelativeLayout;
import android.widget.RelativeLayout.LayoutParams;

import java.io.IOException;

public class MainActivity extends AppCompatActivity implements Callback, PreviewCallback  {

    SurfaceView camerasurface = null;
    Camera camera = null;
    HandlerThread handleThread = null;
    Handler detectHandler = null;
    Runnable detectRunnalbe = null;
    private int width = 320;
    private int height = 240;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        camerasurface = (SurfaceView) findViewById(R.id.camera_preview);
        LayoutParams para = new LayoutParams(480, 800);
        handleThread = new HandlerThread("dt");
        handleThread.start();
        detectHandler = new Handler(handleThread.getLooper());
        para.addRule(RelativeLayout.CENTER_IN_PARENT);
        camerasurface.setLayoutParams(para);
        camerasurface.getHolder().addCallback(this);
        camerasurface.setKeepScreenOn(true);
    }

    @Override
    protected void onResume() {
        super.onResume();
        camera = Camera.open(1);
        Camera.Parameters para = camera.getParameters();
        para.setPreviewSize(width, height);
        camera.setParameters(para);
    }

    @Override
    protected void onPause() {
        super.onPause();
        if (camera != null) {
            camera.setPreviewCallback(null);
            camera.stopPreview();
            camera.release();
            finish();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        handleThread.quit();
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

        try {
            camera.setPreviewDisplay(holder);
        } catch (IOException e) {
            e.printStackTrace();
        }
        camera.setDisplayOrientation(90);
        camera.startPreview();
        camera.setPreviewCallback(this);
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {

    }

    @Override
    public void onPreviewFrame(final byte[] data, Camera camera) {
        camera.setPreviewCallback(null);
        detectHandler.post(new Runnable() {

            @Override
            public void run() {
                byte[] ori = new byte[width * height];
                int is = 0;
                for (int x = width - 1; x >= 0; x--) {
                    for (int y = height - 1; y >= 0; y--) {
                        ori[is] = data[y * width + x];
                        is++;
                    }
                }
                runOnUiThread(new Runnable() {

                    @Override
                    public void run() {
                    }
                });
                MainActivity.this.camera.setPreviewCallback(MainActivity.this);
            }
        });
    }
}

<SurfaceView
        android:id="@+id/camera_preview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true" />

<uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />


### 回答1: Android Camera2 API是Android系统提供的一种新的相机框架,用于实现相机预览和采集功能。Camera2 API可以提供更强大、更灵活的相机控制和图像处理能力。 相比于传统的Camera API,Camera2 API具有以下优势: 1. 能够同时管理多个相机设备:Camera2 API支持同时管理多个相机设备,包括前置摄像头、后置摄像头、深度摄像头等,可以方便地进行相机切换和管理。 2. 提供更灵活的相机控制:Camera2 API提供了更丰富的相机控制选项,可以精确地设置曝光时间、ISO值、焦距等参数,以便于用户根据不同的拍摄场景进行调整。 3. 支持原生的相机预览和采集Camera2 API提供了对原生的预览和采集数据的支持,可以更高效地获取图像数据,用户可以利用这些数据进行实时的图像处理或者保存。 4. 支持原生的相机回调:Camera2 API提供了原生的相机回调接口,用户可以通过设置回调函数来实时获取相机的状态和图像数据,从而实现一些特殊的相机功能,如实时人脸检测、连拍等。 总之,Android Camera2 API提供了更强大、更灵活的相机功能,可以满足开发者对相机预览和采集的各种需求。无论是在智能手机、平板电脑还是其他移动设备上,都可以通过Camera2 API来实现高质量的相机应用。 ### 回答2: Android Camera 2是Android系统中用于处理相机功能的全新API。相较于之前的Camera API,Camera 2更加强大和灵活,提供了更多的功能和优化。 在Android Camera 2中,预览采集是通过创建一个CameraDevice实例来实现的。首先,需要获取相机的相关信息,例如相机的ID、参数等。然后,通过调用CameraManager的openCamera方法来打开指定ID的相机。 在相机打开后,可以通过创建一个CaptureRequest.Builder对象来配置相机的预览设置。可以设置预览的目标Surface、预览图像的尺寸、帧率等。然后,通过调用createCaptureSession方法,传入预览的目标Surface和一个CameraCaptureSession.StateCallback来创建一个预览会话。 在预览会话创建后,可以调用setRepeatingRequest方法来开始预览。Camera2会自动将预览帧数据传输到指定的Surface上,并在Surface上更新预览图像。同时,可以通过设置回调函数来处理预览数据,例如实时显示预览图像、进行进一步的图像处理等。 在预览过程中,还可以根据需要调整相机的参数,例如调整曝光度、焦距、白平衡等。通过创建新的CaptureRequest.Builder对象并设置相应参数,然后调用Session的setRepeatingRequest方法,可以实现动态调整相机参数。 总而言之,Android Camera 2提供了更强大和灵活的方式来实现相机预览采集。通过合理地使用Camera2的API,我们可以轻松地实现各种功能,例如实时预览、图像处理、动态调整参数等。 ### 回答3: Android Camera2预览采集是通过使用Android操作系统的Camera2 API来实现的一种方式。Camera2 API是Android 5.0(Lollipop)版本引入的相机框架,它提供了更多的功能和灵活性,用于控制和管理Android设备上的相机。 使用Camera2 API进行预览采集是一种相对较新和高级的方法,相比传统的Camera API,Camera2 API提供了更多的控制选项和功能,以及更好的性能和稳定性。 通过Camera2 API,我们可以实时地从Android设备的摄像头获取图像,并将图像传输到屏幕上进行实时预览。预览采集可以在应用程序中使用,例如用于视频通话、拍照、视频录制等场景。 Camera2 API的预览采集过程主要涉及以下步骤: 1. 获取相机设备:通过CameraManager类获取设备的摄像头列表,并选择要使用的摄像头设备。 2. 创建相机会话:使用CameraDevice类进行连接和建立与相机设备的会话。 3. 创建预览请求:使用CaptureRequest.Builder类创建一个预览请求,并设置相应的参数,例如预览尺寸、帧率等。 4. 创建预览会话:使用CameraDevice类创建预览会话,并将预览请求设置为预览会话的目标。 5. 开启预览:将预览会话设置为活动状态,相机将开始实时地捕获图像,并通过指定的Surface进行预览。 通过这些步骤,我们可以在Android设备上实现相机预览采集功能,并根据需要进行自定义设置和扩展。预览采集可以进一步应用于更多的相机应用场景,例如人脸识别、图像处理等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值