White Balance support

pull/1/head
Mattia Iavarone 7 years ago
parent f43af464f9
commit 4c021caa8f
  1. 18
      README.md
  2. 59
      camerakit/src/main/api16/com/flurgle/camerakit/Camera1.java
  3. 100
      camerakit/src/main/api16/com/flurgle/camerakit/ConstantMapper.java
  4. 20
      camerakit/src/main/api21/com/flurgle/camerakit/Camera2.java
  5. 3
      camerakit/src/main/base/com/flurgle/camerakit/CameraImpl.java
  6. 14
      camerakit/src/main/base/com/flurgle/camerakit/CameraProperties.java
  7. 7
      camerakit/src/main/java/com/flurgle/camerakit/CameraKit.java
  8. 29
      camerakit/src/main/java/com/flurgle/camerakit/CameraView.java
  9. 8
      camerakit/src/main/res/values/attrs.xml

@ -21,6 +21,7 @@ CameraKit is an easy to use utility to work with the Android Camera APIs. Everyt
- [cameraZoomMode](#camerazoommode)
- [cameraCropOutput](#cameracropoutput)
- [cameraJpegQuality](#camerajpegquality)
- [cameraWhiteBalance](#camerawhitebalance)
- [Permissions Behavior](#permissions-behavior)
- [Dynamic Sizing Behavior](#dynamic-sizing-behavior)
- [Center Crop](#center-crop)
@ -38,6 +39,9 @@ CameraKit is an easy to use utility to work with the Android Camera APIs. Everyt
- `CAPTURE_METHOD_STANDARD`: an image captured normally using the camera APIs.
- `CAPTURE_METHOD_FRAME`: a freeze frame of the `CameraView` preview (similar to SnapChat and Instagram) for devices with slower cameras
- Built-in tap to focus
- EXIF support
- Automatically detected orientation tag
- Plug in location tags with `CameraView.setLocation(double, double)`
- TODO: Built-in pinch to zoom
## Setup
@ -157,6 +161,7 @@ camera.setCameraListener(new CameraListener() {
app:cameraCropOutput="true"
app:cameraJpegQuality="100"
app:cameraVideoQuality="480p"
app:cameraWhiteBalance="auto"
android:adjustViewBounds="true" />
```
@ -171,6 +176,7 @@ camera.setCameraListener(new CameraListener() {
|[`cameraCropOutput`](#cameracropoutput)|`setCropOutput()`|`true` `false`|`false`|
|[`cameraJpegQuality`](#camerajpegquality)|`setJpegQuality()`|`0 <= n <= 100`|`100`|
|[`cameraVideoQuality`](#cameravideoquality)|`setVideoQuality()`|`max480p` `max720p` `max1080p` `max2160p` `highest` `lowest`|`max480p`|
|[`cameraWhiteBalance`](#camerawhitebalance)|`setWhiteBalance()`|`auto` `incandescent` `fluorescent` `daylight` `cloudy`|`auto`|
### cameraFacing
@ -261,6 +267,18 @@ cameraView.setVideoQuality(CameraKit.Constants.VIDEO_QUALITY_HIGHEST);
cameraView.setVideoQuality(CameraKit.Constants.VIDEO_QUALITY_QVGA);
```
### cameraWhiteBalance
Sets the desired white balance for the current session.
```java
cameraView.setWhiteBalance(CameraKit.Constants.WHITE_BALANCE_AUTO);
cameraView.setWhiteBalance(CameraKit.Constants.WHITE_BALANCE_INCANDESCENT);
cameraView.setWhiteBalance(CameraKit.Constants.WHITE_BALANCE_FLUORESCENT);
cameraView.setWhiteBalance(CameraKit.Constants.WHITE_BALANCE_DAYLIGHT);
cameraView.setWhiteBalance(CameraKit.Constants.WHITE_BALANCE_CLOUDY);
```
## Permissions behavior
`CameraView` needs two permissions:

@ -18,12 +18,12 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static com.flurgle.camerakit.CameraKit.Constants.FLASH_OFF;
import static com.flurgle.camerakit.CameraKit.Constants.FOCUS_CONTINUOUS;
import static com.flurgle.camerakit.CameraKit.Constants.FOCUS_OFF;
import static com.flurgle.camerakit.CameraKit.Constants.FOCUS_TAP;
import static com.flurgle.camerakit.CameraKit.Constants.CAPTURE_METHOD_STANDARD;
import static com.flurgle.camerakit.CameraKit.Constants.CAPTURE_METHOD_FRAME;
import static com.flurgle.camerakit.CameraKit.Constants.FOCUS_TAP_WITH_MARKER;
@SuppressWarnings("deprecation")
class Camera1 extends CameraImpl {
@ -37,7 +37,7 @@ class Camera1 extends CameraImpl {
private int mCameraId;
private Camera mCamera;
private Camera.Parameters mCameraParameters;
private CameraProperties mCameraProperties;
private ExtraProperties mExtraProperties;
private Camera.CameraInfo mCameraInfo;
private Size mPreviewSize;
private Size mCaptureSize;
@ -56,10 +56,12 @@ class Camera1 extends CameraImpl {
@Method private int mMethod;
@ZoomMode private int mZoom;
@VideoQuality private int mVideoQuality;
@WhiteBalance private int mWhiteBalance;
private double mLatitude;
private double mLongitude;
private Handler mHandler = new Handler();
private ConstantMapper.MapperImpl mMapper = new ConstantMapper.Mapper1();
Camera1(CameraListener callback, PreviewImpl preview) {
super(callback, preview);
@ -136,11 +138,7 @@ class Camera1 extends CameraImpl {
@Override
void setFacing(@Facing int facing) {
int internalFacing = new ConstantMapper.Facing(facing).map();
if (internalFacing == -1) {
return;
}
int internalFacing = mMapper.mapFacing(facing);
for (int i = 0, count = Camera.getNumberOfCameras(); i < count; i++) {
Camera.getCameraInfo(i, mCameraInfo);
if (mCameraInfo.facing == internalFacing) {
@ -158,30 +156,42 @@ class Camera1 extends CameraImpl {
}
@Override
void setFlash(@Flash int flash) {
void setWhiteBalance(@WhiteBalance int whiteBalance) {
int old = mWhiteBalance;
mWhiteBalance = whiteBalance;
if (mCameraParameters != null) {
List<String> flashes = mCameraParameters.getSupportedFlashModes();
String internalFlash = new ConstantMapper.Flash(flash).map();
if (flashes != null && flashes.contains(internalFlash)) {
mCameraParameters.setFlashMode(internalFlash);
mFlash = flash;
List<String> supported = mCameraParameters.getSupportedWhiteBalance();
String internal = mMapper.mapWhiteBalance(whiteBalance);
if (supported != null && supported.contains(internal)) {
mCameraParameters.setWhiteBalance(internal);
mCamera.setParameters(mCameraParameters);
} else {
String currentFlash = new ConstantMapper.Flash(mFlash).map();
if (flashes == null || !flashes.contains(currentFlash)) {
mCameraParameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
mFlash = FLASH_OFF;
mWhiteBalance = old;
}
}
}
@Override
void setFlash(@Flash int flash) {
int old = mFlash;
mFlash = flash;
if (mCameraParameters != null) {
List<String> flashes = mCameraParameters.getSupportedFlashModes();
String internalFlash = mMapper.mapFlash(flash);
if (flashes != null && flashes.contains(internalFlash)) {
mCameraParameters.setFlashMode(internalFlash);
mCamera.setParameters(mCameraParameters);
} else {
mFlash = flash;
mFlash = old;
}
}
}
@Override
void setFocus(@Focus int focus) {
this.mFocus = focus;
int old = mFocus;
mFocus = focus;
switch (focus) {
case FOCUS_CONTINUOUS:
if (mCameraParameters != null) {
@ -190,17 +200,20 @@ class Camera1 extends CameraImpl {
if (modes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
mCameraParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
} else {
setFocus(FOCUS_OFF);
mFocus = old;
}
}
break;
case FOCUS_TAP:
case FOCUS_TAP_WITH_MARKER:
if (mCameraParameters != null) {
attachFocusTapListener();
final List<String> modes = mCameraParameters.getSupportedFocusModes();
if (modes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
mCameraParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
} else {
mFocus = old;
}
}
break;
@ -318,8 +331,8 @@ class Camera1 extends CameraImpl {
@Nullable
@Override
CameraProperties getCameraProperties() {
return mCameraProperties;
ExtraProperties getExtraProperties() {
return mExtraProperties;
}
// Internal:
@ -424,7 +437,7 @@ class Camera1 extends CameraImpl {
}
private void collectCameraProperties() {
mCameraProperties = new CameraProperties(mCameraParameters.getVerticalViewAngle(),
mExtraProperties = new ExtraProperties(mCameraParameters.getVerticalViewAngle(),
mCameraParameters.getHorizontalViewAngle());
}

@ -6,96 +6,70 @@ import android.hardware.camera2.CameraCharacteristics;
import android.support.v4.util.SparseArrayCompat;
import android.util.SparseIntArray;
public class ConstantMapper {
private abstract static class BaseMapper<T> {
import java.util.Map;
protected int mCameraKitConstant;
public class ConstantMapper {
protected BaseMapper(int cameraKitConstant) {
this.mCameraKitConstant = cameraKitConstant;
}
static abstract class MapperImpl {
abstract T map();
MapperImpl() {}
abstract <T> T mapFlash(@Flash int internalConstant);
abstract <T> T mapFacing(@Facing int internalConstant);
abstract <T> T mapWhiteBalance(@WhiteBalance int internalConstant);
}
static class Flash extends BaseMapper<String> {
private static final SparseArrayCompat<String> FLASH_MODES = new SparseArrayCompat<>();
static class Mapper1 extends MapperImpl {
private static final SparseArrayCompat<String> FLASH = new SparseArrayCompat<>();
private static final SparseArrayCompat<String> WB = new SparseArrayCompat<>();
private static final SparseArrayCompat<Integer> FACING = new SparseArrayCompat<>();
static {
FLASH_MODES.put(CameraKit.Constants.FLASH_OFF, Camera.Parameters.FLASH_MODE_OFF);
FLASH_MODES.put(CameraKit.Constants.FLASH_ON, Camera.Parameters.FLASH_MODE_ON);
FLASH_MODES.put(CameraKit.Constants.FLASH_AUTO, Camera.Parameters.FLASH_MODE_AUTO);
FLASH_MODES.put(CameraKit.Constants.FLASH_TORCH, Camera.Parameters.FLASH_MODE_TORCH);
}
protected Flash(int cameraKitConstant) {
super(cameraKitConstant);
FLASH.put(CameraKit.Constants.FLASH_OFF, Camera.Parameters.FLASH_MODE_OFF);
FLASH.put(CameraKit.Constants.FLASH_ON, Camera.Parameters.FLASH_MODE_ON);
FLASH.put(CameraKit.Constants.FLASH_AUTO, Camera.Parameters.FLASH_MODE_AUTO);
FLASH.put(CameraKit.Constants.FLASH_TORCH, Camera.Parameters.FLASH_MODE_TORCH);
FACING.put(CameraKit.Constants.FACING_BACK, Camera.CameraInfo.CAMERA_FACING_BACK);
FACING.put(CameraKit.Constants.FACING_FRONT, Camera.CameraInfo.CAMERA_FACING_FRONT);
WB.put(CameraKit.Constants.WHITE_BALANCE_AUTO, Camera.Parameters.WHITE_BALANCE_AUTO);
WB.put(CameraKit.Constants.WHITE_BALANCE_INCANDESCENT, Camera.Parameters.WHITE_BALANCE_INCANDESCENT);
WB.put(CameraKit.Constants.WHITE_BALANCE_FLUORESCENT, Camera.Parameters.WHITE_BALANCE_FLUORESCENT);
WB.put(CameraKit.Constants.WHITE_BALANCE_DAYLIGHT, Camera.Parameters.WHITE_BALANCE_DAYLIGHT);
WB.put(CameraKit.Constants.WHITE_BALANCE_CLOUDY, Camera.Parameters.WHITE_BALANCE_CLOUDY_DAYLIGHT);
}
@Override
String map() {
return FLASH_MODES.get(mCameraKitConstant, FLASH_MODES.get(CameraKit.Constants.FLASH_OFF));
}
}
@TargetApi(21)
static class Flash2 extends BaseMapper<String> {
protected Flash2(int cameraKitConstant) {
super(cameraKitConstant);
<T> T mapFlash(int internalConstant) {
return (T) FLASH.get(internalConstant, null);
}
@Override
String map() {
return null;
}
}
static class Facing extends BaseMapper<Integer> {
private static final SparseArrayCompat<Integer> FACING_MODES = new SparseArrayCompat<>();
static {
FACING_MODES.put(CameraKit.Constants.FACING_BACK, Camera.CameraInfo.CAMERA_FACING_BACK);
FACING_MODES.put(CameraKit.Constants.FACING_FRONT, Camera.CameraInfo.CAMERA_FACING_FRONT);
}
protected Facing(int cameraKitConstant) {
super(cameraKitConstant);
<T> T mapFacing(int internalConstant) {
return (T) FACING.get(internalConstant, null);
}
@Override
Integer map() {
return FACING_MODES.get(mCameraKitConstant, FACING_MODES.get(CameraKit.Constants.FACING_BACK));
<T> T mapWhiteBalance(int internalConstant) {
return (T) WB.get(internalConstant, null);
}
}
@TargetApi(21)
static class Facing2 extends BaseMapper<Integer> {
private static final SparseIntArray FACING_MODES = new SparseIntArray();
static class Mapper2 extends MapperImpl {
static {
FACING_MODES.put(CameraKit.Constants.FACING_BACK, CameraCharacteristics.LENS_FACING_BACK);
FACING_MODES.put(CameraKit.Constants.FACING_FRONT, CameraCharacteristics.LENS_FACING_FRONT);
@Override
<T> T mapWhiteBalance(@WhiteBalance int internalConstant) {
return null;
}
protected Facing2(int cameraKitConstant) {
super(cameraKitConstant);
@Override
<T> T mapFacing(@Facing int internalConstant) {
return null;
}
@Override
Integer map() {
return FACING_MODES.get(mCameraKitConstant, FACING_MODES.get(CameraKit.Constants.FACING_BACK));
<T> T mapFlash(@Flash int internalConstant) {
return null;
}
}
}

@ -31,7 +31,8 @@ class Camera2 extends CameraImpl {
private Size mCaptureSize;
private Size mPreviewSize;
private final HashMap<String, CameraProperties> mCameraPropertyMap = new HashMap<>();
private ConstantMapper.MapperImpl mMapper = new ConstantMapper.Mapper2();
private final HashMap<String, ExtraProperties> mExtraPropertiesMap = new HashMap<>();
Camera2(CameraListener callback, PreviewImpl preview, Context context) {
super(callback, preview);
@ -64,7 +65,7 @@ class Camera2 extends CameraImpl {
}
float w = size.getWidth();
float h = size.getHeight();
mCameraPropertyMap.put(cameraId, new CameraProperties(
mExtraPropertiesMap.put(cameraId, new ExtraProperties(
(float) Math.toDegrees(2*Math.atan(w/(maxFocus[0]*2))),
(float) Math.toDegrees(2*Math.atan(h/(maxFocus[0]*2)))
));
@ -99,11 +100,7 @@ class Camera2 extends CameraImpl {
@Override
void setFacing(@Facing int facing) {
int internalFacing = new ConstantMapper.Facing(facing).map();
if (internalFacing == -1) {
return;
}
int internalFacing = mMapper.mapFacing(facing);
final String[] ids;
try {
ids = mCameraManager.getCameraIdList();
@ -164,6 +161,11 @@ class Camera2 extends CameraImpl {
}
@Override
void setWhiteBalance(@WhiteBalance int whiteBalance) {
}
@Override
void setVideoQuality(int videoQuality) {
@ -248,11 +250,11 @@ class Camera2 extends CameraImpl {
@Nullable
@Override
CameraProperties getCameraProperties() {
ExtraProperties getExtraProperties() {
if (mCamera == null) {
return null;
}
return mCameraPropertyMap.get(mCamera.getId());
return mExtraPropertiesMap.get(mCamera.getId());
}
// Internal

@ -24,6 +24,7 @@ abstract class CameraImpl {
abstract void setMethod(@Method int method);
abstract void setZoom(@ZoomMode int zoom);
abstract void setVideoQuality(@VideoQuality int videoQuality);
abstract void setWhiteBalance(@WhiteBalance int whiteBalance);
abstract void setLocation(double latitude, double longitude);
abstract void captureImage();
@ -36,6 +37,6 @@ abstract class CameraImpl {
abstract boolean isCameraOpened();
@Nullable
abstract CameraProperties getCameraProperties();
abstract ExtraProperties getExtraProperties();
}

@ -1,14 +0,0 @@
package com.flurgle.camerakit;
/**
* Simple pojo containing various camera properties.
*/
public class CameraProperties {
public final float verticalViewingAngle;
public final float horizontalViewingAngle;
public CameraProperties(float verticalViewingAngle, float horizontalViewingAngle) {
this.verticalViewingAngle = verticalViewingAngle;
this.horizontalViewingAngle = horizontalViewingAngle;
}
}

@ -59,6 +59,11 @@ public class CameraKit {
public static final int VIDEO_QUALITY_LOWEST = 5;
public static final int VIDEO_QUALITY_QVGA = 6;
public static final int WHITE_BALANCE_AUTO = 0;
public static final int WHITE_BALANCE_INCANDESCENT = 1;
public static final int WHITE_BALANCE_FLUORESCENT = 2;
public static final int WHITE_BALANCE_DAYLIGHT = 3;
public static final int WHITE_BALANCE_CLOUDY = 4;
}
static class Defaults {
@ -70,7 +75,7 @@ public class CameraKit {
static final int DEFAULT_METHOD = Constants.CAPTURE_METHOD_STANDARD;
static final int DEFAULT_PERMISSIONS = Constants.PERMISSIONS_PICTURE;
static final int DEFAULT_VIDEO_QUALITY = Constants.VIDEO_QUALITY_480P;
static final int DEFAULT_WHITE_BALANCE = Constants.WHITE_BALANCE_AUTO;
static final int DEFAULT_JPEG_QUALITY = 100;
static final boolean DEFAULT_CROP_OUTPUT = false;
static final boolean DEFAULT_ADJUST_VIEW_BOUNDS = false;

@ -80,10 +80,10 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
@Flash private int mFlash;
@Focus private int mFocus;
@Method private int mMethod;
@ZoomMode
private int mZoom;
@ZoomMode private int mZoom;
@Permissions private int mPermissions;
@VideoQuality private int mVideoQuality;
@WhiteBalance private int mWhiteBalance;
private int mJpegQuality;
private boolean mCropOutput;
private boolean mAdjustViewBounds;
@ -116,6 +116,7 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
mMethod = a.getInteger(R.styleable.CameraView_cameraCaptureMethod, CameraKit.Defaults.DEFAULT_METHOD);
mZoom = a.getInteger(R.styleable.CameraView_cameraZoomMode, CameraKit.Defaults.DEFAULT_ZOOM);
mPermissions = a.getInteger(R.styleable.CameraView_cameraPermissionPolicy, CameraKit.Defaults.DEFAULT_PERMISSIONS);
mWhiteBalance = a.getInteger(R.styleable.CameraView_cameraWhiteBalance, CameraKit.Defaults.DEFAULT_WHITE_BALANCE);
mVideoQuality = a.getInteger(R.styleable.CameraView_cameraVideoQuality, CameraKit.Defaults.DEFAULT_VIDEO_QUALITY);
mJpegQuality = a.getInteger(R.styleable.CameraView_cameraJpegQuality, CameraKit.Defaults.DEFAULT_JPEG_QUALITY);
mCropOutput = a.getBoolean(R.styleable.CameraView_cameraCropOutput, CameraKit.Defaults.DEFAULT_CROP_OUTPUT);
@ -138,6 +139,7 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
setZoom(mZoom);
setPermissionPolicy(mPermissions);
setVideoQuality(mVideoQuality);
setWhiteBalance(mWhiteBalance);
if (!isInEditMode()) {
mOrientationHelper = new OrientationHelper(context) {
@ -352,8 +354,8 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
}
@Nullable
public CameraProperties getCameraProperties() {
return mCameraImpl.getCameraProperties();
public ExtraProperties getExtraProperties() {
return mCameraImpl.getExtraProperties();
}
@ -366,6 +368,24 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
mCameraImpl.setLocation(latitude, longitude);
}
/**
* Sets desired white balance to current camera session.
* @param whiteBalance desired white balance behavior.
*/
public void setWhiteBalance(@WhiteBalance int whiteBalance) {
mWhiteBalance = whiteBalance;
mCameraImpl.setWhiteBalance(whiteBalance);
}
/**
* Returns the current white balance behavior.
* @return white balance value.
*/
@WhiteBalance
public int getWhiteBalance() {
return mWhiteBalance;
}
@Facing
public int getFacing() {
return mFacing;
@ -373,7 +393,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
public void setFacing(@Facing final int facing) {
this.mFacing = facing;
run(new Runnable() {
@Override
public void run() {

@ -22,6 +22,14 @@
<enum name="tapWithMarker" value="3" />
</attr>
<attr name="cameraWhiteBalance" format="enum">
<enum name="auto" value="0" />
<enum name="incandescent" value="1" />
<enum name="fluorescent" value="2" />
<enum name="daylight" value="3" />
<enum name="cloudy" value="4" />
</attr>
<attr name="cameraZoomMode" format="enum">
<enum name="off" value="0" />

Loading…
Cancel
Save