HDR support (#11)

pull/13/head
Mattia Iavarone 7 years ago committed by GitHub
parent 4e5c772902
commit cbac776f91
  1. 18
      README.md
  2. 27
      cameraview/src/main/java/com/otaliastudios/cameraview/Camera1.java
  3. 8
      cameraview/src/main/java/com/otaliastudios/cameraview/Camera2.java
  4. 3
      cameraview/src/main/java/com/otaliastudios/cameraview/CameraController.java
  5. 29
      cameraview/src/main/java/com/otaliastudios/cameraview/CameraOptions.java
  6. 22
      cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java
  7. 54
      cameraview/src/main/java/com/otaliastudios/cameraview/Mapper.java
  8. 42
      cameraview/src/main/options/com/otaliastudios/cameraview/Hdr.java
  9. 5
      cameraview/src/main/res/values/attrs.xml
  10. 2
      cameraview/src/main/utils/com/otaliastudios/cameraview/CameraUtils.java

@ -30,7 +30,7 @@ compile 'com.otaliastudios:cameraview:1.1.4'
- Multiple capture methods
- Take high-resolution pictures with `capturePicture`
- Take quick snapshots as a freeze frame of the preview with `captureSnapshot` (similar to Snapchat and Instagram)
- Control flash, zoom, white balance, exposure correction and more
- Control HDR, flash, zoom, white balance, exposure correction and more
- **Metadata** support for pictures and videos
- Automatically detected orientation tags
- Plug in location tags with `setLocation()` API
@ -66,7 +66,7 @@ To use the CameraView engine, simply add a `CameraView` to your layout:
android:layout_height="wrap_content" />
```
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
@ -291,7 +291,8 @@ Most camera parameters can be controlled through XML attributes or linked method
app:cameraCropOutput="false"
app:cameraJpegQuality="100"
app:cameraVideoQuality="480p"
app:cameraWhiteBalance="auto" />
app:cameraWhiteBalance="auto"
app:cameraHdr="off" />
```
|XML Attribute|Method|Values|Default Value|
@ -304,6 +305,7 @@ Most camera parameters can be controlled through XML attributes or linked method
|[`cameraJpegQuality`](#camerajpegquality)|`setJpegQuality()`|`0 <= n <= 100`|`100`|
|[`cameraVideoQuality`](#cameravideoquality)|`setVideoQuality()`|`lowest` `highest` `maxQvga` `max480p` `max720p` `max1080p` `max2160p`|`max480p`|
|[`cameraWhiteBalance`](#camerawhitebalance)|`setWhiteBalance()`|`auto` `incandescent` `fluorescent` `daylight` `cloudy`|`auto`|
|[`cameraHdr`](#camerahdr)|`setHdr()`|`off` `on`|`off`|
#### cameraSessionType
@ -390,6 +392,15 @@ cameraView.setWhiteBalance(WhiteBalance.DAYLIGHT);
cameraView.setWhiteBalance(WhiteBalance.CLOUDY);
```
#### cameraHdr
Turns on or off HDR captures.
```java
cameraView.setHdr(Hdr.OFF);
cameraView.setHdr(Hdr.ON);
```
## Other APIs
Other APIs not mentioned above are provided, and are well documented and commented in code.
@ -465,6 +476,7 @@ This is what was done since the library was forked. I have kept the original str
- *gesture framework support*
- *scroll gestures support*
- *MediaActionSound support*
- *Hdr controls*
These are still things that need to be done, off the top of my head:

@ -174,7 +174,7 @@ class Camera1 extends CameraController {
}
private boolean collectCameraId() {
int internalFacing = mMapper.mapFacing(mFacing);
int internalFacing = mMapper.map(mFacing);
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
for (int i = 0, count = Camera.getNumberOfCameras(); i < count; i++) {
Camera.getCameraInfo(i, cameraInfo);
@ -261,13 +261,34 @@ class Camera1 extends CameraController {
private boolean mergeWhiteBalance(Camera.Parameters params, WhiteBalance oldWhiteBalance) {
if (mOptions.getSupportedWhiteBalance().contains(mWhiteBalance)) {
params.setWhiteBalance((String) mMapper.mapWhiteBalance(mWhiteBalance));
params.setWhiteBalance((String) mMapper.map(mWhiteBalance));
return true;
}
mWhiteBalance = oldWhiteBalance;
return false;
}
@Override
void setHdr(Hdr hdr) {
Hdr old = mHdr;
mHdr = hdr;
if (isCameraOpened()) {
synchronized (mLock) {
Camera.Parameters params = mCamera.getParameters();
if (mergeHdr(params, old)) mCamera.setParameters(params);
}
}
}
private boolean mergeHdr(Camera.Parameters params, Hdr oldHdr) {
if (mOptions.getSupportedHdr().contains(mHdr)) {
params.setSceneMode((String) mMapper.map(mHdr));
return true;
}
mHdr = oldHdr;
return false;
}
@Override
void setFlash(Flash flash) {
Flash old = mFlash;
@ -283,7 +304,7 @@ class Camera1 extends CameraController {
private boolean mergeFlash(Camera.Parameters params, Flash oldFlash) {
if (mOptions.getSupportedFlash().contains(mFlash)) {
params.setFlashMode((String) mMapper.mapFlash(mFlash));
params.setFlashMode((String) mMapper.map(mFlash));
return true;
}
mFlash = oldFlash;

@ -101,7 +101,7 @@ class Camera2 extends CameraController {
@Override
void setFacing(Facing facing) {
int internalFacing = mMapper.mapFacing(facing);
int internalFacing = mMapper.map(facing);
final String[] ids;
try {
ids = mCameraManager.getCameraIdList();
@ -139,7 +139,6 @@ class Camera2 extends CameraController {
@Override
void setFlash(Flash flash) {
}
@Override
@ -147,6 +146,11 @@ class Camera2 extends CameraController {
}
@Override
void setHdr(Hdr hdr) {
}
@Override
void setLocation(Location location) {

@ -17,6 +17,7 @@ abstract class CameraController implements Preview.SurfaceCallback {
protected WhiteBalance mWhiteBalance;
protected VideoQuality mVideoQuality;
protected SessionType mSessionType;
protected Hdr mHdr;
CameraController(CameraView.CameraCallbacks callback, Preview preview) {
mCameraCallbacks = callback;
@ -37,6 +38,7 @@ abstract class CameraController implements Preview.SurfaceCallback {
abstract void setWhiteBalance(WhiteBalance whiteBalance);
abstract void setVideoQuality(VideoQuality videoQuality);
abstract void setSessionType(SessionType sessionType);
abstract void setHdr(Hdr hdr);
abstract void setLocation(Location location);
abstract boolean capturePicture();
@ -59,4 +61,5 @@ abstract class CameraController implements Preview.SurfaceCallback {
final WhiteBalance getWhiteBalance() { return mWhiteBalance; }
final VideoQuality getVideoQuality() { return mVideoQuality; }
final SessionType getSessionType() { return mSessionType; }
final Hdr getHdr() { return mHdr; }
}

@ -6,6 +6,7 @@ import android.hardware.Camera;
import android.hardware.camera2.CameraCharacteristics;
import android.support.annotation.NonNull;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@ -18,6 +19,7 @@ public class CameraOptions {
private Set<WhiteBalance> supportedWhiteBalance = new HashSet<>(5);
private Set<Facing> supportedFacing = new HashSet<>(2);
private Set<Flash> supportedFlash = new HashSet<>(4);
private Set<Hdr> supportedHdr = new HashSet<>(2);
private boolean zoomSupported;
private boolean videoSnapshotSupported;
@ -59,6 +61,15 @@ public class CameraOptions {
}
}
// Hdr
strings = params.getSupportedSceneModes();
if (strings != null) {
for (String string : strings) {
Hdr value = mapper.unmapHdr(string);
if (value != null) supportedHdr.add(value);
}
}
zoomSupported = params.isZoomSupported();
videoSnapshotSupported = params.isVideoSnapshotSupported();
autoFocusSupported = params.getSupportedFocusModes().contains(Camera.Parameters.FOCUS_MODE_AUTO);
@ -86,7 +97,7 @@ public class CameraOptions {
*/
@NonNull
public Set<Facing> getSupportedFacing() {
return supportedFacing;
return Collections.unmodifiableSet(supportedFacing);
}
@ -101,7 +112,7 @@ public class CameraOptions {
*/
@NonNull
public Set<Flash> getSupportedFlash() {
return supportedFlash;
return Collections.unmodifiableSet(supportedFlash);
}
@ -117,10 +128,22 @@ public class CameraOptions {
*/
@NonNull
public Set<WhiteBalance> getSupportedWhiteBalance() {
return supportedWhiteBalance;
return Collections.unmodifiableSet(supportedWhiteBalance);
}
/**
* Set of supported hdr values.
*
* @see Hdr#OFF
* @see Hdr#ON
* @return a set of supported values.
*/
@NonNull
public Set<Hdr> getSupportedHdr() {
return Collections.unmodifiableSet(supportedHdr);
}
/**
* Whether zoom is supported. If this is false, pinch-to-zoom
* will not work and {@link CameraView#setZoom(float)} will have no effect.

@ -706,6 +706,28 @@ public class CameraView extends FrameLayout {
}
/**
* Controls the grids to be drawn over the current layout.
*
* @see Hdr#OFF
* @see Hdr#ON
*
* @param hdr desired hdr value
*/
public void setHdr(Hdr hdr) {
mCameraController.setHdr(hdr);
}
/**
* Gets the current hdr value.
* @return the current hdr value
*/
public Hdr getHdr() {
return mCameraController.getHdr();
}
/**
* Set location coordinates to be found later in the jpeg EXIF header
*

@ -1,23 +1,27 @@
package com.otaliastudios.cameraview;
import android.hardware.Camera;
import android.os.Build;
import java.util.HashMap;
abstract class Mapper {
abstract <T> T mapFlash(Flash internalConstant);
abstract <T> T mapFacing(Facing internalConstant);
abstract <T> T mapWhiteBalance(WhiteBalance internalConstant);
abstract <T> T map(Flash flash);
abstract <T> T map(Facing facing);
abstract <T> T map(WhiteBalance whiteBalance);
abstract <T> T map(Hdr hdr);
abstract <T> Flash unmapFlash(T cameraConstant);
abstract <T> Facing unmapFacing(T cameraConstant);
abstract <T> WhiteBalance unmapWhiteBalance(T cameraConstant);
abstract <T> Hdr unmapHdr(T cameraConstant);
static class Mapper1 extends Mapper {
private static final HashMap<Flash, String> FLASH = new HashMap<>();
private static final HashMap<WhiteBalance, String> WB = new HashMap<>();
private static final HashMap<Facing, Integer> FACING = new HashMap<>();
private static final HashMap<Hdr, String> HDR = new HashMap<>();
static {
FLASH.put(Flash.OFF, Camera.Parameters.FLASH_MODE_OFF);
@ -31,21 +35,32 @@ abstract class Mapper {
WB.put(WhiteBalance.FLUORESCENT, Camera.Parameters.WHITE_BALANCE_FLUORESCENT);
WB.put(WhiteBalance.DAYLIGHT, Camera.Parameters.WHITE_BALANCE_DAYLIGHT);
WB.put(WhiteBalance.CLOUDY, Camera.Parameters.WHITE_BALANCE_CLOUDY_DAYLIGHT);
HDR.put(Hdr.OFF, Camera.Parameters.SCENE_MODE_AUTO);
if (Build.VERSION.SDK_INT >= 17) {
HDR.put(Hdr.ON, Camera.Parameters.SCENE_MODE_HDR);
} else {
HDR.put(Hdr.ON, "hdr");
}
}
@Override
<T> T map(Flash flash) {
return (T) FLASH.get(flash);
}
@Override
<T> T mapFlash(Flash internalConstant) {
return (T) FLASH.get(internalConstant);
<T> T map(Facing facing) {
return (T) FACING.get(facing);
}
@Override
<T> T mapFacing(Facing internalConstant) {
return (T) FACING.get(internalConstant);
<T> T map(WhiteBalance whiteBalance) {
return (T) WB.get(whiteBalance);
}
@Override
<T> T mapWhiteBalance(WhiteBalance internalConstant) {
return (T) WB.get(internalConstant);
<T> T map(Hdr hdr) {
return (T) HDR.get(hdr);
}
private <T> T reverseLookup(HashMap<T, ?> map, Object object) {
@ -71,17 +86,22 @@ abstract class Mapper {
<T> WhiteBalance unmapWhiteBalance(T cameraConstant) {
return reverseLookup(WB, cameraConstant);
}
@Override
<T> Hdr unmapHdr(T cameraConstant) {
return reverseLookup(HDR, cameraConstant);
}
}
static class Mapper2 extends Mapper {
@Override
<T> T mapWhiteBalance(WhiteBalance internalConstant) {
<T> T map(WhiteBalance whiteBalance) {
return null;
}
@Override
<T> T mapFlash(Flash internalConstant) {
<T> T map(Flash flash) {
return null;
}
@ -96,7 +116,7 @@ abstract class Mapper {
}
@Override
<T> T mapFacing(Facing internalConstant) {
<T> T map(Facing facing) {
return null;
}
@ -104,6 +124,16 @@ abstract class Mapper {
<T> Facing unmapFacing(T cameraConstant) {
return null;
}
@Override
<T> T map(Hdr hdr) {
return null;
}
@Override
<T> Hdr unmapHdr(T cameraConstant) {
return null;
}
}
}

@ -0,0 +1,42 @@
package com.otaliastudios.cameraview;
/**
* Hdr values indicate whether to use high dynamic range techniques when capturing pictures.
*
* @see CameraView#setHdr(Hdr)
*/
public enum Hdr {
/**
* No HDR.
*/
OFF(0),
/**
* Using HDR.
*/
ON(1);
final static Hdr DEFAULT = OFF;
private int value;
Hdr(int value) {
this.value = value;
}
int value() {
return value;
}
static Hdr fromValue(int value) {
Hdr[] list = Hdr.values();
for (Hdr action : list) {
if (action.value() == value) {
return action;
}
}
return null;
}
}

@ -45,6 +45,11 @@
<enum name="front" value="1" />
</attr>
<attr name="cameraHdr" format="enum">
<enum name="off" value="0" />
<enum name="on" value="1" />
</attr>
<attr name="cameraFlash" format="enum">
<enum name="off" value="0" />
<enum name="on" value="1" />

@ -44,7 +44,7 @@ public class CameraUtils {
* @return true if such sensor exists
*/
public static boolean hasCameraFacing(Context context, Facing facing) {
int internal = new Mapper.Mapper1().mapFacing(facing);
int internal = new Mapper.Mapper1().map(facing);
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
for (int i = 0, count = Camera.getNumberOfCameras(); i < count; i++) {
Camera.getCameraInfo(i, cameraInfo);

Loading…
Cancel
Save