mirror of
https://github.com/danog/termux-api.git
synced 2024-11-26 20:04:42 +01:00
PhotoAPI: Take sensor orientation into account.
On a Nexus 5X, the old code would take pictures that were upside-down. Apparently, the Android device standards require that the long edge of the sensor must align with the long edge of the device, but doesn't say which of the two ways to satisfy this manufacturers should pick. This change makes PhotoAPI generate right-side-up pictures in both conditions. Tested on a Nexus 7 (second-gen) and a Nexus 5X.
This commit is contained in:
parent
f9f439feb0
commit
4b3a1528b0
@ -2,7 +2,6 @@ package com.termux.api;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Camera;
|
||||
import android.graphics.ImageFormat;
|
||||
import android.graphics.SurfaceTexture;
|
||||
import android.hardware.camera2.CameraAccessException;
|
||||
@ -19,7 +18,6 @@ import android.media.ImageReader;
|
||||
import android.os.Looper;
|
||||
import android.util.Size;
|
||||
import android.view.Surface;
|
||||
import android.view.SurfaceView;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import com.termux.api.util.ResultReturner;
|
||||
@ -101,7 +99,7 @@ public class PhotoAPI {
|
||||
static void proceedWithOpenedCamera(final Context context, final CameraManager manager, final CameraDevice camera, final int previews, final File outputFile, final Looper looper, final PrintWriter stdout) throws CameraAccessException, IllegalArgumentException {
|
||||
final List<Surface> outputSurfaces = new ArrayList<>();
|
||||
|
||||
CameraCharacteristics characteristics = manager.getCameraCharacteristics(camera.getId());
|
||||
final CameraCharacteristics characteristics = manager.getCameraCharacteristics(camera.getId());
|
||||
|
||||
int autoExposureMode = CameraMetadata.CONTROL_AE_MODE_OFF;
|
||||
for (int supportedMode : characteristics.get(CameraCharacteristics.CONTROL_AE_AVAILABLE_MODES)) {
|
||||
@ -167,8 +165,7 @@ public class PhotoAPI {
|
||||
// Configure auto-focus (AF) and auto-exposure (AE) modes:
|
||||
jpegRequest.set(CaptureRequest.CONTROL_AF_MODE, CameraMetadata.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
|
||||
jpegRequest.set(CaptureRequest.CONTROL_AE_MODE, autoExposureModeFinal);
|
||||
// Orientation jpeg fix, from the Camera2BasicFragment example:
|
||||
fixOrientation(context, jpegRequest);
|
||||
jpegRequest.set(CaptureRequest.JPEG_ORIENTATION, correctOrientation(context, characteristics));
|
||||
|
||||
if (previews == 0) {
|
||||
saveImage(camera, session, jpegRequest.build());
|
||||
@ -222,27 +219,48 @@ public class PhotoAPI {
|
||||
}, null);
|
||||
}
|
||||
|
||||
/** Orientation jpeg fix, from the Camera2BasicFragment example. */
|
||||
static void fixOrientation(Context context, CaptureRequest.Builder request) {
|
||||
int cameraJpegOrientation;
|
||||
final int deviceOrientation = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getRotation();
|
||||
switch (deviceOrientation) {
|
||||
case Surface.ROTATION_0:
|
||||
cameraJpegOrientation = 90;
|
||||
break;
|
||||
case Surface.ROTATION_90:
|
||||
cameraJpegOrientation = 0;
|
||||
break;
|
||||
case Surface.ROTATION_180:
|
||||
cameraJpegOrientation = 270;
|
||||
break;
|
||||
case Surface.ROTATION_270:
|
||||
cameraJpegOrientation = 180;
|
||||
break;
|
||||
default:
|
||||
cameraJpegOrientation = 0;
|
||||
/**
|
||||
* Determine the correct JPEG orientation, taking into account device and sensor orientations.
|
||||
* See https://developer.android.com/reference/android/hardware/Camera.html#setDisplayOrientation(int)
|
||||
*/
|
||||
static int correctOrientation(final Context context, final CameraCharacteristics characteristics) {
|
||||
final Integer lensFacing = characteristics.get(CameraCharacteristics.LENS_FACING);
|
||||
final boolean isFrontFacing = lensFacing != null && lensFacing == CameraCharacteristics.LENS_FACING_FRONT;
|
||||
TermuxApiLogger.info((isFrontFacing ? "Using" : "Not using") + " a front facing camera.");
|
||||
|
||||
Integer sensorOrientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
|
||||
if (sensorOrientation != null) {
|
||||
TermuxApiLogger.info(String.format("Sensor orientation: %s degrees", sensorOrientation));
|
||||
} else {
|
||||
TermuxApiLogger.info("CameraCharacteristics didn't contain SENSOR_ORIENTATION. Assuming 0 degrees.");
|
||||
sensorOrientation = 0;
|
||||
}
|
||||
request.set(CaptureRequest.JPEG_ORIENTATION, cameraJpegOrientation);
|
||||
|
||||
int deviceOrientation;
|
||||
final int deviceRotation =
|
||||
((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getRotation();
|
||||
switch (deviceRotation) {
|
||||
case Surface.ROTATION_0: deviceOrientation = 0; break;
|
||||
case Surface.ROTATION_90: deviceOrientation = 90; break;
|
||||
case Surface.ROTATION_180: deviceOrientation = 180; break;
|
||||
case Surface.ROTATION_270: deviceOrientation = 270; break;
|
||||
default:
|
||||
TermuxApiLogger.info(
|
||||
String.format("Default display has unknown rotation %d. Assuming 0 degrees.", deviceRotation));
|
||||
deviceOrientation = 0;
|
||||
}
|
||||
TermuxApiLogger.info(String.format("Device orientation: %d degrees", deviceOrientation));
|
||||
|
||||
int jpegOrientation;
|
||||
if (isFrontFacing) {
|
||||
jpegOrientation = sensorOrientation + deviceOrientation;
|
||||
} else {
|
||||
jpegOrientation = sensorOrientation - deviceOrientation;
|
||||
}
|
||||
// Add an extra 360 because (-90 % 360) == -90 and Android won't accept a negative rotation.
|
||||
jpegOrientation = (jpegOrientation + 360) % 360;
|
||||
TermuxApiLogger.info(String.format("Returning JPEG orientation of %d degrees", jpegOrientation));
|
||||
return jpegOrientation;
|
||||
}
|
||||
|
||||
static void closeCamera(CameraDevice camera, Looper looper) {
|
||||
|
Loading…
Reference in New Issue
Block a user