diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/CameraOptions.java b/cameraview/src/main/java/com/otaliastudios/cameraview/CameraOptions.java index 7466e6df..f6401253 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/CameraOptions.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/CameraOptions.java @@ -12,6 +12,8 @@ import android.media.CamcorderProfile; import android.media.ImageReader; import android.media.MediaRecorder; import android.os.Build; +import android.util.Range; +import android.util.Rational; import com.otaliastudios.cameraview.controls.Audio; import com.otaliastudios.cameraview.controls.Control; @@ -198,7 +200,12 @@ public class CameraOptions { if (value != null) supportedHdr.add(value); } - // TODO zoom + //zoom + Float maxZoom = cameraCharacteristics.get(CameraCharacteristics.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM); + if(maxZoom != null) { + zoomSupported = maxZoom > 1; + } + // autofocus int[] afModes = cameraCharacteristics.get(CameraCharacteristics.CONTROL_AF_AVAILABLE_MODES); @@ -210,7 +217,14 @@ public class CameraOptions { } } - // TODO exposure correction + // Exposure correction + Range exposureRange = cameraCharacteristics.get(CameraCharacteristics.CONTROL_AE_COMPENSATION_RANGE); + if(exposureRange != null) { + exposureCorrectionMinValue = exposureRange.getLower(); + exposureCorrectionMaxValue = exposureRange.getUpper(); + } + + exposureCorrectionSupported = exposureCorrectionMinValue != 0 && exposureCorrectionMaxValue != 0; // Picture Sizes diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera2Engine.java b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera2Engine.java index 46058832..15af22a9 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera2Engine.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera2Engine.java @@ -24,6 +24,11 @@ import android.os.Build; import android.view.Surface; import android.view.SurfaceHolder; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.RequiresApi; +import androidx.annotation.WorkerThread; + import com.google.android.gms.tasks.Task; import com.google.android.gms.tasks.TaskCompletionSource; import com.google.android.gms.tasks.Tasks; @@ -60,11 +65,6 @@ import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.atomic.AtomicBoolean; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.annotation.RequiresApi; -import androidx.annotation.WorkerThread; - // TODO zoom // TODO exposure correction @RequiresApi(Build.VERSION_CODES.LOLLIPOP) @@ -926,13 +926,71 @@ public class Camera2Engine extends CameraEngine implements ImageReader.OnImageAv } @Override - public void setZoom(float zoom, @Nullable PointF[] points, boolean notify) { - // TODO + public void setZoom(final float zoom, final @Nullable PointF[] points, final boolean notify) { + mHandler.run(new Runnable() { + @Override + public void run() { + + if (getEngineState() == STATE_STARTED && mCameraOptions.isZoomSupported()) { + + Float maxZoom = mCameraCharacteristics.get(CameraCharacteristics.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM); + + if (maxZoom != null) { + //converting 0.0f-1.0f zoom scale to the actual camera digital zoom scale + //(which will be for example, 1.0-10.0) + float calculatedZoom = (zoom * (maxZoom - 1.0f)) + 1.0f; + + Rect newRect = getZoomRect(calculatedZoom, maxZoom); + mRepeatingRequestBuilder.set(CaptureRequest.SCALER_CROP_REGION, newRect); + applyRepeatingRequestBuilder(); + mZoomValue = zoom; + + if (notify) { + mCallback.dispatchOnZoomChanged(zoom, points); + } + } + + } + mZoomOp.end(null); + } + }); + } + + @NonNull + private Rect getZoomRect(float zoomLevel, float maxDigitalZoom) { + + Rect activeRect = readCharacteristic(mCameraCharacteristics, + CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE, + new Rect()); + + int minW = (int) (activeRect.width() / maxDigitalZoom); + int minH = (int) (activeRect.height() / maxDigitalZoom); + int difW = activeRect.width() - minW; + int difH = activeRect.height() - minH; + + int cropW = (int) (difW * (zoomLevel - 1) / (maxDigitalZoom - 1) / 2F); + int cropH = (int) (difH * (zoomLevel - 1) / (maxDigitalZoom - 1) / 2F); + return new Rect(cropW, cropH, activeRect.width() - cropW, activeRect.height() - cropH); } @Override - public void setExposureCorrection(float EVvalue, @NonNull float[] bounds, @Nullable PointF[] points, boolean notify) { - // TODO + public void setExposureCorrection(final float EVvalue, @NonNull final float[] bounds, @Nullable final PointF[] points, final boolean notify) { + mHandler.run(new Runnable() { + @Override + public void run() { + + if (getEngineState() == STATE_STARTED && mCameraOptions.isExposureCorrectionSupported()) { + mRepeatingRequestBuilder.set(CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION, (int) EVvalue); + applyRepeatingRequestBuilder(); + + mExposureCorrectionValue = EVvalue; + if (notify) { + mCallback.dispatchOnExposureCorrectionChanged(EVvalue, bounds, points); + } + } + mExposureCorrectionOp.end(null); + } + }); } //endregion @@ -1234,5 +1292,4 @@ public class Camera2Engine extends CameraEngine implements ImageReader.OnImageAv }; //endregion -} - +} \ No newline at end of file