diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/Camera1.java b/cameraview/src/main/java/com/otaliastudios/cameraview/Camera1.java
index 76c09970..758bb895 100644
--- a/cameraview/src/main/java/com/otaliastudios/cameraview/Camera1.java
+++ b/cameraview/src/main/java/com/otaliastudios/cameraview/Camera1.java
@@ -580,18 +580,6 @@ class Camera1 extends CameraController implements Camera.PreviewCallback, Camera
/**
* Just a note about the snapshot size - it is the PreviewStreamSize, cropped with the view ratio.
- * One might be tempted to say that it is the SurfaceSize (which already matches the view ratio),
- * but it's not.
- *
- * The camera sensor will capture preview frames with PreviewStreamSize and that's it. Then they
- * are hardware-scaled by the preview surface, but this does not affect the snapshot, as the
- * snapshot recorder simply creates another surface.
- *
- * Done tests to ensure that this is true, by using
- * 1. small SurfaceSize and biggest() PreviewStreamSize: output is not low quality
- * 2. big SurfaceSize and smallest() PreviewStreamSize: output is low quality
- * In both cases the result.size here was set to the biggest of the two.
- *
* @param viewAspectRatio the view aspect ratio
*/
@Override
@@ -607,7 +595,7 @@ class Camera1 extends CameraController implements Camera.PreviewCallback, Camera
result.location = mLocation;
result.isSnapshot = true;
result.facing = mFacing;
- result.size = getPreviewStreamSize(REF_OUTPUT); // Not the real size: it will be cropped to match the view ratio
+ result.size = getUncroppedSnapshotSize(REF_OUTPUT); // Not the real size: it will be cropped to match the view ratio
result.rotation = offset(REF_SENSOR, REF_OUTPUT); // Actually it will be rotated and set to 0.
AspectRatio outputRatio = flip(REF_OUTPUT, REF_VIEW) ? viewAspectRatio.inverse() : viewAspectRatio;
// LOG.e("ROTBUG_pic", "aspectRatio (REF_VIEW):", viewAspectRatio);
@@ -713,11 +701,6 @@ class Camera1 extends CameraController implements Camera.PreviewCallback, Camera
}
/**
- * Is output size the SurfaceSize or the PreviewStreamSize ?
- * I could not find evidence by testing, but I think that comments in {@link #takePictureSnapshot(AspectRatio)}
- * would still apply here, despite the capturing mechanism being different.
- * So we should use PreviewStreamSize as output size, cropped by the view aspect ratio.
- *
* @param file the output file
* @param viewAspectRatio the view aspect ratio
*/
@@ -783,7 +766,7 @@ class Camera1 extends CameraController implements Camera.PreviewCallback, Camera
// Based on this we will use VO for everything. See if we get issues about distortion
// and maybe we can improve. The reason why this happen is beyond my understanding.
- Size outputSize = getPreviewStreamSize(REF_OUTPUT);
+ Size outputSize = getUncroppedSnapshotSize(REF_OUTPUT);
AspectRatio outputRatio = flip(REF_OUTPUT, REF_VIEW) ? viewAspectRatio.inverse() : viewAspectRatio;
Rect outputCrop = CropHelper.computeCrop(outputSize, outputRatio);
outputSize = new Size(outputCrop.width(), outputCrop.height());
diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/CameraController.java b/cameraview/src/main/java/com/otaliastudios/cameraview/CameraController.java
index bf48253c..9699ea9e 100644
--- a/cameraview/src/main/java/com/otaliastudios/cameraview/CameraController.java
+++ b/cameraview/src/main/java/com/otaliastudios/cameraview/CameraController.java
@@ -53,6 +53,9 @@ abstract class CameraController implements
private SizeSelector mPictureSizeSelector;
private SizeSelector mVideoSizeSelector;
+ private int mSnapshotMaxWidth = Integer.MAX_VALUE; // in REF_VIEW for consistency with SizeSelectors
+ private int mSnapshotMaxHeight = Integer.MAX_VALUE; // in REF_VIEW for consistency with SizeSelectors
+
protected int mCameraId;
protected CameraOptions mCameraOptions;
protected Mapper mMapper;
@@ -311,6 +314,14 @@ abstract class CameraController implements
mAudioBitRate = audioBitRate;
}
+ final void setSnapshotMaxWidth(int maxWidth) {
+ mSnapshotMaxWidth = maxWidth;
+ }
+
+ final void setSnapshotMaxHeight(int maxHeight) {
+ mSnapshotMaxHeight = maxHeight;
+ }
+
//endregion
//region Abstract setters and APIs
@@ -518,6 +529,39 @@ abstract class CameraController implements
return flip(REF_VIEW, reference) ? mPreview.getSurfaceSize().flip() : mPreview.getSurfaceSize();
}
+ /**
+ * Returns the snapshot size, but not cropped with the view dimensions, which
+ * is what we will do before creating the snapshot. However, cropping is done at various
+ * levels so we don't want to perform the op here.
+ *
+ * The base snapshot size is based on PreviewStreamSize (later cropped with view ratio). Why?
+ * One might be tempted to say that it is the SurfaceSize (which already matches the view ratio).
+ *
+ * The camera sensor will capture preview frames with PreviewStreamSize and that's it. Then they
+ * are hardware-scaled by the preview surface, but this does not affect the snapshot, as the
+ * snapshot recorder simply creates another surface.
+ *
+ * Done tests to ensure that this is true, by using
+ * 1. small SurfaceSize and biggest() PreviewStreamSize: output is not low quality
+ * 2. big SurfaceSize and smallest() PreviewStreamSize: output is low quality
+ * In both cases the result.size here was set to the biggest of the two.
+ *
+ * I could not find the same evidence for videos, but I would say that the same things should
+ * apply, despite the capturing mechanism being different.
+ */
+ @Nullable
+ final Size getUncroppedSnapshotSize(int reference) {
+ Size baseSize = getPreviewStreamSize(reference);
+ if (baseSize == null) return null;
+ boolean flip = flip(reference, REF_VIEW);
+ int maxWidth = flip ? mSnapshotMaxHeight : mSnapshotMaxWidth;
+ int maxHeight = flip ? mSnapshotMaxWidth : mSnapshotMaxHeight;
+ return new Size(
+ Math.min(baseSize.getWidth(), maxWidth),
+ Math.max(baseSize.getHeight(), maxHeight)
+ );
+ }
+
//endregion
diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java b/cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java
index 489a5cfe..deafbe50 100644
--- a/cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java
+++ b/cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java
@@ -1388,6 +1388,27 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
});
}
+ /**
+ * Sets the max width for snapshots taken with {@link #takePictureSnapshot()} or
+ * {@link #takeVideoSnapshot(File)}. If the snapshot width exceeds this value, the snapshot
+ * will be scaled down to match this constraint.
+ *
+ * @param maxWidth max width for snapshots
+ */
+ public void setSnapshotMaxWidth(int maxWidth) {
+ mCameraController.setSnapshotMaxWidth(maxWidth);
+ }
+
+ /**
+ * Sets the max height for snapshots taken with {@link #takePictureSnapshot()} or
+ * {@link #takeVideoSnapshot(File)}. If the snapshot height exceeds this value, the snapshot
+ * will be scaled down to match this constraint.
+ *
+ * @param maxHeight max height for snapshots
+ */
+ public void setSnapshotMaxHeight(int maxHeight) {
+ mCameraController.setSnapshotMaxHeight(maxHeight);
+ }
/**
* Returns the size used for snapshots, or null if it hasn't been computed
@@ -1402,7 +1423,7 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
// Get the preview size and crop according to the current view size.
// It's better to do calculations in the REF_VIEW reference, and then flip if needed.
- Size preview = mCameraController.getPreviewStreamSize(CameraController.REF_VIEW);
+ Size preview = mCameraController.getUncroppedSnapshotSize(CameraController.REF_VIEW);
AspectRatio viewRatio = AspectRatio.of(getWidth(), getHeight());
Rect crop = CropHelper.computeCrop(preview, viewRatio);
Size cropSize = new Size(crop.width(), crop.height());
diff --git a/cameraview/src/main/res/values/attrs.xml b/cameraview/src/main/res/values/attrs.xml
index f25628fe..5ea86273 100644
--- a/cameraview/src/main/res/values/attrs.xml
+++ b/cameraview/src/main/res/values/attrs.xml
@@ -25,6 +25,9 @@
+
+
+