Skip to content

Commit

Permalink
Camera1 API: Split display orientation calculation from camera rotati…
Browse files Browse the repository at this point in the history
…on calculation (google#115)

- Adjusted camera rotation to flip when landscape
- Always apply parameters when opening a camera
  • Loading branch information
mkotyk authored and yaraki committed Jun 12, 2017
1 parent 9bbe07b commit 3eaeac0
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 24 deletions.
88 changes: 64 additions & 24 deletions library/src/main/api14/com/google/android/cameraview/Camera1.java
Original file line number Diff line number Diff line change
Expand Up @@ -257,14 +257,13 @@ void setDisplayOrientation(int displayOrientation) {
}
mDisplayOrientation = displayOrientation;
if (isCameraOpened()) {
int cameraRotation = calcCameraRotation(displayOrientation);
mCameraParameters.setRotation(cameraRotation);
mCameraParameters.setRotation(calcCameraRotation(displayOrientation));
mCamera.setParameters(mCameraParameters);
final boolean needsToStopPreview = mShowingPreview && Build.VERSION.SDK_INT < 14;
if (needsToStopPreview) {
mCamera.stopPreview();
}
mCamera.setDisplayOrientation(cameraRotation);
mCamera.setDisplayOrientation(calcDisplayOrientation(displayOrientation));
if (needsToStopPreview) {
mCamera.startPreview();
}
Expand Down Expand Up @@ -306,7 +305,7 @@ private void openCamera() {
mAspectRatio = Constants.DEFAULT_ASPECT_RATIO;
}
adjustCameraParameters();
mCamera.setDisplayOrientation(calcCameraRotation(mDisplayOrientation));
mCamera.setDisplayOrientation(calcDisplayOrientation(mDisplayOrientation));
mCallback.onCameraOpened();
}

Expand All @@ -328,22 +327,21 @@ void adjustCameraParameters() {
sizes = mPreviewSizes.sizes(mAspectRatio);
}
Size size = chooseOptimalSize(sizes);
final Camera.Size currentSize = mCameraParameters.getPictureSize();
if (currentSize.width != size.getWidth() || currentSize.height != size.getHeight()) {
// Largest picture size in this ratio
final Size pictureSize = mPictureSizes.sizes(mAspectRatio).last();
if (mShowingPreview) {
mCamera.stopPreview();
}
mCameraParameters.setPreviewSize(size.getWidth(), size.getHeight());
mCameraParameters.setPictureSize(pictureSize.getWidth(), pictureSize.getHeight());
mCameraParameters.setRotation(calcCameraRotation(mDisplayOrientation));
setAutoFocusInternal(mAutoFocus);
setFlashInternal(mFlash);
mCamera.setParameters(mCameraParameters);
if (mShowingPreview) {
mCamera.startPreview();
}

// Always re-apply camera parameters
// Largest picture size in this ratio
final Size pictureSize = mPictureSizes.sizes(mAspectRatio).last();
if (mShowingPreview) {
mCamera.stopPreview();
}
mCameraParameters.setPreviewSize(size.getWidth(), size.getHeight());
mCameraParameters.setPictureSize(pictureSize.getWidth(), pictureSize.getHeight());
mCameraParameters.setRotation(calcCameraRotation(mDisplayOrientation));
setAutoFocusInternal(mAutoFocus);
setFlashInternal(mFlash);
mCamera.setParameters(mCameraParameters);
if (mShowingPreview) {
mCamera.startPreview();
}
}

Expand All @@ -356,7 +354,7 @@ private Size chooseOptimalSize(SortedSet<Size> sizes) {
int desiredHeight;
final int surfaceWidth = mPreview.getWidth();
final int surfaceHeight = mPreview.getHeight();
if (mDisplayOrientation == 90 || mDisplayOrientation == 270) {
if (isLandscape(mDisplayOrientation)) {
desiredWidth = surfaceHeight;
desiredHeight = surfaceWidth;
} else {
Expand All @@ -382,14 +380,56 @@ private void releaseCamera() {
}
}

private int calcCameraRotation(int rotation) {
/**
* Calculate display orientation
* https://developer.android.com/reference/android/hardware/Camera.html#setDisplayOrientation(int)
*
* This calculation is used for orienting the preview
*
* Note: This is not the same calculation as the camera rotation
*
* @param screenOrientationDegrees Screen orientation in degrees
* @return Number of degrees required to rotate preview
*/
private int calcDisplayOrientation(int screenOrientationDegrees) {
if (mCameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
return (360 - (mCameraInfo.orientation + rotation) % 360) % 360;
return (360 - (mCameraInfo.orientation + screenOrientationDegrees) % 360) % 360;
} else { // back-facing
return (mCameraInfo.orientation - rotation + 360) % 360;
return (mCameraInfo.orientation - screenOrientationDegrees + 360) % 360;
}
}

/**
* Calculate camera rotation
*
* This calculation is applied to the output JPEG either via Exif Orientation tag
* or by actually transforming the bitmap. (Determined by vendor camera API implementation)
*
* Note: This is not the same calculation as the display orientation
*
* @param screenOrientationDegrees Screen orientation in degrees
* @return Number of degrees to rotate image in order for it to view correctly.
*/
private int calcCameraRotation(int screenOrientationDegrees) {
if (mCameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
return (mCameraInfo.orientation + screenOrientationDegrees) % 360;
} else { // back-facing
final int landscapeFlip = isLandscape(screenOrientationDegrees) ? 180 : 0;
return (mCameraInfo.orientation + screenOrientationDegrees + landscapeFlip) % 360;
}
}

/**
* Test if the supplied orientation is in landscape.
*
* @param orientationDegrees Orientation in degrees (0,90,180,270)
* @return True if in landscape, false if portrait
*/
private boolean isLandscape(int orientationDegrees) {
return (orientationDegrees == Constants.LANDSCAPE_90 ||
orientationDegrees == Constants.LANDSCAPE_270);
}

/**
* @return {@code true} if {@link #mCameraParameters} was modified.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,6 @@ interface Constants {
int FLASH_AUTO = 3;
int FLASH_RED_EYE = 4;

int LANDSCAPE_90 = 90;
int LANDSCAPE_270 = 270;
}

0 comments on commit 3eaeac0

Please sign in to comment.