Add setPreviewSize method

pull/360/head
Mattia Iavarone 6 years ago
parent 26f313c74e
commit bc85178acf
  1. 9
      cameraview/src/androidTest/java/com/otaliastudios/cameraview/CameraViewTest.java
  2. 2
      cameraview/src/androidTest/java/com/otaliastudios/cameraview/MockCameraController.java
  3. 47
      cameraview/src/main/java/com/otaliastudios/cameraview/CameraController.java
  4. 22
      cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java
  5. 35
      docs/_posts/2018-12-20-preview-size.md
  6. 18
      docs/_posts/2018-12-20-v1-migration-guide.md
  7. 3
      docs/index.md

@ -558,6 +558,15 @@ public class CameraViewTest extends BaseTest {
assertEquals(cameraView.getVideoCodec(), VideoCodec.H_264); assertEquals(cameraView.getVideoCodec(), VideoCodec.H_264);
} }
@Test
public void testPreviewSizeSelector() {
SizeSelector source = SizeSelectors.minHeight(50);
cameraView.setPreviewSize(source);
SizeSelector result = mockController.getPreviewSizeSelector();
assertNotNull(result);
assertEquals(result, source);
}
@Test @Test
public void testPictureSizeSelector() { public void testPictureSizeSelector() {
SizeSelector source = SizeSelectors.minHeight(50); SizeSelector source = SizeSelectors.minHeight(50);

@ -109,7 +109,7 @@ public class MockCameraController extends CameraController {
} }
@Override @Override
void startAutoFocus(@Nullable Gesture gesture, PointF point) { void startAutoFocus(@Nullable Gesture gesture, @NonNull PointF point) {
mFocusStarted = true; mFocusStarted = true;
} }

@ -49,13 +49,15 @@ abstract class CameraController implements
protected float mExposureCorrectionValue; protected float mExposureCorrectionValue;
protected boolean mPlaySounds; protected boolean mPlaySounds;
@Nullable private SizeSelector mPreviewSizeSelector;
private SizeSelector mPictureSizeSelector;
private SizeSelector mVideoSizeSelector;
protected int mCameraId; protected int mCameraId;
protected CameraOptions mCameraOptions; protected CameraOptions mCameraOptions;
protected Mapper mMapper; protected Mapper mMapper;
protected FrameManager mFrameManager; protected FrameManager mFrameManager;
protected SizeSelector mPictureSizeSelector;
protected PictureRecorder mPictureRecorder; protected PictureRecorder mPictureRecorder;
protected SizeSelector mVideoSizeSelector;
protected VideoRecorder mVideoRecorder; protected VideoRecorder mVideoRecorder;
protected long mVideoMaxSize; protected long mVideoMaxSize;
protected int mVideoMaxDuration; protected int mVideoMaxDuration;
@ -221,6 +223,7 @@ abstract class CameraController implements
} }
// Forces a restart. // Forces a restart.
@SuppressWarnings("WeakerAccess")
protected final void restart() { protected final void restart() {
LOG.i("Restart:", "posting runnable"); LOG.i("Restart:", "posting runnable");
mHandler.post(new Runnable() { mHandler.post(new Runnable() {
@ -274,6 +277,10 @@ abstract class CameraController implements
mDeviceOrientation = deviceOrientation; mDeviceOrientation = deviceOrientation;
} }
final void setPreviewSizeSelector(@Nullable SizeSelector selector) {
mPreviewSizeSelector = selector;
}
final void setPictureSizeSelector(@NonNull SizeSelector selector) { final void setPictureSizeSelector(@NonNull SizeSelector selector) {
mPictureSizeSelector = selector; mPictureSizeSelector = selector;
} }
@ -343,7 +350,7 @@ abstract class CameraController implements
abstract void stopVideo(); abstract void stopVideo();
abstract void startAutoFocus(@Nullable Gesture gesture, PointF point); abstract void startAutoFocus(@Nullable Gesture gesture, @NonNull PointF point);
abstract void setPlaySounds(boolean playSounds); abstract void setPlaySounds(boolean playSounds);
@ -411,6 +418,11 @@ abstract class CameraController implements
return mAudioBitRate; return mAudioBitRate;
} }
@Nullable
/* for tests */ final SizeSelector getPreviewSizeSelector() {
return mPreviewSizeSelector;
}
@NonNull @NonNull
/* for tests */ final SizeSelector getPictureSizeSelector() { /* for tests */ final SizeSelector getPictureSizeSelector() {
return mPictureSizeSelector; return mPictureSizeSelector;
@ -532,12 +544,19 @@ abstract class CameraController implements
@NonNull @NonNull
@SuppressWarnings("WeakerAccess") @SuppressWarnings("WeakerAccess")
protected final Size computePreviewSize(@NonNull List<Size> previewSizes) { protected final Size computePreviewSize(@NonNull List<Size> previewSizes) {
// instead of flipping everything to REF_VIEW, we can just flip the // These sizes come in REF_SENSOR. Since there is an external selector involved,
// surface size from REF_VIEW to REF_SENSOR, and reflip at the end. // we must convert all of them to REF_VIEW, then flip back when returning.
AspectRatio targetRatio = AspectRatio.of(mCaptureSize.getWidth(), mCaptureSize.getHeight()); boolean flip = flip(REF_SENSOR, REF_VIEW);
List<Size> sizes = new ArrayList<>(previewSizes.size());
for (Size size : previewSizes) {
sizes.add(flip ? size.flip() : size);
}
// Create our own default selector, which will be used if the external mPreviewSizeSelector
// is null, or if it fails in finding a size.
Size targetMinSize = mPreview.getOutputSurfaceSize(); Size targetMinSize = mPreview.getOutputSurfaceSize();
boolean flip = flip(REF_VIEW, REF_SENSOR); AspectRatio targetRatio = AspectRatio.of(mCaptureSize.getWidth(), mCaptureSize.getHeight());
if (flip) targetMinSize = targetMinSize.flip(); if (flip) targetRatio = targetRatio.inverse();
LOG.i("size:", "computePreviewSize:", "targetRatio:", targetRatio, "targetMinSize:", targetMinSize); LOG.i("size:", "computePreviewSize:", "targetRatio:", targetRatio, "targetMinSize:", targetMinSize);
SizeSelector matchRatio = SizeSelectors.and( // Match this aspect ratio and sort by biggest SizeSelector matchRatio = SizeSelectors.and( // Match this aspect ratio and sort by biggest
SizeSelectors.aspectRatio(targetRatio, 0), SizeSelectors.aspectRatio(targetRatio, 0),
@ -552,7 +571,17 @@ abstract class CameraController implements
matchRatio, // If couldn't respect size, at least match aspect ratio matchRatio, // If couldn't respect size, at least match aspect ratio
SizeSelectors.biggest() // If couldn't match any, take the biggest. SizeSelectors.biggest() // If couldn't match any, take the biggest.
); );
Size result = matchAll.select(previewSizes).get(0);
// Apply the external selector with this as a fallback,
// and return a size in REF_SENSOR reference.
SizeSelector selector;
if (mPreviewSizeSelector != null) {
selector = SizeSelectors.or(mPreviewSizeSelector, matchAll);
} else {
selector = matchAll;
}
Size result = selector.select(sizes).get(0);
if (flip) result = result.flip();
LOG.i("computePreviewSize:", "result:", result, "flip:", flip); LOG.i("computePreviewSize:", "result:", result, "flip:", flip);
return result; return result;
} }

@ -1062,6 +1062,28 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
} }
/**
* <strong>ADVANCED FEATURE</strong> - sets a size selector for the preview stream.
* The {@link SizeSelector} will be invoked with the list of available sizes, and the first
* acceptable size will be accepted and passed to the internal engine & surface.
*
* This is typically NOT NEEDED. The default size selector is already smart enough to respect
* the picture/video output aspect ratio, and be bigger than the surface so that there is no
* upscaling. If all you want is set an aspect ratio, use {@link #setPictureSize(SizeSelector)}
* and {@link #setVideoSize(SizeSelector)}.
*
* When size changes, the {@link CameraView} is remeasured so any WRAP_CONTENT dimension
* is recomputed accordingly.
*
* 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);
}
/** /**
* Set the current session type to either picture or video. * Set the current session type to either picture or video.
* *

@ -20,7 +20,7 @@ This means that your visible preview can be of any size, not just the presets.
Whatever you do, the preview will never be distorted - it can only be cropped Whatever you do, the preview will never be distorted - it can only be cropped
if needed. if needed.
### Examples ## Examples
##### Center Inside ##### Center Inside
@ -51,3 +51,36 @@ of the internal preview surface, the surface will be cropped to fill the view.
This means that part of the preview might be hidden, and the output might contain parts of the scene This means that part of the preview might be hidden, and the output might contain parts of the scene
that were not visible during the capture, **unless it is taken as a snapshot, since snapshots account for cropping**. that were not visible during the capture, **unless it is taken as a snapshot, since snapshots account for cropping**.
## Advanced feature: Preview Size Selection
**Only do this if you know what you are doing. This is typically not needed - prefer picture/video size selectors,
as they will drive the preview size selection and, eventually, the view size. If what you want is just
choose an aspect ratio, do so with [Capture Size](capture-size.html) selection.**
As said, `WRAP_CONTENT` adapts the view boundaries to the preview size. The preview size must be determined
based on the sizes that the device sensor & hardware actually support. This operation is done automatically
by the engine. The default selector will do the following:
- Constraint 1: match the picture/video output aspect ratio (so you get what you see)
- Constraint 2: match sizes a bit bigger than the View (so there is no upscaling)
- Try to match both, or just one, or fallback to the biggest available size
There are not so many reason why you would replace this, other than control the frame processor size
or, indirectly, the snapshot size. You can, however, hook into the process using `setPreviewSize(SizeSelector)`:
```java
cameraView.setPreviewSize(new SizeSelector() {
@Override
public List<Size> select(List<Size> source) {
// Receives a list of available sizes.
// Must return a list of acceptable sizes.
}
});
```
After the preview size is determined, if it has changed since list time, the `CameraView` will receive
another call to `onMeasure` so the `WRAP_CONTENT` magic can take place.
To understand how SizeSelectors work and the available utilities, please read the [Capture Size](capture-size.html) document.

@ -1,7 +1,7 @@
--- ---
layout: page layout: page
title: "v1 Migration Guide" title: "v1 Migration Guide"
subtitle: "Breaking Changes & concepts" subtitle: "Breaking Changes & new concepts"
category: extra category: extra
date: 2018-12-20 19:01:55 date: 2018-12-20 19:01:55
order: 1 order: 1
@ -120,6 +120,21 @@ The GL surface, as an extra benefit, has a much more efficient way of capturing
that avoids OOM errors, rotating the image on the fly, reading EXIF, and other horrible things belonging to v1. that avoids OOM errors, rotating the image on the fly, reading EXIF, and other horrible things belonging to v1.
These picture snapshots will also work while taking videos. These picture snapshots will also work while taking videos.
### Advanced feature: Preview Sizing
We finally introduced a `setPreviewSize()` method which accepts a `SizeSelector`. The use of this method
is discouraged if you don't know exactly what you are doing. The default preview size selector is already
smart enough to
- respect the picture/video aspect ratio
- be a bit bigger than the view so that there is no upscaling
There are not so many reason why you would use this method, other than, for example, control the frame
processor size or, indirectly, the snapshots size. If what you are doing is just assigning an aspect ratio,
for instance, please do so using `setPictureSize()` and `setVideoSize()`.
**Note**: `getPreviewSize()` was removed as it has no useful meaning.
### CameraListener ### CameraListener
The listener interface brings two breaking signature changes: The listener interface brings two breaking signature changes:
@ -143,4 +158,3 @@ Might be used in the future to speed up development.
TODO: opencollective? TODO: opencollective?
TODO: improve the focus marker drawing, move out of XML (accept a drawable?) TODO: improve the focus marker drawing, move out of XML (accept a drawable?)
TODO: do we want getPreviewSize() / setPreviewSize() ? probably not the getter.

@ -27,10 +27,11 @@ addressing most of the common issues and needs, and still leaving you with flexi
### Get started ### Get started
Get started with [install info](about/install.html), [quick setup](about/getting-started.html), or Get started with [install info](about/install.html), [quick setup](about/getting-started.html), or
read the in-depth [documentation](). read the in-depth [documentation](docs/camera-events.html).
### Older versions ### Older versions
This website contains documentation and informations about version 2.X.X of the library. This website contains documentation and informations about version 2.X.X of the library.
For older versions, please take a look at the v1 branch in the [project page](https://github.com/natario1/CameraView). For older versions, please take a look at the v1 branch in the [project page](https://github.com/natario1/CameraView).
For migration guide, take a look at the [migration page](extra/v1-migration-guide.html).

Loading…
Cancel
Save