android -- java 拍照获取图片数据

几经折腾,综合了网上各大神的经验分享,终于可以顺利在手机上实例拍照功能了。

本人当前使用的 android studio 版本为 2.3.2

首先整理一下实现拍照功能的实现思路:

1、在 AndroidManifest.xml 开通必要的权限。

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

<uses-feature android:name="android.hardware.camera" android:required="true" />

<uses-feature android:name="android.hardware.autofocus" android:required="true" />

2、因为在拍照之前,在手机上能预览到摄像头所获取到的景物,所以需要在主界面上增加一个景物预览的前端控件:

<SurfaceView
    android:id="@+id/surfaceView"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

3、要拍照,所以要有一个触发事件的控件。可以根据自己的喜好随便放(Button、View、TextView等等都可以)。

4、拍照的结果需要一个控件来展示。(ImageView、View都可以)

5、后端代码。

     摄像头 Camera 对象这里采用的是  import android.hardware.Camera;

5.1、声明主要变量

private Camera camera;
private SurfaceView surfaceView; 
private SurfaceHolder holder; 
private SurfaceHolder holder1;

5.1.1 为  holder1 对象赋值:在 SurfaceCallBack 类的 surfaceCreated 方法里

注: holder 和 holder1 是两个不同的对象!

surfaceView = (SurfaceView) findViewById(R.id.surfaceView); //就是第2步里的 SurfaceView 控件 id
holder = surfaceView.getHolder();
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
//holder.setFixedSize(176, 144);//设置分辨率
holder.setKeepScreenOn(true);//屏幕长亮

holder.addCallback(new SurfaceCallBack());为SurfaceView的句柄添加一个回调函数
class SurfaceCallBack implements SurfaceHolder.Callback {

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        holder1 = holder;
        openCamera();
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
            if (camera != null) {
                Camera.Parameters parameters = camera.getParameters();//获取各项参数
                Camera.Size previewSize = findFitPreResolution(parameters);
                parameters.setPreviewSize(previewSize.width, previewSize.height);// 设置预览大小

                parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
                parameters.setPictureFormat(PixelFormat.JPEG);//设置图片格式
                //不能与setPreviewSize一起使用,否则setParamters会报错
                //parameters.setPreviewFrameRate(5);//设置每秒显示4帧
                parameters.setJpegQuality(80);// 设置照片质量
                Camera.Size pictureSize = null;
                if (equalRate(screenWidth, screenHeight, 1.33f)) {
                    pictureSize = findFitPicResolution(parameters, (float) 4 / 3);
                } else {
                    pictureSize = findFitPicResolution(parameters, (float) 16 / 9);
                }

                parameters.setPictureSize(pictureSize.width, pictureSize.height);// 设置保存的图片尺寸
                camera.setParameters(parameters);
                camera.startPreview();
            }        
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        if (camera != null) {
            //当surfaceview关闭时,关闭预览并释放资源
            camera.stopPreview();
            camera.release();//释放相机
            camera = null;
        }
        holder.getSurface().release();
    }

    private Camera.Size findFitPreResolution(Camera.Parameters cameraParameters) {
        List<Camera.Size> supportedPicResolutions = cameraParameters.getSupportedPreviewSizes();

        Camera.Size resultSize = null;
        for (Camera.Size size : supportedPicResolutions) {
            if (size.width <= ALLOW_PIC_LEN) {
                if (resultSize == null) {
                    resultSize = size;
                } else if (size.width > resultSize.width) {
                    resultSize = size;
                }
            }
        }
        if (resultSize == null) {
            return supportedPicResolutions.get(0);
        }
        return resultSize;
    }

    private Camera.Size findFitPicResolution(Camera.Parameters cameraParameters, float bl) {
        List<Camera.Size> supportedPicResolutions = cameraParameters.getSupportedPictureSizes();

        Camera.Size resultSize = null;
        for (Camera.Size size : supportedPicResolutions) {
            if ((float) size.width / size.height == bl && size.width <= ALLOW_PIC_LEN && size.height <= ALLOW_PIC_LEN) {
                if (resultSize == null) {
                    resultSize = size;
                } else if (size.width > resultSize.width) {
                    resultSize = size;
                }
            }
        }
        if (resultSize == null) {
            return supportedPicResolutions.get(0);
        }
        return resultSize;
    }
}

5.1.2 打开摄像头相关

private void openCamera(){
    int cameraPosition = Camera.CameraInfo.CAMERA_FACING_BACK;
    // 打开摄像头
    camera = Camera.open(cameraPosition);
    // 设置用于显示拍照影像的SurfaceHolder对象
    camera.setPreviewDisplay(holder1);
    camera.setDisplayOrientation(90);
    camera.startPreview();
    camera.autoFocus(autoFocusCallback);
}

 5.1.3  autoFocusCallback 回调:

那么这时 autoFocusCallback = new MyAutoFocusCall();

class MyAutoFocusCall implements Camera.AutoFocusCallback {
    @Override
    public void onAutoFocus(boolean success, Camera camera) {
        //to do something.
    }
}

6 在触发拍照的事件里执行如下代码获取图片数据:

camera.takePicture(shutterCallback, null, pictureCallback);

6.1   shutterCallback 回调

shutterCallback = new MyShutterCallback(); 

class MyShutterCallback implements Camera.ShutterCallback{
    @Override
    public void onShutter() {
        //to do something.
    }
}

6.2  pictureCallback 回调

pictureCallback = new MyPictureCallback();

class MyPictureCallback implements Camera.PictureCallback{
    @Override
    public void onPictureTaken(byte[] data, Camera camera) {
        if (null == data) return;
        Bitmap img = BitmapFactory.decodeByteArray(data, 0, data.length);        
        //img 可以在 ImageView 里显示(imgView 对象自己用 findViewById 获取)
        imgView.setImageBitmap(img);
    }
}

7、到这步是可以显示拍照的图片了(如果不出意外,环境不出问题的话),但是这时会发现所展示的拍照后的结果图片角度不对,应该顺时针旋转90度才对。

private Bitmap RotatePic(Bitmap img) {
    int width = img.getWidth();
    int height = img.getHeight();

    Matrix matrix = new Matrix();
    matrix.setRotate(90);
    Bitmap resultImg = Bitmap.createBitmap(img, 0, 0, width, height, matrix, true);
    //BitmapDrawable bitmapDrawable = new BitmapDrawable(resizedBitmap);
    return resultImg;
}

这里的 resultImg 才是最终拍照后的图片。所以需要在显示图片前调用 RotatePic 方法旋转图片:

img = RotatePic(img);

imgView.setImageBitmap(img);

 

 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值