android Camera(一)

前言

在API级别21中不
推荐使用该类。我们建议[android.hardware.camera2](https://developer.android.com/reference/android/hardware/camera2/package-summary)对新应用程序使用新的API。

Camera类用于设置图像捕获设置,开始/停止预览,快照和检索帧以对视频进行编码。此类是Camera服务的客户端,该服务管理实际的相机硬件。

Camera1的使用

一、权限

要访问设备相机,您必须[Manifest.permission.CAMERA](https://developer.android.com/reference/android/Manifest.permission#CAMERA)在Android清单中声明该 权限。另外,请确保包含 <uses-feature> 清单元素,以声明应用程序使用的相机功能。例如,如果您使用相机和自动对焦功能,则清单应包括以下内容:

 <uses-permission android:name="android.permission.CAMERA" />
 <uses-feature android:name="android.hardware.camera" />
 <uses-feature android:name="android.hardware.camera.autofocus" />

如果是6.0以上的手机还要动态申请权限,关于权限这块大家可以使用PermissionUtil全局管理。

二、相机的初始化

1.摄像头数量确定

/** Check if this device has a camera */
private boolean checkCameraHardware(Context context) {
    if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){
        // this device has a camera
        return true;
    } else {
        // no camera on this device
        return false;
    }
}
  1. 从中获取Camera的实例Camera.open(camera_Id);设置参数,getParameters()获取已有参数,如果有必要对返回的参数进行修改,然后调用setParameters();

 private void openCamera(int cameraType, int width, int height) {
            if (mCamera != null) {
                throw new RuntimeException("camera already initialized");
            }

            Camera.CameraInfo info = new Camera.CameraInfo();
            int numCameras = Camera.getNumberOfCameras();
            for (int i = 0; i < numCameras; i++) {
                Camera.getCameraInfo(i, info);
                if (info.facing == cameraType) {
                    CAMERA_ID = i;
                    mCamera = Camera.open(i);
                    break;
                }
            }
            if (mCamera == null) {
                throw new RuntimeException("unable to open camera");
            }

            final Camera.Parameters params = mCamera.getParameters();

      //  帧率设置
            final List<int[]> supportedFpsRange = params.getSupportedPreviewFpsRange();
            final int[] max_fps = supportedFpsRange.get(supportedFpsRange.size() - 1);
            params.setPreviewFpsRange(max_fps[0], max_fps[1]);

            // 优化后的camera FPS设置方法
            int framerate = 30 * 1000;
            List<int[]> rates = params.getSupportedPreviewFpsRange();
            int[] closetFramerate = rates.get(0);
            for (int i = 0; i < rates.size(); i++) {
                int[] rate = rates.get(i);
 
                int curDelta = Math.abs(rate[1] - framerate);
                int bestDelta = Math.abs(closetFramerate[1] - framerate);
                if (curDelta < bestDelta) {
                    closetFramerate = rate;
                } else if (curDelta == bestDelta) {
                    closetFramerate = closetFramerate[0] < rate[0] ? rate : closetFramerate;
                }
            }
            params.setPreviewFpsRange(closetFramerate[0], closetFramerate[1]);

            // 请求最近支持的预览大小
            final Camera.Size closestSize = getClosestSupportedSize(params.getSupportedPreviewSizes(), width, height);
            params.setPreviewSize(closestSize.width, closestSize.height);


            // 在Nexus7上请求最接近的图片大小以解决纵横比问题
            final Camera.Size pictureSize = getClosestSupportedSize(params.getSupportedPictureSizes(), width, height);
            params.setPictureSize(pictureSize.width, pictureSize.height);

            //根据设备方向旋转相机预览
            setRotation(params);
            mCamera.setParameters(params);
        }

3.调用setDisplayOrientation(int) 确保正确的预览和照片方向

 private final void setRotation(final Camera.Parameters params) {
       
            final CameraGLSurfaceView parent = mWeakParent.get();
            if (parent == null) return;

            final Display display = ((WindowManager) parent.getContext().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
            final int rotation = display.getRotation();
            int degrees = 0;
            switch (rotation) {
                case Surface.ROTATION_0:
                    degrees = 0;
                    break;
                case Surface.ROTATION_90:
                    degrees = 90;
                    break;
                case Surface.ROTATION_180:
                    degrees = 180;
                    break;
                case Surface.ROTATION_270:
                    degrees = 270;
                    break;
            }
            //获取摄像头是前置摄像头还是后置摄像头
            final Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
            android.hardware.Camera.getCameraInfo(CAMERA_ID, info);
            int orientation = info.orientation;
            mIsFrontFace = (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT);
            if (mIsFrontFace) {    // front camera
                degrees = (orientation + degrees) % 360;
                degrees = (360 - degrees) % 360;  // reverse
            } else {  // back camera
                degrees = (orientation - degrees + 360) % 360;
            }

            // 设置方向
            mCamera.setDisplayOrientation(degrees);
            parent.mPreviewRotation = orientation;
            parent.mRotation = degrees;

        }

4.预览 ,调用startPreview(),开始更新预览图 ,将相机与SurfaceHolde或者texturer绑定Camera.setPreviewDisplay(surfaceHolder)
Camera.setPreviewTexture(surfaceTexture)

 /**
         * start camera preview
         *
         * @param width
         * @param height
         */
        private void startPreview(final int width, final int height, final SurfaceTexture surfaceTexture, int cameraId) {
            mViewWidth = width;
            mViewHeight = height;
            CAMERA_ID = cameraId;
            if (mCamera == null) {
                try {
                    openCamera(width, height);
                    final Camera.Size previewSize = mCamera.getParameters().getPreviewSize();
                    CameraManager.getInstance().getFirstCameraPreviewListener().onBeforeStartPreviewWithChained(previewSize.width, previewSize.height, true);
                    byte[] preAllocedBuffer = new byte[previewSize.width * previewSize.height * ImageFormat.getBitsPerPixel(ImageFormat.NV21)];
                    mCamera.addCallbackBuffer(preAllocedBuffer);
                    mCamera.setPreviewCallbackWithBuffer(this);
                } catch (final RuntimeException e) {
                    if (mCamera != null) {
                        mCamera.release();
                        mCamera = null;
                    }
                }

                if (mCamera != null) {
                    try {
                        mCamera.startPreview();
                    } catch (Exception e) {

                    }
                    CameraManager.getInstance().getFirstCameraPreviewListener().onAfterStartPreviewWithChained();
                }
            }

            if (surfaceTexture != null) {
                setPreviewTexture(surfaceTexture);
            }
        }


        private void setPreviewTexture(SurfaceTexture surfaceTexture) {
            if (mCamera != null && surfaceTexture != null) {
                mSurfaceTexture = surfaceTexture;
                try {
                    mCamera.setPreviewTexture(surfaceTexture);
                } catch (IOException e) {
                }
            }
        }

5.获取实时NV21格式的数据
mCamera.setPreviewCallbackWithBuffer(new Camera.PreviewCallback() {
@Override
public void onPreviewFrame(byte[] data, Camera camera) {

}

});
onPreview回调回来的data就是实时的帧数据,我们可以对数据进行处理,比如加美颜等等。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 197,966评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,170评论 2 375
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 144,909评论 0 327
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,959评论 1 268
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,851评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,583评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,956评论 3 388
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,590评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,878评论 1 293
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,892评论 2 314
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,719评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,501评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,957评论 3 300
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,124评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,440评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,003评论 2 343
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,211评论 2 339

推荐阅读更多精彩内容