Android相机开发

Android相机开发

推荐几个好的图片选择+拍照的框架
bilibili/boxing
LuckSiege/PictureSelector5900多个star
jeasonlzy/ImagePicker3600多个star
sucese/phoenix有Camera1和Camera2使用
只有相机功能
CameraKit/camerakit-android3900多个star
natario1/CameraView自由度很高的相机

申请权限

<uses-permission android:name="android.permission.CAMERA" />
<!--可以防止APP被安装到没有相机的Android设备上(目前仅Google Play支持)-->
<uses-feature android:name="android.hardware.camera" />

动态权限不要忘了

创建一个可以预览的界面

1.创建一个新工程

2.在新创建的工程中activity中布局文件

<FrameLayout
    android:id="@+id/preview_f"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

3.创建一个相机预览的view 继承SurfaceView

最新都开始用TextureView,关于SurfaceView/TextureView

  • SurfaceView是一个有自己Surface的View。界面渲染可以放在单独线程而不是主线程中。它更像是一个Window,自身不能做变形和动画。
  • TextureView同样也有自己的Surface。但是它只能在拥有硬件加速层层的Window中绘制,它更像是一个普通View,可以做变形和动画。

更多关于SurfaceView与TextureView区别的内容可以参考这篇文章Android 5.0(Lollipop)中的SurfaceTexture,TextureView, SurfaceView和GLSurfaceView.

官方给出的方案,图片来自于Android平台Camera开发实践指南:

《Android相机开发》 官方给出的方案

