The size and orientation of the camera android development

Transfer: https://glumes.com/post/android/android-camera-aspect-ratio-and-orientation , if infringement, please contact.

In the Android Camera development, two relatively suck problem is the size and orientation.

Wherein the size refers to:

  • The camera displays the frame size preview
  • The size of the camera frame
  • Android display controls the size of the camera preview

The direction refers to the

  • The camera displays the direction of the preview frame
  • Direction of the camera frame
  • Android phone's own direction

Properly handle these three directions and three dimensions in the development of their relations job here with Camera 1.0 version of the API as an example, refer to Google's open source project: cameraview  and  Android-Camera2Basic  .

size


Camera as a hardware device that can offer two sizes:

  • Preview frame size
  • Shooting frame size

Preview frame size

By  getSupportedPreviewSizes collection size preview frames may be supported methods.

		private final SizeMap mPreviewSizes = new SizeMap();
        mCamera = Camera.open(mCameraId);
        mCameraParameters = mCamera.getParameters();
        // Supported preview sizes
        mPreviewSizes.clear();
        for (Camera.Size size : mCameraParameters.getSupportedPreviewSizes()) {
            mPreviewSizes.add(new Size(size.width, size.height));
        }

And  mPreviewSizes that  SizeMap type, view source code, in fact, when you add a preview frame size length and width, they also calculated the aspect ratio and save up structure of the storage aspect ratio can be one to many relationship, It is the same aspect ratio, width and length can have a variety of sizes, so long as they are after the same proportions about the last minutes.

    // 同一个长宽比,对应多个尺寸
    private final ArrayMap<AspectRatio, SortedSet<Size>> mRatios = new ArrayMap<>();

For example, the size is 1920 * 1080 1280 * 720 and the aspect ratio is 16: 9 aspect ratio and the size of 800 * 640 * 600 and 480 are 4: 3.

Here argument is that the aspect ratio, there is talk aspect ratio. In fact all the same, are, the longer of value that side of the short side when the phone horizontally.

When calculating the aspect ratio, the width and the greatest common divisor necessary to obtain a high value, so as to be approximately divided calculate Euclidean algorithm, also called 辗转相除法: the greatest common divisor of two integers which equal the lesser of the number of greatest common divisor of two numbers and dividing the remainder. Into the code as follows:

	// a > b
    private static int gcd(int a, int b) {
        while (b != 0) {
            int c = b;
            b = a % b;
            a = c;
        }
        return a;
    }

Shooting frame size

By  getSupportedPictureSizes set photographing frame size can be supported methods.

        // Supported picture sizes;
        private final SizeMap mPictureSizes = new SizeMap();
        mPictureSizes.clear();
        for (Camera.Size size : mCameraParameters.getSupportedPictureSizes()) {
            mPictureSizes.add(new Size(size.width, size.height));
        }

Preview frames and similar storage structure, when obtaining a set of dimensions, and their corresponding calculated aspect ratio.

The Android size of the camera preview display control in the control method can get its corresponding Width and Height.

Computes aspect

With these three dimensions, the next step is how to deal with.

In order to preview and capturing, the image stretching phenomenon does not occur, the aspect ratio is preferably uniform aspect ratio and display a preview control frame, and aspect ratio of the shooting frame and preview frames and also controls the display aspect ratio consistent, in short, the best of the three aspect ratio is the same, we will have the best preview and shooting

Because the cell phone image preview control is made according to the size of the camera preview frame controls  the zoom come, when the aspect ratio will inevitably lead to inconsistencies preview image distortion. The aspect ratio is the aspect ratio of the preview frame and the frame of the shot is inconsistent, it will lead to deformation of stretching the picture was taken.

In  cameraview  source, first set the default aspect ratio of 4: 3.

AspectRatio DEFAULT_ASPECT_RATIO = AspectRatio.of(4, 3);

According to this aspect ratio, you can get a list of those dimensions according to the size of the set from the preview frame, and then find the width and height just above the preview control width and height dimensions from those lists. If the preview control is less than the width and height of the image it is stretched will result.

        SortedSet<Size> sizes = mPreviewSizes.sizes(mAspectRatio);
        if (sizes == null) { // Not supported
            mAspectRatio = chooseAspectRatio();
            // 根据选定的长宽比得到对应的支持的尺寸集合
            sizes = mPreviewSizes.sizes(mAspectRatio);
        }
        // 和预览控件的尺寸相比较,从尺寸集合中找到合适的尺寸
        Size size = chooseOptimalSize(sizes);
        // 把找到的合适尺寸,设置给相机的预览帧
        mCameraParameters.setPreviewSize(size.getWidth(), size.getHeight());

DETAILED find a preview frame size code is as follows:

    private Size chooseOptimalSize(SortedSet<Size> sizes) {
        if (!mPreview.isReady()) { // Not yet laid out
            return sizes.first(); // Return the smallest size
        }
        int desiredWidth;
        int desiredHeight;
        // 预览界面的尺寸
        final int surfaceWidth = mPreview.getWidth();
        final int surfaceHeight = mPreview.getHeight();
        // 是否是横屏,若是横屏的话,宽和高相互调换
        if (isLandscape(mDisplayOrientation)) {
            desiredWidth = surfaceHeight;
            desiredHeight = surfaceWidth;
        } else {
            desiredWidth = surfaceWidth;
            desiredHeight = surfaceHeight;
        }

        // 从选定的长宽比支持的尺寸中,找到长和宽都大于或等于控件尺寸的
        Size result = null;
        for (Size size : sizes) { // Iterate from small to large
            if (desiredWidth <= size.getWidth() && desiredHeight <= size.getHeight()) {
                return size;
            }
            result = size;
        }
        // 实在没有符合条件的,选择支持尺寸中最大的返回。
        return result;
    }

Note that when the screen is in the landscape mode type, width and preview control occurs transformed another job to be interchanged.

After finding the right size preview frame, you can set to the camera.

The size of the camera frame, and it is to be selected according to the aspect ratio.

        final Size pictureSize = mPictureSizes.sizes(mAspectRatio).last();

Under certain circumstances, aspect ratio, frame shooting often choose the largest size, as a clearer picture taken, which is why last used  last method.

Thus, in the case where the aspect ratio of the good is determined, it may be provided corresponding to the size.

Google's  android-Camera2Basic  project, there is such a code set size, which is determined in accordance with different maximum size of pictures taken good aspect ratio, instead of the default selection common 4: 3 ratio, after this foundation was set.

       Size largest = Collections.max(Arrays.asList(map.getOutputSizes(ImageFormat.JPEG)),
                        new CompareSizesByArea());

You can see, setting the aspect ratio is still very important aspect in the camera.

 

direction


Get the size of the problem, the left direction.

Your camera has two directions need to be addressed:

  • Preview frame direction
  • The direction of the shooting frame

To get a better camera experience, properly handle the preview frame and direction of shooting frames and allows the contents of the phone screen to see through all the normal direction.

It must first clear the nature of the phone:

  • When the mobile phone screen  竖立时的自然方向, this time, the coordinate origin at the upper left corner, the right X-axis positive direction, the positive direction of the Y-axis downward, aspect ratio short .
  • When the mobile phone screen  横放时的自然方向, this time, the coordinate origin at the upper left corner, the right X-axis positive direction, the positive direction of the Y-axis downward, aspect ratio length .

Preview frame direction

Image data while the camera is fixed to the sensor is on the phone with a camera from an image sensor of a hardware default viewing direction: origin is located in the phone counterclockwise horizontally upper left corner, i.e., applications consistent with the landscape screen orientation X . That is a 90 degree angle to the screen in the X direction vertical screen applications.

Pirates of the map here a few:

back_camera_coordinate

So, for landscape applications, the natural direction of the screen and the camera's image sensor the same direction, so the image seen is positive. As for the vertical screen applications, the preview image on the side coming. You will have to rotate the preview image 90 degrees clockwise to function properly preview image.

Horizontal screen shot results:

landscape_camera

Vertical screen shot results:

portrait

A deviation angle of 90 degrees on a preview screen and the direction of the natural direction of the camera, the Camera's  orientationproperties is also described:

