Browse Source

Upload from camera: pinch to zoom, apect ratio

This implements pinch to zoom in the full range supported by the
camera HAL, fixes aspect ration handling on rotation, and sets up
for multiple resolution and aspect ratio support.

Signed-off-by: Adam Serbinski <adam@serbinski.com>
Adam Serbinski 3 years ago
parent
commit
d2d98314ee

+ 1 - 0
app/build.gradle

@@ -187,6 +187,7 @@ dependencies {
     ktlint "com.pinterest:ktlint:0.43.0"
     ktlint "com.pinterest:ktlint:0.43.0"
     implementation 'org.conscrypt:conscrypt-android:2.5.2'
     implementation 'org.conscrypt:conscrypt-android:2.5.2'
 
 
+    implementation 'androidx.camera:camera-core:1.0.1'
     implementation 'androidx.camera:camera-camera2:1.0.1'
     implementation 'androidx.camera:camera-camera2:1.0.1'
     implementation 'androidx.camera:camera-lifecycle:1.0.1'
     implementation 'androidx.camera:camera-lifecycle:1.0.1'
     implementation 'androidx.camera:camera-view:1.0.0-alpha28'
     implementation 'androidx.camera:camera-view:1.0.0-alpha28'

+ 38 - 12
app/src/main/java/com/nextcloud/talk/activities/TakePhotoActivity.java

@@ -32,6 +32,7 @@ import android.util.DisplayMetrics;
 import android.util.Log;
 import android.util.Log;
 import android.util.Size;
 import android.util.Size;
 import android.view.OrientationEventListener;
 import android.view.OrientationEventListener;
+import android.view.ScaleGestureDetector;
 import android.view.Surface;
 import android.view.Surface;
 import android.view.View;
 import android.view.View;
 import android.widget.Toast;
 import android.widget.Toast;
@@ -52,6 +53,7 @@ import java.util.concurrent.ExecutionException;
 import androidx.annotation.NonNull;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.Nullable;
 import androidx.appcompat.app.AppCompatActivity;
 import androidx.appcompat.app.AppCompatActivity;
+import androidx.camera.core.AspectRatio;
 import androidx.camera.core.Camera;
 import androidx.camera.core.Camera;
 import androidx.camera.core.ImageCapture;
 import androidx.camera.core.ImageCapture;
 import androidx.camera.core.ImageCaptureException;
 import androidx.camera.core.ImageCaptureException;
@@ -76,6 +78,9 @@ public class TakePhotoActivity extends AppCompatActivity {
 
 
     private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss", Locale.ROOT);
     private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss", Locale.ROOT);
 
 
+    private Camera camera;
+    private boolean crop = false, lowres = false;
+
     @Override
     @Override
     protected void onCreate(@Nullable Bundle savedInstanceState) {
     protected void onCreate(@Nullable Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         super.onCreate(savedInstanceState);
@@ -89,13 +94,12 @@ public class TakePhotoActivity extends AppCompatActivity {
         cameraProviderFuture.addListener(() -> {
         cameraProviderFuture.addListener(() -> {
             try {
             try {
                 final ProcessCameraProvider cameraProvider = cameraProviderFuture.get();
                 final ProcessCameraProvider cameraProvider = cameraProviderFuture.get();
-                final Preview preview = getPreview();
-                final ImageCapture imageCapture = getImageCapture();
-                final Camera camera = cameraProvider.bindToLifecycle(
+
+                camera = cameraProvider.bindToLifecycle(
                     this,
                     this,
                     viewModel.getCameraSelector(),
                     viewModel.getCameraSelector(),
-                    imageCapture,
-                    preview);
+                    getImageCapture(false, false),
+                    getPreview(false));
 
 
                 viewModel.getTorchToggleButtonImageResource()
                 viewModel.getTorchToggleButtonImageResource()
                     .observe(
                     .observe(
@@ -110,11 +114,11 @@ public class TakePhotoActivity extends AppCompatActivity {
                 binding.switchCamera.setOnClickListener((v) -> {
                 binding.switchCamera.setOnClickListener((v) -> {
                     viewModel.toggleCameraSelector();
                     viewModel.toggleCameraSelector();
                     cameraProvider.unbindAll();
                     cameraProvider.unbindAll();
-                    cameraProvider.bindToLifecycle(
+                    camera = cameraProvider.bindToLifecycle(
                         this,
                         this,
                         viewModel.getCameraSelector(),
                         viewModel.getCameraSelector(),
-                        imageCapture,
-                        preview);
+                        getImageCapture(crop, lowres),
+                        getPreview(crop));
                 });
                 });
                 binding.retake.setOnClickListener((v) -> {
                 binding.retake.setOnClickListener((v) -> {
                     Uri uri = (Uri) binding.photoPreview.getTag();
                     Uri uri = (Uri) binding.photoPreview.getTag();
@@ -133,6 +137,22 @@ public class TakePhotoActivity extends AppCompatActivity {
                     finish();
                     finish();
                 });
                 });
 
 
+                ScaleGestureDetector mDetector =
+                    new ScaleGestureDetector(this, new ScaleGestureDetector.SimpleOnScaleGestureListener(){
+                        @Override
+                        public boolean onScale(ScaleGestureDetector detector){
+                            float ratio = camera.getCameraInfo().getZoomState().getValue().getZoomRatio();
+                            float delta = detector.getScaleFactor();
+                            camera.getCameraControl().setZoomRatio(ratio * delta);
+                            return true;
+                        }
+                    });
+                binding.preview.setOnTouchListener((v, event) -> {
+                    v.performClick();
+                    mDetector.onTouchEvent(event);
+                    return true;
+                });
+
                 // Enable enlarging the image more than default 3x maximumScale.
                 // Enable enlarging the image more than default 3x maximumScale.
                 // Medium scale adapted to make double-tap behaviour more consistent.
                 // Medium scale adapted to make double-tap behaviour more consistent.
                 binding.photoPreview.setMaximumScale(MAX_SCALE);
                 binding.photoPreview.setMaximumScale(MAX_SCALE);
@@ -182,8 +202,12 @@ public class TakePhotoActivity extends AppCompatActivity {
         binding.photoPreview.setVisibility(View.VISIBLE);
         binding.photoPreview.setVisibility(View.VISIBLE);
     }
     }
 
 
-    private ImageCapture getImageCapture() {
-        final ImageCapture imageCapture = new ImageCapture.Builder().setTargetResolution(new Size(1080, 1920)).build();
+    private ImageCapture getImageCapture(boolean crop, boolean lowres) {
+        final ImageCapture imageCapture;
+        if (lowres) imageCapture = new ImageCapture.Builder()
+            .setTargetResolution(new Size(crop ? 1080 : 1440, 1920)).build();
+        else imageCapture = new ImageCapture.Builder()
+            .setTargetAspectRatio(crop ? AspectRatio.RATIO_16_9 : AspectRatio.RATIO_4_3).build();
 
 
         orientationEventListener = new OrientationEventListener(this) {
         orientationEventListener = new OrientationEventListener(this) {
             @Override
             @Override
@@ -288,9 +312,11 @@ public class TakePhotoActivity extends AppCompatActivity {
         return rotate;
         return rotate;
     }
     }
 
 
-    private Preview getPreview() {
-        Preview preview = new Preview.Builder().build();
+    private Preview getPreview(boolean crop) {
+        Preview preview = new Preview.Builder()
+            .setTargetAspectRatio(crop ? AspectRatio.RATIO_16_9 : AspectRatio.RATIO_4_3).build();
         preview.setSurfaceProvider(binding.preview.getSurfaceProvider());
         preview.setSurfaceProvider(binding.preview.getSurfaceProvider());
+
         return preview;
         return preview;
     }
     }
 
 

+ 3 - 2
app/src/main/res/layout/activity_take_picture.xml

@@ -32,14 +32,15 @@
     <androidx.camera.view.PreviewView
     <androidx.camera.view.PreviewView
         android:id="@+id/preview"
         android:id="@+id/preview"
         android:layout_width="match_parent"
         android:layout_width="match_parent"
-        android:layout_height="match_parent" />
+        android:layout_height="match_parent"
+        app:scaleType="fitCenter" />
 
 
     <com.github.chrisbanes.photoview.PhotoView
     <com.github.chrisbanes.photoview.PhotoView
         android:id="@+id/photo_preview"
         android:id="@+id/photo_preview"
         android:layout_width="match_parent"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:layout_height="match_parent"
         android:contentDescription="@null"
         android:contentDescription="@null"
-        android:scaleType="fitStart"
+        android:scaleType="fitCenter"
         android:visibility="invisible" />
         android:visibility="invisible" />
 
 
     <com.google.android.material.button.MaterialButton
     <com.google.android.material.button.MaterialButton