public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {

    private final SurfaceHolder mHolder;
    private Camera mCamera;

    public CameraPreview(Context context) {
        super(context);
        mHolder = getHolder();
        mHolder.addCallback(this);
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        //surface第一次创建时回调
        //打开相机
        mCamera = Camera.open();
        try {
            mCamera.setPreviewDisplay(holder);
            mCamera.startPreview();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        //surface变化的时候回调(格式/大小)
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        //surface销毁的时候回调
        mHolder.removeCallback(this);
        mCamera.setPreviewCallback(null);
        mCamera.stopPreview();
        mCamera.release();
        mCamera = null;
    }
}

4.在activity中添加

public class MainActivity extends AppCompatActivity {

    private FrameLayout mFrameLayout;

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

    private void initCamera() {
        CameraPreview preview = new CameraPreview(this);
        mFrameLayout.addView(preview);
    }

    private void initView() {
        mFrameLayout = (FrameLayout) findViewById(R.id.preview_f);
    }
}

至此可以显示一个相机界面,并有图像显示。

添加偏好设置

如分辨率、闪光灯、对焦等。

通过当前界面的相机camera对象获取起设置的参数getParameters()

预览分辨率

  • parameters.getSupportedPreviewSizes()获取相机支持的所有预览分辨率

预览格式

具体参照ImageFormat或者自己Google

  • parameters.getSupportedPreviewFormats()获取相机支持的所有预览格式

照片分辨率

  • parameters.getSupportedPictureSizes()获取相机支持的所有图片分辨率

图片格式

具体参照ImageFormat或者自己Google

  • parameters.getSupportedPictureFormats()获取相机支持的所有图片格式

视频分辨率

parameters.getSupportedVideoSizes()获取相机支持的所有视频分辨率

对焦模式

  • parameters.getSupportedFocusModes()获取相机支持的所有对焦模式

曝光补偿

  • parameters.getMinExposureCompensation()获取相机支持的最低曝光补偿
  • parameters.getMaxExposureCompensation()获取相机支持的最高曝光补偿

闪光灯模式

  • parameters.getSupportedFlashModes()获取相机支持的闪光灯模式

白平衡

  • parameters.getSupportedWhiteBalance()获取相机支持的白平衡

场景

parameters.getSupportedSceneModes()获取相机支持的场景

声明GPS权限

想要拍到的照片中包含GPS信息

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

代码如下

int numberOfCameras = Camera.getNumberOfCameras();
Log.d("123===", "相机个数===" + numberOfCameras);
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
for (int i = 0; i < numberOfCameras; i++) {
    Camera.getCameraInfo(i, cameraInfo);
    //后置:0 CAMERA_FACING_BACK; 前置:1 CAMERA_FACING_FRONT
    Log.d("123===", "当前相机信息=" + cameraInfo.facing);
}


Camera camera = mPreview.getCamera();
Camera.Parameters parameters = camera.getParameters();

Log.d("123===", "预览分辨率-----------");
List<Camera.Size> supportedPreviewSizes = parameters.getSupportedPreviewSizes();
for (Camera.Size previewSize : supportedPreviewSizes) {
    Log.d("123===", previewSize.width + "---" + previewSize.height);
}
Log.d("123===", "预览分辨率-----------");
Log.d("123===", "");
Log.d("123===", "");


Log.d("123===", "获得相机支持的图片预览格式-----------ImageFormat");
List<Integer> supportedPreviewFormats = parameters.getSupportedPreviewFormats();
for (Integer supportedPreviewFormat : supportedPreviewFormats) {
    Log.d("123===", supportedPreviewFormat + "");
}
Log.d("123===", "获得相机支持的图片预览格式-----------");
Log.d("123===", "");
Log.d("123===", "");


Log.d("123===", "照片分辨率-----------");
List<Camera.Size> supportedPictureSizes = parameters.getSupportedPictureSizes();
for (Camera.Size pictureSize : supportedPictureSizes) {
    Log.d("123===", pictureSize.width + "---" + pictureSize.height);
}
Log.d("123===", "照片分辨率-----------");
Log.d("123===", "");
Log.d("123===", "");


Log.d("123===", "获得相机支持的图片格式-----------ImageFormat");
List<Integer> supportedPictureFormats = parameters.getSupportedPictureFormats();
for (Integer supportedPreviewFormat : supportedPictureFormats) {
    Log.d("123===", supportedPreviewFormat + "");
}
Log.d("123===", "获得相机支持的图片格式-----------");
Log.d("123===", "");
Log.d("123===", "");


Log.d("123===", "视频分辨率-----------");
List<Camera.Size> supportedVideoSizes = parameters.getSupportedVideoSizes();
for (Camera.Size supportedVideoSize : supportedVideoSizes) {
    Log.d("123===", supportedVideoSize.width + "---" + supportedVideoSize.height);

}
Log.d("123===", "视频分辨率-----------");
Log.d("123===", "");
Log.d("123===", "");

Log.d("123===", "对焦模式-----------ImageFormat");
List<String> supportedFocusModes = parameters.getSupportedFocusModes();
for (String supportedFocusMode : supportedFocusModes) {
    Log.d("123===", supportedFocusMode + "");
}
Log.d("123===", "对焦模式-----------");
Log.d("123===", "");
Log.d("123===", "");

Log.d("123===", "曝光补偿-----------");
int minExposureCompensation = parameters.getMinExposureCompensation();
int maxExposureCompensation = parameters.getMaxExposureCompensation();
Log.d("123===", "最高=" + maxExposureCompensation);
Log.d("123===", "最低=" + minExposureCompensation);
Log.d("123===", "曝光补偿-----------");
Log.d("123===", "");
Log.d("123===", "");


Log.d("123===", "支持闪光灯模式-----------");
List<String> supportedFlashModes = parameters.getSupportedFlashModes();
for (String supportedFlashMode : supportedFlashModes) {
    Log.d("123===", "闪光模式--->" + supportedFlashMode);
}
Log.d("123===", "支持闪光灯模式-----------");
Log.d("123===", "");
Log.d("123===", "");


Log.d("123===", "支持白平衡-----------");
List<String> supportedWhiteBalance = parameters.getSupportedWhiteBalance();
for (String s : supportedWhiteBalance) {
    Log.d("123===", "--->" + s);
}
Log.d("123===", "支持白平衡-----------");
Log.d("123===", "");
Log.d("123===", "");

Log.d("123===", "场景-----------");
List<String> supportedSceneModes = parameters.getSupportedSceneModes();
for (String s : supportedSceneModes) {
    Log.d("123===", "--->" + s);
}
Log.d("123===", "场景-----------");
Log.d("123===", "");
Log.d("123===", "");

拍照,视频,对焦

假如需要使用原生拍照功能的话,Camera#takePicture()

拍照和视频都是网上那一套流程,具体的因为时间原因暂时先这样了。

相机预览和保存注意事项

下面三张图片引用自:Android: Camera相机开发详解(中) ——实现预览、拍照、保存照片等功能

  • 相机预览方向

《Android相机开发》 相机预览方向

  • 采集的图像方向

《Android相机开发》 采集的图像方向

  • 前置摄像头预览与保存一致

《Android相机开发》 前置摄像头预览与保存一致

参考

    原文作者:Thor_果冻
    原文地址: https://www.jianshu.com/p/c383c94aaf10
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