camera_orientation_description

orientation indicates the direction of the camera image. Its value is to rotate the image clockwise camera image when the natural direction of the same equipment, it may be 0,90,180,270 four.

For vertical screen applications, the rear camera sensor is installed in the horizontal screen, the screen faces when you right if the natural direction of the rear edge of the top and the camera sensor device are parallel, the rear camera 90 is the orientation. If the right is the natural direction of the top edge of the front camera and the sensor device are parallel, the orientation of the front camera 270.

For front and rear camera orientation sensor are different, there may be different values ​​on different devices.

Activity in the absence of defined directions, using officially recommended code to set the direction:

  public static void setCameraDisplayOrientation(Activity activity, int cameraId, android.hardware.Camera camera) {
        android.hardware.Camera.CameraInfo info =
                new android.hardware.Camera.CameraInfo();
        android.hardware.Camera.getCameraInfo(cameraId, info);
        int rotation = activity.getWindowManager().getDefaultDisplay()
                .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;
        }

        int result;
        if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
            result = (info.orientation + degrees) % 360;
            result = (360 - result) % 360;  // compensate the mirror
        } else {  // back-facing
            result = (info.orientation - degrees + 360) % 360;
        }
        camera.setDisplayOrientation(result);
    }

First, calculate the angle of the device rotates counterclockwise, rear camera for calculation of the sensor: (info.orientation - degrees + 360)% 360.

Since the direction of the camera image needs to be restored to its natural direction of clockwise rotation, counterclockwise rotation and the screen that it comes off the rotatable camera, so the two are subtracted, then add 360 modulo operation.

For the front camera sensor, since the use of the front camera, in the vertical direction seen from the screen is often a mirror image because the camera hardware image flipped horizontally made, i.e. the vertical direction against the reversed image content , the pre-rotation is equivalent to 180 degrees. After then only needs to be rotated 90 degrees to the direction of the nature, but is a mirror image, i.e., the left-right inverted.

One thing to note is that before the API 14, first close the preview when you call setDisplayOrientation method.

Finally Pirates more clarity about:

The direction of the shooting frame

Determine the direction of the preview, when the direction of the shooting also need to determine.

You can set the final direction of the camera to shoot pictures by Camera.Parameters.setRotation function.

The official referral code:

    public void onOrientationChanged(int orientation) {
        if (orientation == ORIENTATION_UNKNOWN) {
            return;
        }
        android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
        android.hardware.Camera.getCameraInfo(cameraId, info);

        orientation = (orientation + 45) / 90 * 90;
        int rotation = 0;

        if (info.facing == CameraInfo.CAMERA_FACING_FRONT) {
            rotation = (info.orientation - orientation + 360) % 360;
        } else {  // back-facing camera
            rotation = (info.orientation + orientation) % 360;
        }
        mParameters.setRotation(rotation);
    }

Calculated direction of rotation, take into account the direction of the current screen and camera.

OrientationEventListener and Camera.orientation used in conjunction. When changing the screen orientation, OrientationEventListener will receive a corresponding notification, the callback method onOrientationChanged in to change the shooting direction of the camera, actually performed in the callback method in changing the direction of the camera preview.

OnOrientationChanged method returns the value from 0 ~ 359. The value can only be setRotation 0,90,180,270. So it is necessary to do a similar operation on the orientation of the screen rounding direction.

Of course getRotation method can get directions from the Display class on the line in this callback, in short, is there a notification callback, then change direction in this screen capture and preview.

For the front camera, the camera orientation and orientation of the difference between the two is the orientation angle to be rotated; for the rear camera, is the sum of the two to the angle of rotation.

Here, on the development of the camera is provided in the size and orientation have a clearer understanding.

reference


  1. https://blog.csdn.net/Tencent_Bugly/article/details/53375311
  2. https://blog.csdn.net/daiqiquan/article/details/40650055
  3. https://zhuanlan.zhihu.com/p/20559606
  4. http://javayhu.me/blog/2017/09/25/camera-development-experience-on-android/
Published 17 original articles · won praise 2 · views 20000 +

Guess you like

Origin blog.csdn.net/toove/article/details/94562894