diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/CameraController.java b/cameraview/src/main/java/com/otaliastudios/cameraview/CameraController.java index ba39b2f4..78ab6eea 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/CameraController.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/CameraController.java @@ -51,6 +51,7 @@ abstract class CameraController implements protected CameraOptions mCameraOptions; protected Mapper mMapper; protected FrameManager mFrameManager; + protected SizeSelector mPreviewSizeSelector; protected SizeSelector mPictureSizeSelector; protected MediaRecorder mMediaRecorder; protected File mVideoFile; @@ -270,8 +271,12 @@ abstract class CameraController implements mDeviceOrientation = deviceOrientation; } - final void setPictureSizeSelector(SizeSelector selector) { - mPictureSizeSelector = selector; + final void setPreviewSizeSelector(SizeSelector previewSizeSelector) { + mPreviewSizeSelector = previewSizeSelector; + } + + final void setPictureSizeSelector(SizeSelector pictureSizeSelector) { + mPictureSizeSelector = pictureSizeSelector; } //endregion @@ -366,6 +371,10 @@ abstract class CameraController implements return mAudio; } + public SizeSelector getPreviewSizeSelector() { + return mPreviewSizeSelector; + } + final SizeSelector getPictureSizeSelector() { return mPictureSizeSelector; } @@ -480,19 +489,28 @@ abstract class CameraController implements boolean flip = shouldFlipSizes(); AspectRatio targetRatio = AspectRatio.of(mPictureSize.getWidth(), mPictureSize.getHeight()); Size targetMinSize = mPreview.getSurfaceSize(); - if (flip) targetMinSize = targetMinSize.flip(); + if (flip) { + ArrayList temp = new ArrayList<>(previewSizes.size()); + for (Size previewSize : previewSizes) { + temp.add(previewSize.flip()); + } + + previewSizes = temp; + } LOG.i("size:", "computePreviewSize:", "targetRatio:", targetRatio, "targetMinSize:", targetMinSize); SizeSelector matchRatio = SizeSelectors.aspectRatio(targetRatio, 0); SizeSelector matchSize = SizeSelectors.and( SizeSelectors.minHeight(targetMinSize.getHeight()), SizeSelectors.minWidth(targetMinSize.getWidth())); SizeSelector matchAll = SizeSelectors.or( + mPreviewSizeSelector, SizeSelectors.and(matchRatio, matchSize), SizeSelectors.and(matchRatio, SizeSelectors.biggest()), // If couldn't match both, match ratio and biggest. SizeSelectors.biggest() // If couldn't match any, take the biggest. ); Size result = matchAll.select(previewSizes).get(0); LOG.i("computePreviewSize:", "result:", result, "flip:", flip); + if (flip) result = result.flip(); return result; } diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java b/cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java index 4b0a1dec..1e1dff29 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java @@ -27,6 +27,7 @@ import android.widget.FrameLayout; import java.io.ByteArrayOutputStream; import java.io.File; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; @@ -109,33 +110,68 @@ public class CameraView extends FrameLayout { Audio audio = Audio.fromValue(a.getInteger(R.styleable.CameraView_cameraAudio, Audio.DEFAULT.value())); // Size selectors - List constraints = new ArrayList<>(3); + List previewSizeSelectors = new ArrayList<>(3); + if (a.hasValue(R.styleable.CameraView_cameraPreviewSizeMinWidth)) { + previewSizeSelectors.add(SizeSelectors.minWidth(a.getInteger(R.styleable.CameraView_cameraPreviewSizeMinWidth, 0))); + } + if (a.hasValue(R.styleable.CameraView_cameraPreviewSizeMaxWidth)) { + previewSizeSelectors.add(SizeSelectors.maxWidth(a.getInteger(R.styleable.CameraView_cameraPreviewSizeMaxWidth, 0))); + } + if (a.hasValue(R.styleable.CameraView_cameraPreviewSizeMinHeight)) { + previewSizeSelectors.add(SizeSelectors.minHeight(a.getInteger(R.styleable.CameraView_cameraPreviewSizeMinHeight, 0))); + } + if (a.hasValue(R.styleable.CameraView_cameraPreviewSizeMaxHeight)) { + previewSizeSelectors.add(SizeSelectors.maxHeight(a.getInteger(R.styleable.CameraView_cameraPreviewSizeMaxHeight, 0))); + } + if (a.hasValue(R.styleable.CameraView_cameraPreviewSizeMinArea)) { + previewSizeSelectors.add(SizeSelectors.minArea(a.getInteger(R.styleable.CameraView_cameraPreviewSizeMinArea, 0))); + } + if (a.hasValue(R.styleable.CameraView_cameraPreviewSizeMaxArea)) { + previewSizeSelectors.add(SizeSelectors.maxArea(a.getInteger(R.styleable.CameraView_cameraPreviewSizeMaxArea, 0))); + } + if (a.hasValue(R.styleable.CameraView_cameraPreviewSizeAspectRatio)) { + //noinspection ConstantConditions + previewSizeSelectors.add(SizeSelectors.aspectRatio(AspectRatio.parse(a.getString(R.styleable.CameraView_cameraPreviewSizeAspectRatio)), 0)); + } + if (a.getBoolean(R.styleable.CameraView_cameraPreviewSizeSmallest, false)) previewSizeSelectors.add(SizeSelectors.smallest()); + if (a.getBoolean(R.styleable.CameraView_cameraPreviewSizeBiggest, false)) previewSizeSelectors.add(SizeSelectors.biggest()); + SizeSelector previewSizeSelector = !previewSizeSelectors.isEmpty() ? + SizeSelectors.and(previewSizeSelectors.toArray(new SizeSelector[previewSizeSelectors.size()])) : + new SizeSelector() { + @NonNull + @Override + public List select(@NonNull List source) { + return Collections.emptyList(); + } + }; + + List pictureSizeSelectors = new ArrayList<>(3); if (a.hasValue(R.styleable.CameraView_cameraPictureSizeMinWidth)) { - constraints.add(SizeSelectors.minWidth(a.getInteger(R.styleable.CameraView_cameraPictureSizeMinWidth, 0))); + pictureSizeSelectors.add(SizeSelectors.minWidth(a.getInteger(R.styleable.CameraView_cameraPictureSizeMinWidth, 0))); } if (a.hasValue(R.styleable.CameraView_cameraPictureSizeMaxWidth)) { - constraints.add(SizeSelectors.maxWidth(a.getInteger(R.styleable.CameraView_cameraPictureSizeMaxWidth, 0))); + pictureSizeSelectors.add(SizeSelectors.maxWidth(a.getInteger(R.styleable.CameraView_cameraPictureSizeMaxWidth, 0))); } if (a.hasValue(R.styleable.CameraView_cameraPictureSizeMinHeight)) { - constraints.add(SizeSelectors.minHeight(a.getInteger(R.styleable.CameraView_cameraPictureSizeMinHeight, 0))); + pictureSizeSelectors.add(SizeSelectors.minHeight(a.getInteger(R.styleable.CameraView_cameraPictureSizeMinHeight, 0))); } if (a.hasValue(R.styleable.CameraView_cameraPictureSizeMaxHeight)) { - constraints.add(SizeSelectors.maxHeight(a.getInteger(R.styleable.CameraView_cameraPictureSizeMaxHeight, 0))); + pictureSizeSelectors.add(SizeSelectors.maxHeight(a.getInteger(R.styleable.CameraView_cameraPictureSizeMaxHeight, 0))); } if (a.hasValue(R.styleable.CameraView_cameraPictureSizeMinArea)) { - constraints.add(SizeSelectors.minArea(a.getInteger(R.styleable.CameraView_cameraPictureSizeMinArea, 0))); + pictureSizeSelectors.add(SizeSelectors.minArea(a.getInteger(R.styleable.CameraView_cameraPictureSizeMinArea, 0))); } if (a.hasValue(R.styleable.CameraView_cameraPictureSizeMaxArea)) { - constraints.add(SizeSelectors.maxArea(a.getInteger(R.styleable.CameraView_cameraPictureSizeMaxArea, 0))); + pictureSizeSelectors.add(SizeSelectors.maxArea(a.getInteger(R.styleable.CameraView_cameraPictureSizeMaxArea, 0))); } if (a.hasValue(R.styleable.CameraView_cameraPictureSizeAspectRatio)) { //noinspection ConstantConditions - constraints.add(SizeSelectors.aspectRatio(AspectRatio.parse(a.getString(R.styleable.CameraView_cameraPictureSizeAspectRatio)), 0)); + pictureSizeSelectors.add(SizeSelectors.aspectRatio(AspectRatio.parse(a.getString(R.styleable.CameraView_cameraPictureSizeAspectRatio)), 0)); } - if (a.getBoolean(R.styleable.CameraView_cameraPictureSizeSmallest, false)) constraints.add(SizeSelectors.smallest()); - if (a.getBoolean(R.styleable.CameraView_cameraPictureSizeBiggest, false)) constraints.add(SizeSelectors.biggest()); - SizeSelector selector = !constraints.isEmpty() ? - SizeSelectors.and(constraints.toArray(new SizeSelector[constraints.size()])) : + if (a.getBoolean(R.styleable.CameraView_cameraPictureSizeSmallest, false)) pictureSizeSelectors.add(SizeSelectors.smallest()); + if (a.getBoolean(R.styleable.CameraView_cameraPictureSizeBiggest, false)) pictureSizeSelectors.add(SizeSelectors.biggest()); + SizeSelector pictureSizeSelector = !pictureSizeSelectors.isEmpty() ? + SizeSelectors.and(pictureSizeSelectors.toArray(new SizeSelector[pictureSizeSelectors.size()])) : SizeSelectors.biggest(); // Gestures @@ -181,7 +217,8 @@ public class CameraView extends FrameLayout { setGrid(grid); setHdr(hdr); setAudio(audio); - setPictureSize(selector); + setPreviewSize(previewSizeSelector); + setPictureSize(pictureSizeSelector); // Apply gestures mapGesture(Gesture.TAP, tapGesture); @@ -1008,6 +1045,17 @@ public class CameraView extends FrameLayout { } + /** + * Sets preview size. The {@link SizeSelector} will be invoked with the list of available + * size, and the first acceptable size will be accepted and passed to the internal engine. + * See the {@link SizeSelectors} class for handy utilities for creating selectors. + * + * @param selector a size selector + */ + public void setPreviewSize(@NonNull SizeSelector selector) { + mCameraController.setPreviewSizeSelector(selector); + } + /** * Sets picture capture size. The {@link SizeSelector} will be invoked with the list of available * size, and the first acceptable size will be accepted and passed to the internal engine. diff --git a/cameraview/src/main/res/values/attrs.xml b/cameraview/src/main/res/values/attrs.xml index d52abdd1..a2a1f1be 100644 --- a/cameraview/src/main/res/values/attrs.xml +++ b/cameraview/src/main/res/values/attrs.xml @@ -2,6 +2,24 @@ + + + + + + + + + + + + + + + + + + diff --git a/demo/src/main/java/com/otaliastudios/cameraview/demo/CameraActivity.java b/demo/src/main/java/com/otaliastudios/cameraview/demo/CameraActivity.java index 4337a629..2911e47e 100644 --- a/demo/src/main/java/com/otaliastudios/cameraview/demo/CameraActivity.java +++ b/demo/src/main/java/com/otaliastudios/cameraview/demo/CameraActivity.java @@ -55,6 +55,12 @@ public class CameraActivity extends AppCompatActivity implements View.OnClickLis } }); + // You can control preview size +// camera.setPreviewSize(SizeSelectors.and( +// SizeSelectors.maxWidth(getWindowManager().getDefaultDisplay().getWidth() / 2), +// SizeSelectors.biggest() +// )); + findViewById(R.id.edit).setOnClickListener(this); findViewById(R.id.capturePhoto).setOnClickListener(this); findViewById(R.id.captureVideo).setOnClickListener(this);