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 - Multiple capture methods
- Take high-resolution pictures with `capturePicture` - Take high-resolution pictures with `capturePicture`
- Take quick snapshots as a freeze frame of the preview with `captureSnapshot` (similar to Snapchat and Instagram) - 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 - **Metadata** support for pictures and videos
- Automatically detected orientation tags - Automatically detected orientation tags
- Plug in location tags with `setLocation()` API - 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" /> 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 ```java
@Override @Override
@ -291,7 +291,8 @@ Most camera parameters can be controlled through XML attributes or linked method
app:cameraCropOutput="false" app:cameraCropOutput="false"
app:cameraJpegQuality="100" app:cameraJpegQuality="100"
app:cameraVideoQuality="480p" app:cameraVideoQuality="480p"
app:cameraWhiteBalance="auto" /> app:cameraWhiteBalance="auto"
app:cameraHdr="off" />
``` ```
|XML Attribute|Method|Values|Default Value| |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`| |[`cameraJpegQuality`](#camerajpegquality)|`setJpegQuality()`|`0 <= n <= 100`|`100`|
|[`cameraVideoQuality`](#cameravideoquality)|`setVideoQuality()`|`lowest` `highest` `maxQvga` `max480p` `max720p` `max1080p` `max2160p`|`max480p`| |[`cameraVideoQuality`](#cameravideoquality)|`setVideoQuality()`|`lowest` `highest` `maxQvga` `max480p` `max720p` `max1080p` `max2160p`|`max480p`|
|[`cameraWhiteBalance`](#camerawhitebalance)|`setWhiteBalance()`|`auto` `incandescent` `fluorescent` `daylight` `cloudy`|`auto`| |[`cameraWhiteBalance`](#camerawhitebalance)|`setWhiteBalance()`|`auto` `incandescent` `fluorescent` `daylight` `cloudy`|`auto`|
|[`cameraHdr`](#camerahdr)|`setHdr()`|`off` `on`|`off`|
#### cameraSessionType #### cameraSessionType
@ -390,6 +392,15 @@ cameraView.setWhiteBalance(WhiteBalance.DAYLIGHT);
cameraView.setWhiteBalance(WhiteBalance.CLOUDY); cameraView.setWhiteBalance(WhiteBalance.CLOUDY);
``` ```
#### cameraHdr
Turns on or off HDR captures.
```java
cameraView.setHdr(Hdr.OFF);
cameraView.setHdr(Hdr.ON);
```
## Other APIs ## Other APIs
Other APIs not mentioned above are provided, and are well documented and commented in code. 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* - *gesture framework support*
- *scroll gestures support* - *scroll gestures support*
- *MediaActionSound support* - *MediaActionSound support*
- *Hdr controls*
These are still things that need to be done, off the top of my head: 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() { private boolean collectCameraId() {
int internalFacing = mMapper.mapFacing(mFacing); int internalFacing = mMapper.map(mFacing);
Camera.CameraInfo cameraInfo = new Camera.CameraInfo(); Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
for (int i = 0, count = Camera.getNumberOfCameras(); i < count; i++) { for (int i = 0, count = Camera.getNumberOfCameras(); i < count; i++) {
Camera.getCameraInfo(i, cameraInfo); Camera.getCameraInfo(i, cameraInfo);
@ -261,13 +261,34 @@ class Camera1 extends CameraController {
private boolean mergeWhiteBalance(Camera.Parameters params, WhiteBalance oldWhiteBalance) { private boolean mergeWhiteBalance(Camera.Parameters params, WhiteBalance oldWhiteBalance) {
if (mOptions.getSupportedWhiteBalance().contains(mWhiteBalance)) { if (mOptions.getSupportedWhiteBalance().contains(mWhiteBalance)) {
params.setWhiteBalance((String) mMapper.mapWhiteBalance(mWhiteBalance)); params.setWhiteBalance((String) mMapper.map(mWhiteBalance));
return true; return true;
} }
mWhiteBalance = oldWhiteBalance; mWhiteBalance = oldWhiteBalance;
return false; 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 @Override
void setFlash(Flash flash) { void setFlash(Flash flash) {
Flash old = mFlash; Flash old = mFlash;
@ -283,7 +304,7 @@ class Camera1 extends CameraController {
private boolean mergeFlash(Camera.Parameters params, Flash oldFlash) { private boolean mergeFlash(Camera.Parameters params, Flash oldFlash) {
if (mOptions.getSupportedFlash().contains(mFlash)) { if (mOptions.getSupportedFlash().contains(mFlash)) {
params.setFlashMode((String) mMapper.mapFlash(mFlash)); params.setFlashMode((String) mMapper.map(mFlash));
return true; return true;
} }
mFlash = oldFlash; mFlash = oldFlash;

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

@ -17,6 +17,7 @@ abstract class CameraController implements Preview.SurfaceCallback {
protected WhiteBalance mWhiteBalance; protected WhiteBalance mWhiteBalance;
protected VideoQuality mVideoQuality; protected VideoQuality mVideoQuality;
protected SessionType mSessionType; protected SessionType mSessionType;
protected Hdr mHdr;
CameraController(CameraView.CameraCallbacks callback, Preview preview) { CameraController(CameraView.CameraCallbacks callback, Preview preview) {
mCameraCallbacks = callback; mCameraCallbacks = callback;
@ -37,6 +38,7 @@ abstract class CameraController implements Preview.SurfaceCallback {
abstract void setWhiteBalance(WhiteBalance whiteBalance); abstract void setWhiteBalance(WhiteBalance whiteBalance);
abstract void setVideoQuality(VideoQuality videoQuality); abstract void setVideoQuality(VideoQuality videoQuality);
abstract void setSessionType(SessionType sessionType); abstract void setSessionType(SessionType sessionType);
abstract void setHdr(Hdr hdr);
abstract void setLocation(Location location); abstract void setLocation(Location location);
abstract boolean capturePicture(); abstract boolean capturePicture();
@ -59,4 +61,5 @@ abstract class CameraController implements Preview.SurfaceCallback {
final WhiteBalance getWhiteBalance() { return mWhiteBalance; } final WhiteBalance getWhiteBalance() { return mWhiteBalance; }
final VideoQuality getVideoQuality() { return mVideoQuality; } final VideoQuality getVideoQuality() { return mVideoQuality; }
final SessionType getSessionType() { return mSessionType; } 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.hardware.camera2.CameraCharacteristics;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
@ -18,6 +19,7 @@ public class CameraOptions {
private Set<WhiteBalance> supportedWhiteBalance = new HashSet<>(5); private Set<WhiteBalance> supportedWhiteBalance = new HashSet<>(5);
private Set<Facing> supportedFacing = new HashSet<>(2); private Set<Facing> supportedFacing = new HashSet<>(2);
private Set<Flash> supportedFlash = new HashSet<>(4); private Set<Flash> supportedFlash = new HashSet<>(4);
private Set<Hdr> supportedHdr = new HashSet<>(2);
private boolean zoomSupported; private boolean zoomSupported;
private boolean videoSnapshotSupported; 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(); zoomSupported = params.isZoomSupported();
videoSnapshotSupported = params.isVideoSnapshotSupported(); videoSnapshotSupported = params.isVideoSnapshotSupported();
autoFocusSupported = params.getSupportedFocusModes().contains(Camera.Parameters.FOCUS_MODE_AUTO); autoFocusSupported = params.getSupportedFocusModes().contains(Camera.Parameters.FOCUS_MODE_AUTO);
@ -86,7 +97,7 @@ public class CameraOptions {
*/ */
@NonNull @NonNull
public Set<Facing> getSupportedFacing() { public Set<Facing> getSupportedFacing() {
return supportedFacing; return Collections.unmodifiableSet(supportedFacing);
} }
@ -101,7 +112,7 @@ public class CameraOptions {
*/ */
@NonNull @NonNull
public Set<Flash> getSupportedFlash() { public Set<Flash> getSupportedFlash() {
return supportedFlash; return Collections.unmodifiableSet(supportedFlash);
} }
@ -117,10 +128,22 @@ public class CameraOptions {
*/ */
@NonNull @NonNull
public Set<WhiteBalance> getSupportedWhiteBalance() { 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 * Whether zoom is supported. If this is false, pinch-to-zoom
* will not work and {@link CameraView#setZoom(float)} will have no effect. * 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 * Set location coordinates to be found later in the jpeg EXIF header
* *

@ -1,23 +1,27 @@
package com.otaliastudios.cameraview; package com.otaliastudios.cameraview;
import android.hardware.Camera; import android.hardware.Camera;
import android.os.Build;
import java.util.HashMap; import java.util.HashMap;
abstract class Mapper { abstract class Mapper {
abstract <T> T mapFlash(Flash internalConstant); abstract <T> T map(Flash flash);
abstract <T> T mapFacing(Facing internalConstant); abstract <T> T map(Facing facing);
abstract <T> T mapWhiteBalance(WhiteBalance internalConstant); abstract <T> T map(WhiteBalance whiteBalance);
abstract <T> T map(Hdr hdr);
abstract <T> Flash unmapFlash(T cameraConstant); abstract <T> Flash unmapFlash(T cameraConstant);
abstract <T> Facing unmapFacing(T cameraConstant); abstract <T> Facing unmapFacing(T cameraConstant);
abstract <T> WhiteBalance unmapWhiteBalance(T cameraConstant); abstract <T> WhiteBalance unmapWhiteBalance(T cameraConstant);
abstract <T> Hdr unmapHdr(T cameraConstant);
static class Mapper1 extends Mapper { static class Mapper1 extends Mapper {
private static final HashMap<Flash, String> FLASH = new HashMap<>(); private static final HashMap<Flash, String> FLASH = new HashMap<>();
private static final HashMap<WhiteBalance, String> WB = new HashMap<>(); private static final HashMap<WhiteBalance, String> WB = new HashMap<>();
private static final HashMap<Facing, Integer> FACING = new HashMap<>(); private static final HashMap<Facing, Integer> FACING = new HashMap<>();
private static final HashMap<Hdr, String> HDR = new HashMap<>();
static { static {
FLASH.put(Flash.OFF, Camera.Parameters.FLASH_MODE_OFF); 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.FLUORESCENT, Camera.Parameters.WHITE_BALANCE_FLUORESCENT);
WB.put(WhiteBalance.DAYLIGHT, Camera.Parameters.WHITE_BALANCE_DAYLIGHT); WB.put(WhiteBalance.DAYLIGHT, Camera.Parameters.WHITE_BALANCE_DAYLIGHT);
WB.put(WhiteBalance.CLOUDY, Camera.Parameters.WHITE_BALANCE_CLOUDY_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 @Override
<T> T mapFlash(Flash internalConstant) { <T> T map(Facing facing) {
return (T) FLASH.get(internalConstant); return (T) FACING.get(facing);
} }
@Override @Override
<T> T mapFacing(Facing internalConstant) { <T> T map(WhiteBalance whiteBalance) {
return (T) FACING.get(internalConstant); return (T) WB.get(whiteBalance);
} }
@Override @Override
<T> T mapWhiteBalance(WhiteBalance internalConstant) { <T> T map(Hdr hdr) {
return (T) WB.get(internalConstant); return (T) HDR.get(hdr);
} }
private <T> T reverseLookup(HashMap<T, ?> map, Object object) { private <T> T reverseLookup(HashMap<T, ?> map, Object object) {
@ -71,17 +86,22 @@ abstract class Mapper {
<T> WhiteBalance unmapWhiteBalance(T cameraConstant) { <T> WhiteBalance unmapWhiteBalance(T cameraConstant) {
return reverseLookup(WB, cameraConstant); return reverseLookup(WB, cameraConstant);
} }
@Override
<T> Hdr unmapHdr(T cameraConstant) {
return reverseLookup(HDR, cameraConstant);
}
} }
static class Mapper2 extends Mapper { static class Mapper2 extends Mapper {
@Override @Override
<T> T mapWhiteBalance(WhiteBalance internalConstant) { <T> T map(WhiteBalance whiteBalance) {
return null; return null;
} }
@Override @Override
<T> T mapFlash(Flash internalConstant) { <T> T map(Flash flash) {
return null; return null;
} }
@ -96,7 +116,7 @@ abstract class Mapper {
} }
@Override @Override
<T> T mapFacing(Facing internalConstant) { <T> T map(Facing facing) {
return null; return null;
} }
@ -104,6 +124,16 @@ abstract class Mapper {
<T> Facing unmapFacing(T cameraConstant) { <T> Facing unmapFacing(T cameraConstant) {
return null; 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" /> <enum name="front" value="1" />
</attr> </attr>
<attr name="cameraHdr" format="enum">
<enum name="off" value="0" />
<enum name="on" value="1" />
</attr>
<attr name="cameraFlash" format="enum"> <attr name="cameraFlash" format="enum">
<enum name="off" value="0" /> <enum name="off" value="0" />
<enum name="on" value="1" /> <enum name="on" value="1" />

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

Loading…
Cancel
Save