CameraView is a well documented, high-level library that makes capturing pictures and videos easy,
addressing most of the common issues and needs, and still leaving you with flexibility where needed. See [CHANGELOG](https://github.com/natario1/CameraView/blob/master/CHANGELOG.md).
addressing most of the common issues and needs, and still leaving you with flexibility where needed.
See [CHANGELOG](https://github.com/natario1/CameraView/blob/master/CHANGELOG.md).
```groovy
compile 'com.otaliastudios:cameraview:1.3.2'
@ -30,10 +31,11 @@ See below for a [list of what was done](#roadmap) and [licensing info](#contribu
- Seamless image and video capturing
- **Gestures** support (tap to focus, pinch to zoom and much more)
- System permission handling
- Dynamic sizing behavior
- Create a `CameraView` of **any size**
- Center inside or center crop behaviors
- Automatic output cropping to match your `CameraView` bounds
- Smart sizing behavior
- Preview: Create a `CameraView` of **any size**
- Preview: Center inside or center crop behaviors
- Output: Handy utilities to set the output size
- Output: Automatic cropping to match your `CameraView` preview bounds
- Built-in **grid drawing**
- Multiple capture methods
- Take high-resolution pictures with `capturePicture`
@ -55,9 +57,9 @@ See below for a [list of what was done](#roadmap) and [licensing info](#contribu
@ -78,7 +80,9 @@ To use the CameraView engine, simply add a `CameraView` to your layout:
android:layout_height="wrap_content" />
```
`CameraView` has lots of XML attributes, so keep reading. Make sure you override `onResume`, `onPause` and `onDestroy` in your activity or fragment, and call `CameraView.start()`, `stop()` and `destroy()`.
`CameraView` has lots of XML attributes, so keep reading. Make sure you override `onResume`,
`onPause` and `onDestroy` in your activity or fragment, and call `CameraView.start()`, `stop()`
and `destroy()`.
```java
@Override
@ -102,7 +106,8 @@ protected void onDestroy() {
### Capturing Images
To capture an image just call `CameraView.capturePicture()`. Make sure you setup a `CameraListener` to handle the image callback.
To capture an image just call `CameraView.capturePicture()`. Make sure you setup a `CameraListener`
You can also use `camera.captureSnapshot()` to capture a preview frame. This is faster, though will ensure lower quality output.
You can also use `camera.captureSnapshot()` to capture a preview frame. This is faster, though will
ensure lower quality output.
### Capturing Video
To capture video just call `CameraView.startRecordingVideo(file)` to start, and `CameraView.stopRecordingVideo()` to finish. Make sure you setup a `CameraListener` to handle the video callback.
To capture video just call `CameraView.startRecordingVideo(file)` to start, and
`CameraView.stopRecordingVideo()` to finish. Make sure you setup a `CameraListener` to handle
`CameraView` listen to lots of different gestures inside its bounds. You have the chance to map these gestures to particular actions or camera controls, using `mapGesture()`. This lets you emulate typical behaviors in a single line:
`CameraView` listen to lots of different gestures inside its bounds. You have the chance to map
these gestures to particular actions or camera controls, using `mapGesture()`.
This lets you emulate typical behaviors in a single line:
```java
cameraView.mapGesture(Gesture.PINCH, GestureAction.ZOOM); // Pinch to zoom!
@ -261,19 +272,25 @@ Simple as that. More gestures are coming. There are two things to be noted:
|`SCROLL_VERTICAL` (`cameraGestureScrollVertical`)|Vertical movement gesture.|`zoom` `exposureCorrection``none`|
## Dynamic Sizing Behavior
## Sizing Behavior
`CameraView` has a smart measuring behavior that will let you do what you want with a few flags. Measuring is controlled simply by `layout_width` and `layout_height` attributes, with this meaning:
### Preview Size
`CameraView` has a smart measuring behavior that will let you do what you want with a few flags.
Measuring is controlled simply by `layout_width` and `layout_height` attributes, with this meaning:
- `WRAP_CONTENT` : try to stretch this dimension to respect the preview aspect ratio.
- `MATCH_PARENT` : fill this dimension, even if this means ignoring the aspect ratio.
- Fixed values (e.g. `500dp`) : respect this dimension.
You can have previews of all sizes, not just the supported presets. Whaterever you do, the preview will never be distorted.
You can have previews of all sizes, not just the supported presets. Whaterever you do,
the preview will never be distorted.
### Center inside
#### Center Inside
You can emulate a **center inside** behavior (like the `ImageView` scaletype) by setting both dimensions to `wrap_content`. The camera will get the biggest possible size that fits into your bounds, just like what happens with image views.
You can emulate a **center inside** behavior (like the `ImageView` scaletype) by setting
both dimensions to `wrap_content`. The camera will get the biggest possible size that fits
into your bounds, just like what happens with image views.
```xml
@ -282,11 +299,15 @@ You can emulate a **center inside** behavior (like the `ImageView` scaletype) by
android:layout_height="wrap_content" />
```
This means that the whole preview is visible, and the image output matches what was visible during the capture.
This means that the whole preview is visible, and the image output matches what was visible
during the capture.
### Center crop
#### Center Crop
You can emulate a **center crop** behavior by setting both dimensions to fixed values or to `MATCH_PARENT`. The camera view will fill the rect. If your dimensions don't match the aspect ratio of the internal preview surface, the surface will be cropped to fill the view, just like `android:scaleType="centerCrop"` on an `ImageView`.
You can emulate a **center crop** behavior by setting both dimensions to fixed values or to
`MATCH_PARENT`. The camera view will fill the rect. If your dimensions don't match the aspect ratio
of the internal preview surface, the surface will be cropped to fill the view,
just like `android:scaleType="centerCrop"` on an `ImageView`.
```xml
<com.otaliastudios.cameraview.CameraView
@ -294,7 +315,64 @@ You can emulate a **center crop** behavior by setting both dimensions to fixed v
android:layout_height="match_parent" />
```
This means that part of the preview is hidden, and the image output will contain parts of the scene that were not visible during the capture. If this is a problem, see [cameraCropOutput](#cameracropoutput).
This means that part of the preview is hidden, and the image output will contain parts of the scene
that were not visible during the capture. If this is a problem, see [cameraCropOutput](#cameracropoutput).
### Picture Size
On top of this, you can control the actual size of the output picture, among the list of available sizes.
It is the size of the final JPEG picture. This can be achieved directly through XML, or
using the `SizeSelector` class:
```java
cameraView.setPictureSize(new SizeSelector() {
@Override
public List<Size> select(List<Size> source) {
// Receives a list of available sizes.
// Must return a list of acceptable sizes.
}
});
```
In practice, this is way easier using XML attributes or leveraging the `SizeSelectors` utilities:
SizeSelector ratio = SizeSelectors.aspectRatio(AspectRatio.of(1, 1), 0); // Matches 1:1 sizes.
SizeSelector result = SizeSelectors.or(
SizeSelectors.and(ratio, dimensions), // Try to match both constraints
ratio, // If none is found, at least try to match the aspect ratio
SizeSelectors.biggest() // If none is found, take the biggest
);
camera.setPictureSize(result);
```
## Camera controls
@ -337,10 +415,16 @@ Most camera parameters can be controlled through XML attributes or linked method
What to capture - either picture or video. This has a couple of consequences:
- Sizing: capture and preview size are chosen among the available picture or video sizes, depending on the flag. When `picture`, we choose the max possible picture size and adapt the preview. When `video`, we respect the `videoQuality` choice and adapt the picture and the preview size.
- Picture capturing: due to sizing behavior, capturing pictures in `video` mode might lead to inconsistent results. In this case it is encouraged to use `captureSnapshot` instead, which will capture preview frames. This is fast and thus works well with slower camera sensors.
- Picture capturing: while recording a video, image capturing might work, but it is not guaranteed (it's device dependent)
- Permission behavior: when requesting a `video` session, the record audio permission will be requested. If this is needed, the audio permission should be added to your manifest or the app will crash.
- Sizing: picture and preview size are chosen among the available picture or video sizes,
depending on the flag. The picture size is chosen according to the given [size selector](#picture-size).
When `video`, in addition, we try to match the `videoQuality` aspect ratio.
- Picture capturing: due to sizing behavior, capturing pictures in `video` mode might lead to
inconsistent results. In this case it is encouraged to use `captureSnapshot` instead, which will
capture preview frames. This is fast and thus works well with slower camera sensors.
- Picture capturing: while recording a video, image capturing might work, but it is not guaranteed
(it's device dependent)
- Permission behavior: when requesting a `video` session, the record audio permission will be requested.
If this is needed, the audio permission should be added to your manifest or the app will crash.
Lets you draw grids over the camera preview. Supported values are `off`, `draw3x3` and `draw4x4` for regular grids, and `drawPhi` for a grid based on the golden ratio constant, often used in photography.
Lets you draw grids over the camera preview. Supported values are `off`, `draw3x3` and `draw4x4`
for regular grids, and `drawPhi` for a grid based on the golden ratio constant, often used in photography.
- the Camera1 engine will always play shutter sounds regardless of this flag
@ -501,7 +587,6 @@ Other APIs not mentioned above are provided, and are well documented and comment
|`setZoom(float)`, `getZoom()`|Sets a zoom value, where 0 means camera zoomed out and 1 means zoomed in. No-op if zoom is not supported, or camera not started.|
|`setExposureCorrection(float)`, `getExposureCorrection()`|Sets exposure compensation EV value, in camera stops. No-op if this is not supported. Should be between the bounds returned by CameraOptions.|
|`toggleFacing()`|Toggles the facing value between `Facing.FRONT` and `Facing.BACK`.|
|`toggleFlash()`|Toggles the flash value between `Flash.OFF`, `Flash.ON`, and `Flash.AUTO`.|
|`setLocation(Location)`|Sets location data to be appended to picture/video metadata.|
|`setLocation(double, double)`|Sets latitude and longitude to be appended to picture/video metadata.|
|`getLocation()`|Retrieves location data previously applied with setLocation().|
@ -617,6 +702,7 @@ all the code was changed.
- *Frame processor support*
- *inject external loggers*
- *error handling*
- *capture size selectors*
These are still things that need to be done, off the top of my head: