refactor w/ readme updates

pull/1/head
Dylan McIntyre 8 years ago
parent 31d7cfc082
commit 94f71bd6d8
  1. 122
      README.md
  2. 133
      camerakit/src/main/api16/com/flurgle/camerakit/Camera1.java
  3. 19
      camerakit/src/main/api21/com/flurgle/camerakit/Camera2.java
  4. 14
      camerakit/src/main/base/com/flurgle/camerakit/CameraImpl.java
  5. 30
      camerakit/src/main/java/com/flurgle/camerakit/CameraKit.java
  6. 259
      camerakit/src/main/java/com/flurgle/camerakit/CameraView.java
  7. 34
      camerakit/src/main/res/values/attrs.xml
  8. 8
      camerakit/src/main/types/com/flurgle/camerakit/Focus.java
  9. 6
      camerakit/src/main/types/com/flurgle/camerakit/Method.java
  10. 14
      camerakit/src/main/types/com/flurgle/camerakit/Zoom.java
  11. 16
      demo/src/main/java/com/flurgle/camerakit/demo/MainActivity.java
  12. 4
      demo/src/main/res/layout/activity_main.xml

@ -2,7 +2,7 @@
#####Originally a fork of [Google's CameraView library](https://github.com/google/cameraview).
CameraKit is an extraordinarily easy to use utility to work with the infamous Android Camera and Camera2 APIs. Built by [Dylan McIntyre](https://github.com/dwillmc).
CameraKit is an extraordinarily easy to use utility to work with the infamous Android Camera and Camera2 APIs. Built by [Dylan McIntyre](https://github.com/dwillmc).
Try out all the unique features using the CameraKit Demo from the Google Play store!
@ -20,26 +20,24 @@ Try out all the unique features using the CameraKit Demo from the Google Play st
- [Usage](#usage)
- [Events](#events)
- [Extra Attributes](#extra-attributes)
- [`ckCropOutput`](#ckcropoutput)
- [`ckFacing`](#ckfacing)
- [`ckFlash`](#ckflash)
- [`ckCaptureMode`](#ckcapturemode)
- [`ckPinchToZoom`](#ckpinchtozoom)
- [`ckTapToFocus`](#cktaptofocus)
- [`ckAutoFocus`](#ckautofocus)
- [`ckCaptureSize`](#ckcapturesize)
- [`ckJpegCompression`](#ckjpegcompression)
- [`ckFocus`](#ckfocus)
- [`ckMethod`](#ckmethod)
- [`ckZoom`](#ckzoom)
- [`ckCropOutput`](#ckcropoutput)
- [`ckJpegQuality`](#ckjpegquality)
- [Capturing Images](#capturing-images)
- [Capturing Video](#capturing-video)
- [Automatic Permissions Behavior](#automatic-permissions-behavior)
- [Dynamic Sizing Behavior](#dynamic-sizing-behavior)
- [Output Cropping](#output-cropping)
- [`adjustViewBounds`](#adjustviewbounds)
- [Capture Mode Behavior](#capture-mode-behavior)
- [Quality](#quality)
- [Speed](#speed)
- [Capture Methods](#capture-methods)
- [Standard](#standard)
- [Still](#still)
- [Auto](#auto)
- [Tap To Focus](#tap-to-focus)
- [Focus](#focus)
- [Credits](#credits)
- [License](#license)
@ -51,9 +49,9 @@ Try out all the unique features using the CameraKit Demo from the Google Play st
- Automatic preview scaling.
- Create a `CameraView` of any size (not just presets!).
- Automatic output cropping to match your `CameraView` bounds.
- Multiple capture modes.
- `PICTURE_MODE_STANDARD`: an image captured normally using the camera APIs.
- `PICTURE_MODE_STILL`: a freeze frame of the `CameraView` preview (similar to SnapChat and Instagram) for devices with slower cameras.
- Multiple capture methods.
- `METHOD_STANDARD`: an image captured normally using the camera APIs.
- `METHOD_STILL`: a freeze frame of the `CameraView` preview (similar to SnapChat and Instagram) for devices with slower cameras.
- Automatic picture mode determination based on measured speed.
- Built-in tap to focus and auto focus.
- Built-in pinch to zoom.
@ -74,7 +72,8 @@ To use CameraKit, simply add a `CameraView` to your layout:
<com.flurgle.camerakit.CameraView
android:id="@+id/camera"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
android:layout_height="wrap_content"
android:adjustViewBounds="true" />
```
Make sure you override `onResume` and `onPause` in your activity, and make calls respectively to `CameraView.start()` and `CameraView.stop()`.
@ -119,7 +118,7 @@ camera.setCameraListener(new CameraListener() {
public void onVideoTaken(File video) {
super.onVideoTaken(video);
}
});
```
@ -129,25 +128,17 @@ camera.setCameraListener(new CameraListener() {
<com.flurgle.camerakit.CameraView xmlns:camerakit="http://schemas.android.com/apk/res-auto"
android:id="@+id/camera"
android:layout_width="match_parent"
android:layout_height="match_parent"
camerakit:ckCropOutput="true"
android:layout_height="wrap_content"
camerakit:ckFacing="back"
camerakit:ckFlash="off"
camerakit:ckCaptureMode="quality"
camerakit:ckPinchToZoom="true"
camerakit:ckTapToFocus="on"
camerakit:ckAutoFocus="true"
camerakit:ckCaptureSize="8"
camerakit:ckJpegCompression="100" />
camerakit:ckFocus="continuous"
camerakit:ckMethod="standard"
camerakit:ckZoom="pinch"
camerakit:ckCropOutput="true"
camerakit:ckJpegQuality="100"
android:adjustViewBounds="true" />
```
#### `ckCropOutput`
| Value | Description |
| --------------| -------------|
| `true` | Crop the output image or video to only contain what can be seen on the `CameraView` preview. |
| `false` | Output the full image or video regardless of what is visible on the `CameraView` preview. |
#### `ckFacing`
| Value | Description |
@ -163,44 +154,37 @@ camera.setCameraListener(new CameraListener() {
| `on` | Default `CameraView` flash to on. |
| `auto` | Default `CameraView` flash to automatic. |
#### `ckCaptureMode`
| Value | Description |
| --------------| -------------|
| `standard` | Use normal Android Camera API image capturing. |
| `still` | Freeze the `CameraView` preview and grab a `Bitmap` of the frame. |
| `auto` (coming soon) | Default picture mode to `standard`, but fallback to `still` if capturing is determined to be too slow. |
#### `ckPinchToZoom`
#### `ckFocus`
| Value | Description |
| --------------| -------------|
| `true` | User can zoom using pinching gestures with their fingers. |
| `false` | Default pinch to zoom behavior disabled. |
| `off` | Tap to focus is enabled and a visible focus circle appears when tapped, similar to the Android built-in camera. |
| `continuous` | Tap to focus is enabled, but no focus circle appears. |
| `tap` | Tap to focus is off. |
#### `ckTapToFocus`
#### `ckMethod`
| Value | Description |
| --------------| -------------|
| `visible` | Tap to focus is enabled and a visible focus circle appears when tapped, similar to the Android built-in camera. |
| `invisible` | Tap to focus is enabled, but no focus circle appears. |
| `off` | Tap to focus is off. |
| `standard` | Use normal Android Camera API image capturing. |
| `still` | Freeze the `CameraView` preview and grab a `Bitmap` of the frame. |
| `auto` (coming soon) | Default picture mode to `standard`, but fallback to `still` if capturing is determined to be too slow. |
#### `ckAutoFocus`
#### `ckZoom`
| Value | Description |
| --------------| -------------|
| `true` | Continuously allow the `CameraView` preview to adjust focus automatically. |
| `false` | Never adjust focus during preview. |
| `off` | User can zoom using pinching gestures with their fingers. |
| `pinch` | User can zoom in and out using pinching gestures on the `CameraView`. |
#### `ckCaptureSize`
#### `ckCropOutput`
| Value | Description |
| --------------| -------------|
| `n <= 0` | Capture at the highest quality possible. |
| `n > 0` | Capture at a size of approximately `n` megapixels. |
| `true` | Crop the output image or video to only contain what can be seen on the `CameraView` preview. |
| `false` | Output the full image or video regardless of what is visible on the `CameraView` preview. |
#### `ckJpegCompression`
#### `ckJpegQuality`
| Value | Description |
| --------------| -------------|
@ -209,20 +193,20 @@ camera.setCameraListener(new CameraListener() {
### 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.captureImage()`. Make sure you setup a `CameraListener` to handle the image callback.
```java
camera.setCameraListener(new CameraListener() {
@Override
public void onPictureTaken(byte[] picture) {
super.onPictureTaken(picture);
// Create a bitmap
Bitmap result = BitmapFactory.decodeByteArray(picture, 0, picture.length);
}
});
camera.takePicture();
camera.captureImage();
```
### Capturing Video
@ -234,7 +218,7 @@ camera.setCameraListener(new CameraListener() {
@Override
public void onVideoTaken(File video) {
super.onVideoTaken(video);
// The File parameter is an MP4 file.
// The File parameter is an MP4 file.
}
});
@ -251,7 +235,7 @@ camera.postDelayed(new Runnable() {
You can handle permissions yourself in whatever way you want, but if you make a call to `CameraView.start()` without the `android.permission.CAMERA` permission, an exception would normally be thrown and your app would crash.
With CameraKit, we will automatically prompt for the `android.permission.CAMERA` permission if it's not available. If you want to handle it yourself, just make sure you dont call `CameraView.start()` until you acquire the permissions.
With CameraKit, we will automatically prompt for the `android.permission.CAMERA` permission if it's not available. If you want to handle it yourself, just make sure you don't call `CameraView.start()` until you acquire the permissions.
![Permissions behavior gif](.repo/permissions.gif)
@ -271,35 +255,35 @@ When you capture output you can either capture everything - even what is not vis
You can use a mix of a fixed dimension (a set value or `match_parent`) as well as `wrap_content`. When you do this make sure you set `android:adjustViewBounds="true"` on the `CameraView`.
When you do this the dimension set to `wrap_content` will automatically align with the true aspect ratio of the preview surface. In this case the whole preview will be visible.
When you do this the dimension set to `wrap_content` will automatically align with the true aspect ratio of the preview surface. In this case the whole preview will be visible with no cropping.
## Capture Mode Behavior
## Capture Methods
We decided to add multiple capture modes to CameraKit to allow you to give a better image capturing experience to users with slower cameras when appropriate.
See [`ckPictureMode`](#ckpicturemode) above for usage.
See [`ckMethod`](#ckmethod) above for usage.
### Quality
### Standard
When you use `PICTURE_MODE_QUALITY` (`camerakit:ckPictureMode="quality"`), images will be captured using the normal camera API capture method using the shutter.
When you use `METHOD_STANDARD` (`camerakit:ckMethod="standard"`), images will be captured using the normal camera API capture method using the shutter.
[Insert GIF]
### Speed
### Still
When you use `PICTURE_MODE_SPEED` (`camerakit:ckPictureMode="speed"`), images will be captured by grabbing a single frame from the preview. This behavior is the same as SnapChat and Instagram. This method has a higher rate of motion blur but can be a better experience for users with slower cameras.
When you use `METHOD_STILL` (`camerakit:ckMethod="still"`), images will be captured by grabbing a single frame from the preview. This behavior is the same as SnapChat and Instagram. This method has a higher rate of motion blur but can be a better experience for users with slower cameras.
[Insert GIF]
### Auto
When you use `PICTURE_MODE_AUTO` (`camerakit:ckPictureMode="speed"`), images will be first be captured using the [quality](#quality) method. If capture consistently takes a long amount of time, the picture mode will fallback to [speed](#speed).
When you use `METHOD_AUTO` (`camerakit:ckMethod="auto"`), images will be first be captured using the [standard](#standard) method. If capture consistently takes a long amount of time, the picture mode will fallback to [still](#still) capture.
[Insert GIF]
## Tap To Focus
## Focus
Along with the always on auto-focus, you can enable tap to focus in your `CameraView`. See [`ckTapToFocus`](#cktaptofocus) for usage. You have the option of having it on with a visible focus marker, on with no marker, or off.
Along with the always on auto-focus, you can enable tap to focus in your `CameraView`. See [`ckFocus`](#ckFocus) for usage. You have the option of having it on with a visible focus marker, on with no marker, or off.
[Insert GIF]

@ -11,6 +11,13 @@ import java.util.List;
import java.util.Set;
import java.util.TreeSet;
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.METHOD_STANDARD;
import static com.flurgle.camerakit.CameraKit.Constants.METHOD_STILL;
@SuppressWarnings("deprecation")
public class Camera1 extends CameraImpl {
@ -21,10 +28,22 @@ public class Camera1 extends CameraImpl {
private Size mPreviewSize;
private Size mCaptureSize;
private int mDisplayOrientation;
@Facing
private int mFacing;
@Flash
private int mFlash;
private boolean mContinuousFocus;
private int mDisplayOrientation;
@Focus
private int mFocus;
@Method
private int mMethod;
@Zoom
private int mZoom;
Camera1(CameraListener callback, PreviewImpl preview) {
super(callback, preview);
@ -57,6 +76,11 @@ public class Camera1 extends CameraImpl {
releaseCamera();
}
@Override
void setDisplayOrientation(int displayOrientation) {
this.mDisplayOrientation = displayOrientation;
}
@Override
void setFacing(@Facing int facing) {
int internalFacing = new ConstantMapper.Facing(facing).map();
@ -81,7 +105,7 @@ public class Camera1 extends CameraImpl {
@Override
void setFlash(@Flash int flash) {
if (isCameraOpened()) {
if (mCameraParameters != null) {
List<String> flashes = mCameraParameters.getSupportedFlashModes();
String internalFlash = new ConstantMapper.Flash(flash).map();
if (flashes != null && flashes.contains(internalFlash)) {
@ -91,7 +115,7 @@ public class Camera1 extends CameraImpl {
String currentFlash = new ConstantMapper.Flash(mFlash).map();
if (flashes == null || !flashes.contains(currentFlash)) {
mCameraParameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
mFlash = CameraKit.Constants.FLASH_OFF;
mFlash = FLASH_OFF;
}
}
@ -102,61 +126,76 @@ public class Camera1 extends CameraImpl {
}
@Override
void setContinuousFocus(boolean continuousFocus) {
this.mContinuousFocus = continuousFocus;
if (mCameraParameters != null) {
final List<String> modes = mCameraParameters.getSupportedFocusModes();
if (mContinuousFocus && modes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
mCameraParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
} else if (modes.contains(Camera.Parameters.FOCUS_MODE_FIXED)) {
mCameraParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_FIXED);
} else if (modes.contains(Camera.Parameters.FOCUS_MODE_INFINITY)) {
mCameraParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_INFINITY);
} else {
mCameraParameters.setFocusMode(modes.get(0));
}
}
}
void setFocus(@Focus int focus) {
this.mFocus = focus;
switch (focus) {
case FOCUS_CONTINUOUS:
if (mCameraParameters != null) {
final List<String> modes = mCameraParameters.getSupportedFocusModes();
if (modes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
mCameraParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
} else {
setFocus(FOCUS_OFF);
}
}
break;
@Override
void setDisplayOrientation(int displayOrientation) {
this.mDisplayOrientation = displayOrientation;
}
case FOCUS_TAP:
setFocus(FOCUS_CONTINUOUS);
break;
@Override
void focus() {
mCamera.autoFocus(null);
case FOCUS_OFF:
if (mCameraParameters != null) {
final List<String> modes = mCameraParameters.getSupportedFocusModes();
if (modes.contains(Camera.Parameters.FOCUS_MODE_FIXED)) {
mCameraParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_FIXED);
} else if (modes.contains(Camera.Parameters.FOCUS_MODE_INFINITY)) {
mCameraParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_INFINITY);
} else {
mCameraParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
}
}
break;
}
}
@Override
void zoom(float percentZoom) {
void setMethod(@Method int method) {
this.mMethod = method;
}
@Override
void captureStandard() {
mCamera.takePicture(null, null, null, new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
mCameraListener.onPictureTaken(data);
camera.startPreview();
}
});
void setZoom(@Zoom int zoom) {
this.mZoom = zoom;
}
@Override
void captureStill() {
mCamera.setOneShotPreviewCallback(new Camera.PreviewCallback() {
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
new Thread(new ProcessStillTask(data, camera, mCameraInfo, new ProcessStillTask.OnStillProcessedListener() {
void captureImage() {
switch (mMethod) {
case METHOD_STANDARD:
mCamera.takePicture(null, null, null, new Camera.PictureCallback() {
@Override
public void onStillProcessed(final YuvImage yuv) {
mCameraListener.onPictureTaken(yuv);
public void onPictureTaken(byte[] data, Camera camera) {
mCameraListener.onPictureTaken(data);
camera.startPreview();
}
})).start();
}
});
});
break;
case METHOD_STILL:
mCamera.setOneShotPreviewCallback(new Camera.PreviewCallback() {
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
new Thread(new ProcessStillTask(data, camera, mCameraInfo, new ProcessStillTask.OnStillProcessedListener() {
@Override
public void onStillProcessed(final YuvImage yuv) {
mCameraListener.onPictureTaken(yuv);
}
})).start();
}
});
break;
}
}
@Override
@ -297,7 +336,7 @@ public class Camera1 extends CameraImpl {
+ (mFacing == CameraKit.Constants.FACING_FRONT ? 180 : 0)
);
setContinuousFocus(mContinuousFocus);
setFocus(mFocus);
setFlash(mFlash);
mCamera.setParameters(mCameraParameters);

@ -17,42 +17,37 @@ class Camera2 extends CameraImpl {
}
@Override
void setFacing(@Facing int facing) {
}
@Override
void setFlash(@Flash int flash) {
void setDisplayOrientation(int displayOrientation) {
}
@Override
void setContinuousFocus(boolean autoFocus) {
void setFacing(@Facing int facing) {
}
@Override
void setDisplayOrientation(int displayOrientation) {
void setFlash(@Flash int flash) {
}
@Override
void focus() {
void setFocus(@Focus int focus) {
}
@Override
void zoom(float percentZoom) {
void setMethod(@Method int method) {
}
@Override
void captureStandard() {
void setZoom(@Zoom int zoom) {
}
@Override
void captureStill() {
void captureImage() {
}

@ -13,17 +13,15 @@ abstract class CameraImpl {
abstract void start();
abstract void stop();
abstract void setFacing(@Facing int facing);
abstract void setFlash(@Flash int flash);
abstract void setContinuousFocus(boolean autoFocus);
abstract void setDisplayOrientation(int displayOrientation);
abstract void focus();
abstract void zoom(float percentZoom);
abstract void captureStandard();
abstract void captureStill();
abstract void setFacing(@Facing int facing);
abstract void setFlash(@Flash int flash);
abstract void setFocus(@Focus int focus);
abstract void setMethod(@Method int method);
abstract void setZoom(@Zoom int zoom);
abstract void captureImage();
abstract void startVideo();
abstract void endVideo();

@ -13,6 +13,8 @@ public class CameraKit {
public static class Constants {
public static final int PERMISSION_REQUEST_CAMERA = 16;
public static final int FACING_BACK = 0;
public static final int FACING_FRONT = 1;
@ -20,15 +22,31 @@ public class CameraKit {
public static final int FLASH_ON = 1;
public static final int FLASH_AUTO = 2;
public static final int CAPTURE_MODE_STANDARD = 0;
public static final int CAPTURE_MODE_STILL = 1;
public static final int PICTURE_MODE_AUTO = 2;
public static final int METHOD_STANDARD = 0;
public static final int METHOD_STILL = 1;
public static final int METHOD_AUTO = 2;
public static final int FOCUS_OFF = 0;
public static final int FOCUS_CONTINUOUS = 1;
public static final int FOCUS_TAP = 2;
public static final int TAP_TO_FOCUS_VISIBLE = 0;
public static final int TAP_TO_FOCUS_INVISIBLE = 1;
public static final int TAP_TO_FOCUS_OFF = 2;
public static final int ZOOM_OFF = 0;
public static final int ZOOM_PINCH = 1;
}
static class Defaults {
static final int DEFAULT_FACING = Constants.FACING_BACK;
static final int DEFAULT_FLASH = Constants.FLASH_OFF;
static final int DEFAULT_FOCUS = Constants.FOCUS_OFF;
static final int DEFAULT_METHOD = Constants.METHOD_STANDARD;
static final int DEFAULT_ZOOM = Constants.ZOOM_OFF;
static final int DEFAULT_JPEG_QUALITY = 100;
static final boolean DEFAULT_CROP_OUTPUT = false;
static final boolean DEFAULT_ADJUST_VIEW_BOUNDS = false;
}
}

@ -8,64 +8,47 @@ import android.content.pm.PackageManager;
import android.content.res.TypedArray;
import android.graphics.Rect;
import android.graphics.YuvImage;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v4.hardware.display.DisplayManagerCompat;
import android.support.v4.os.ParcelableCompat;
import android.support.v4.os.ParcelableCompatCreatorCallbacks;
import android.support.v4.view.ViewCompat;
import android.util.AttributeSet;
import android.view.Display;
import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;
import java.io.ByteArrayOutputStream;
import java.io.File;
import static com.flurgle.camerakit.CameraKit.Constants.CAPTURE_MODE_STANDARD;
import static com.flurgle.camerakit.CameraKit.Constants.CAPTURE_MODE_STILL;
import static com.flurgle.camerakit.CameraKit.Constants.FACING_BACK;
import static com.flurgle.camerakit.CameraKit.Constants.FACING_FRONT;
import static com.flurgle.camerakit.CameraKit.Constants.FLASH_AUTO;
import static com.flurgle.camerakit.CameraKit.Constants.FLASH_OFF;
import static com.flurgle.camerakit.CameraKit.Constants.FLASH_ON;
import static com.flurgle.camerakit.CameraKit.Constants.TAP_TO_FOCUS_VISIBLE;
import static com.flurgle.camerakit.CameraKit.Constants.METHOD_STANDARD;
public class CameraView extends FrameLayout {
private static final int PERMISSION_REQUEST_CAMERA = 16;
private static final int DEFAULT_CAPTURE_SIZE = -1;
private static final int DEFAULT_JPEG_COMPRESSION = 100;
@Facing
private int mFacing;
@Flash
private int mFlash;
@TapToFocus
private int mTapToFocus;
@CaptureMode
private int mCaptureMode;
private boolean mCropOutput;
private boolean mContinuousFocus;
@Focus
private int mFocus;
private float mCaptureSize;
@Method
private int mMethod;
private int mJpegCompression;
@Zoom
private int mZoom;
private int mJpegQuality;
private boolean mCropOutput;
private boolean mAdjustViewBounds;
private boolean mWaitingForPermission;
private CameraListenerMiddleWare mCameraListener;
private DisplayOrientationDetector mDisplayOrientationDetector;
@ -79,8 +62,6 @@ public class CameraView extends FrameLayout {
@SuppressWarnings("all")
public CameraView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
if (attrs != null) {
TypedArray a = context.getTheme().obtainStyledAttributes(
attrs,
@ -88,15 +69,15 @@ public class CameraView extends FrameLayout {
0, 0);
try {
mFacing = a.getInteger(R.styleable.CameraView_ckFacing, FACING_BACK);
mFlash = a.getInteger(R.styleable.CameraView_ckFlash, FLASH_OFF);
mTapToFocus = a.getInteger(R.styleable.CameraView_ckTapToFocus, TAP_TO_FOCUS_VISIBLE);
mCaptureMode = a.getInteger(R.styleable.CameraView_ckCaptureMode, CAPTURE_MODE_STANDARD);
mCropOutput = a.getBoolean(R.styleable.CameraView_ckCropOutput, false);
mContinuousFocus = a.getBoolean(R.styleable.CameraView_ckContinuousFocus, true);
mCaptureSize = a.getFloat(R.styleable.CameraView_ckCaptureSize, DEFAULT_CAPTURE_SIZE);
mJpegCompression = a.getInteger(R.styleable.CameraView_ckJpegCompression, DEFAULT_JPEG_COMPRESSION);
mAdjustViewBounds = a.getBoolean(R.styleable.CameraView_android_adjustViewBounds, false);
mFacing = a.getInteger(R.styleable.CameraView_ckFacing, CameraKit.Defaults.DEFAULT_FACING);
mFlash = a.getInteger(R.styleable.CameraView_ckFlash, CameraKit.Defaults.DEFAULT_FLASH);
mFocus = a.getInteger(R.styleable.CameraView_ckFocus, CameraKit.Defaults.DEFAULT_FOCUS);
mMethod = a.getInteger(R.styleable.CameraView_ckMethod, CameraKit.Defaults.DEFAULT_METHOD);
mZoom = a.getInteger(R.styleable.CameraView_ckZoom, CameraKit.Defaults.DEFAULT_ZOOM);
mJpegQuality = a.getInteger(R.styleable.CameraView_ckJpegQuality, CameraKit.Defaults.DEFAULT_JPEG_QUALITY);
mCropOutput = a.getBoolean(R.styleable.CameraView_ckCropOutput, CameraKit.Defaults.DEFAULT_CROP_OUTPUT);
mAdjustViewBounds = a.getBoolean(R.styleable.CameraView_android_adjustViewBounds, CameraKit.Defaults.DEFAULT_ADJUST_VIEW_BOUNDS);
} finally {
a.recycle();
}
@ -109,11 +90,9 @@ public class CameraView extends FrameLayout {
setFacing(mFacing);
setFlash(mFlash);
setCaptureMode(mCaptureMode);
setCropOutput(mCropOutput);
setTapToFocus(mTapToFocus);
setContinuousFocus(mContinuousFocus);
setCaptureSize(mCaptureSize);
setFocus(mFocus);
setMethod(mMethod);
setZoom(mZoom);
mDisplayOrientationDetector = new DisplayOrientationDetector(context) {
@Override
@ -140,30 +119,34 @@ public class CameraView extends FrameLayout {
}
@Override
protected Parcelable onSaveInstanceState() {
SavedState state = new SavedState(super.onSaveInstanceState());
state.facing = mFacing;
state.flash = mFlash;
return state;
}
@Override
protected void onRestoreInstanceState(Parcelable state) {
if (!(state instanceof SavedState)) {
super.onRestoreInstanceState(state);
return;
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (mAdjustViewBounds) {
Size previewSize = getPreviewSize();
if (getLayoutParams().width == LayoutParams.WRAP_CONTENT) {
int height = MeasureSpec.getSize(heightMeasureSpec);
float ratio = (float) height / (float) previewSize.getWidth();
int width = (int) (previewSize.getHeight() * ratio);
super.onMeasure(
MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
heightMeasureSpec
);
} else if (getLayoutParams().height == LayoutParams.WRAP_CONTENT) {
int width = MeasureSpec.getSize(widthMeasureSpec);
float ratio = (float) width / (float) previewSize.getHeight();
int height = (int) (previewSize.getWidth() * ratio);
super.onMeasure(
widthMeasureSpec,
MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)
);
}
} else {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
SavedState ss = (SavedState) state;
super.onRestoreInstanceState(ss.getSuperState());
setFacing(ss.facing);
setFlash(ss.flash);
}
public void start() {
int permissionCheck = ContextCompat.checkSelfPermission(getContext(), Manifest.permission.CAMERA);
if (permissionCheck == PackageManager.PERMISSION_GRANTED) {
mWaitingForPermission = false;
mCameraImpl.start();
} else {
requestCameraPermission();
@ -179,6 +162,34 @@ public class CameraView extends FrameLayout {
mCameraImpl.setFacing(facing);
}
public void setFlash(@Flash int flash) {
this.mFlash = flash;
mCameraImpl.setFlash(flash);
}
public void setFocus(@Focus int focus) {
this.mFocus = focus;
mCameraImpl.setFocus(mFocus);
}
public void setMethod(@Method int method) {
this.mMethod = method;
mCameraImpl.setMethod(mMethod);
}
public void setZoom(@Zoom int zoom) {
this.mZoom = zoom;
mCameraImpl.setZoom(mZoom);
}
public void setJpegQuality(int jpegQuality) {
this.mJpegQuality = jpegQuality;
}
public void setCropOutput(boolean cropOutput) {
this.mCropOutput = cropOutput;
}
@Facing
public int toggleFacing() {
switch (mFacing) {
@ -194,11 +205,6 @@ public class CameraView extends FrameLayout {
return mFacing;
}
public void setFlash(@Flash int flash) {
this.mFlash = flash;
mCameraImpl.setFlash(flash);
}
@Flash
public int toggleFlash() {
switch (mFlash) {
@ -218,50 +224,12 @@ public class CameraView extends FrameLayout {
return mFlash;
}
public void setCaptureMode(@CaptureMode int captureMode) {
this.mCaptureMode = captureMode;
}
@CaptureMode
public int getCaptureMode() {
return mCaptureMode;
}
public void setCropOutput(boolean cropOutput) {
this.mCropOutput = cropOutput;
}
public void setTapToFocus(@TapToFocus int tapToFocus) {
this.mTapToFocus = tapToFocus;
if (tapToFocus == CameraKit.Constants.TAP_TO_FOCUS_OFF) {
mPreviewImpl.getView().setOnTouchListener(null);
} else {
mPreviewImpl.getView().setOnTouchListener(mTapToFocusOnTouchListener);
}
}
public void setContinuousFocus(boolean continuousFocus) {
this.mContinuousFocus = continuousFocus;
mCameraImpl.setContinuousFocus(continuousFocus);
}
public void setCaptureSize(float captureSize) {
this.mCaptureSize = captureSize;
}
public void setCameraListener(CameraListener cameraListener) {
this.mCameraListener.setCameraListener(cameraListener);
}
public void capturePicture() {
switch (mCaptureMode) {
case CAPTURE_MODE_STANDARD:
mCameraImpl.captureStandard();
break;
case CAPTURE_MODE_STILL:
mCameraImpl.captureStill();
break;
}
public void captureImage() {
mCameraImpl.captureImage();
}
public void startRecordingVideo() {
@ -291,74 +259,11 @@ public class CameraView extends FrameLayout {
}
if (activity != null) {
ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO}, PERMISSION_REQUEST_CAMERA);
mWaitingForPermission = true;
}
}
@Override
public void onWindowFocusChanged(boolean hasWindowFocus) {
super.onWindowFocusChanged(hasWindowFocus);
if (mWaitingForPermission) {
if (ContextCompat.checkSelfPermission(getContext(), Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {
start();
}
}
}
private OnTouchListener mTapToFocusOnTouchListener = new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
mCameraImpl.focus();
}
return false;
}
};
protected static class SavedState extends BaseSavedState {
@Facing
private int facing;
@Flash
private int flash;
@SuppressWarnings("WrongConstant")
public SavedState(Parcel source, ClassLoader loader) {
super(source);
facing = source.readInt();
flash = source.readInt();
}
public SavedState(Parcelable superState) {
super(superState);
}
@Override
public void writeToParcel(Parcel out, int flags) {
super.writeToParcel(out, flags);
out.writeInt(facing);
out.writeInt(flash);
ActivityCompat.requestPermissions(
activity,
new String[]{Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO},
CameraKit.Constants.PERMISSION_REQUEST_CAMERA);
}
public static final Parcelable.Creator<SavedState> CREATOR = ParcelableCompat.newCreator(new ParcelableCompatCreatorCallbacks<SavedState>() {
@Override
public SavedState createFromParcel(Parcel in, ClassLoader loader) {
return new SavedState(in, loader);
}
@Override
public SavedState[] newArray(int size) {
return new SavedState[size];
}
});
}
private class CameraListenerMiddleWare extends CameraListener {
@ -381,10 +286,10 @@ public class CameraView extends FrameLayout {
public void onPictureTaken(byte[] jpeg) {
super.onPictureTaken(jpeg);
if (mCropOutput) {
int width = mCaptureMode == CAPTURE_MODE_STANDARD ? mCameraImpl.getCaptureResolution().getWidth() : mCameraImpl.getPreviewResolution().getWidth();
int height = mCaptureMode == CAPTURE_MODE_STANDARD ? mCameraImpl.getCaptureResolution().getHeight() : mCameraImpl.getPreviewResolution().getHeight();
int width = mMethod == METHOD_STANDARD ? mCameraImpl.getCaptureResolution().getWidth() : mCameraImpl.getPreviewResolution().getWidth();
int height = mMethod == METHOD_STANDARD ? mCameraImpl.getCaptureResolution().getHeight() : mCameraImpl.getPreviewResolution().getHeight();
AspectRatio outputRatio = AspectRatio.of(getWidth(), getHeight());
getCameraListener().onPictureTaken(new CenterCrop(jpeg, outputRatio, mJpegCompression).getJpeg());
getCameraListener().onPictureTaken(new CenterCrop(jpeg, outputRatio, mJpegQuality).getJpeg());
} else {
getCameraListener().onPictureTaken(jpeg);
}
@ -395,10 +300,10 @@ public class CameraView extends FrameLayout {
super.onPictureTaken(yuv);
if (mCropOutput) {
AspectRatio outputRatio = AspectRatio.of(getWidth(), getHeight());
getCameraListener().onPictureTaken(new CenterCrop(yuv, outputRatio, mJpegCompression).getJpeg());
getCameraListener().onPictureTaken(new CenterCrop(yuv, outputRatio, mJpegQuality).getJpeg());
} else {
ByteArrayOutputStream out = new ByteArrayOutputStream();
yuv.compressToJpeg(new Rect(0, 0, yuv.getWidth(), yuv.getHeight()), mJpegCompression, out);
yuv.compressToJpeg(new Rect(0, 0, yuv.getWidth(), yuv.getHeight()), mJpegQuality, out);
getCameraListener().onPictureTaken(out.toByteArray());
}
}

@ -14,27 +14,33 @@
<enum name="auto" value="2" />
</attr>
<attr name="ckCaptureMode" format="enum">
<enum name="standard" value="0" />
<enum name="still" value="1" />
<enum name="auto" value="2" />
</attr>
<attr name="ckFocus" format="enum">
<enum name="off" value="0" />
<enum name="continuous" value="1" />
<attr name="ckCropOutput" format="boolean" />
<!-- TODO: Set to unique value when feature added -->
<enum name="tap" value="1" />
</attr>
<attr name="ckPinchToZoom" format="boolean" />
<attr name="ckZoom" format="enum">
<enum name="off" value="0" />
<attr name="ckTapToFocus" format="enum">
<enum name="visible" value="0" />
<enum name="invisible" value="1" />
<enum name="off" value="2" />
<!-- TODO: Set to unique value when feature added -->
<enum name="pinch" value="0" />
</attr>
<attr name="ckContinuousFocus" format="boolean" />
<attr name="ckCaptureSize" format="float" />
<attr name="ckMethod" format="enum">
<enum name="standard" value="0" />
<enum name="still" value="1" />
<attr name="ckJpegCompression" format="integer" />
<!-- TODO: Set to unique value when feature added -->
<enum name="auto" value="0" />
</attr>
<attr name="ckJpegQuality" format="integer" />
<attr name="ckCropOutput" format="boolean" />
<attr name="android:adjustViewBounds" />

@ -5,11 +5,11 @@ import android.support.annotation.IntDef;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import static com.flurgle.camerakit.CameraKit.Constants.TAP_TO_FOCUS_INVISIBLE;
import static com.flurgle.camerakit.CameraKit.Constants.TAP_TO_FOCUS_OFF;
import static com.flurgle.camerakit.CameraKit.Constants.TAP_TO_FOCUS_VISIBLE;
import static com.flurgle.camerakit.CameraKit.Constants.FOCUS_TAP;
import static com.flurgle.camerakit.CameraKit.Constants.FOCUS_OFF;
import static com.flurgle.camerakit.CameraKit.Constants.FOCUS_CONTINUOUS;
@Retention(RetentionPolicy.SOURCE)
@IntDef({TAP_TO_FOCUS_VISIBLE, TAP_TO_FOCUS_INVISIBLE, TAP_TO_FOCUS_OFF})
@IntDef({FOCUS_CONTINUOUS, FOCUS_TAP, FOCUS_OFF})
public @interface Focus {
}

@ -5,10 +5,10 @@ import android.support.annotation.IntDef;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import static com.flurgle.camerakit.CameraKit.Constants.CAPTURE_MODE_STANDARD;
import static com.flurgle.camerakit.CameraKit.Constants.CAPTURE_MODE_STILL;
import static com.flurgle.camerakit.CameraKit.Constants.METHOD_STANDARD;
import static com.flurgle.camerakit.CameraKit.Constants.METHOD_STILL;
@Retention(RetentionPolicy.SOURCE)
@IntDef({CAPTURE_MODE_STANDARD, CAPTURE_MODE_STILL})
@IntDef({METHOD_STANDARD, METHOD_STILL})
public @interface Method {
}

@ -1,8 +1,14 @@
package com.flurgle.camerakit;
/**
* Created by dylanmcintyre on 2/21/17.
*/
import android.support.annotation.IntDef;
public class Zoom {
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import static com.flurgle.camerakit.CameraKit.Constants.ZOOM_OFF;
import static com.flurgle.camerakit.CameraKit.Constants.ZOOM_PINCH;
@Retention(RetentionPolicy.SOURCE)
@IntDef({ZOOM_OFF, ZOOM_PINCH})
public @interface Zoom {
}

@ -136,7 +136,7 @@ public class MainActivity extends AppCompatActivity {
startActivity(intent);
}
});
camera.capturePicture();
camera.captureImage();
}
@OnClick(R.id.captureVideo)
@ -191,10 +191,10 @@ public class MainActivity extends AppCompatActivity {
RadioGroup.OnCheckedChangeListener captureModeChangedListener = new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
camera.setCaptureMode(
camera.setMethod(
checkedId == R.id.modeCaptureQuality ?
CameraKit.Constants.CAPTURE_MODE_STANDARD :
CameraKit.Constants.CAPTURE_MODE_STILL
CameraKit.Constants.METHOD_STANDARD :
CameraKit.Constants.METHOD_STILL
);
Toast.makeText(MainActivity.this, "Picture capture set to" + (checkedId == R.id.modeCaptureQuality ? " quality!" : " speed!"), Toast.LENGTH_SHORT).show();
@ -215,12 +215,12 @@ public class MainActivity extends AppCompatActivity {
RadioGroup.OnCheckedChangeListener tapToFocusModeChangedListener = new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
camera.setTapToFocus(
camera.setFocus(
checkedId == R.id.modeTapToFocusVisible ?
CameraKit.Constants.TAP_TO_FOCUS_VISIBLE :
CameraKit.Constants.FOCUS_CONTINUOUS :
checkedId == R.id.modeTapToFocusInvisible ?
CameraKit.Constants.TAP_TO_FOCUS_INVISIBLE :
CameraKit.Constants.TAP_TO_FOCUS_OFF
CameraKit.Constants.FOCUS_TAP :
CameraKit.Constants.FOCUS_OFF
);
Toast.makeText(MainActivity.this, "Tap to focus is" + (checkedId == R.id.modeTapToFocusOff ? " off!" : (checkedId == R.id.modeTapToFocusVisible) ? " on and visible!" : " on and invisible!"), Toast.LENGTH_SHORT).show();

@ -19,11 +19,11 @@
android:layout_height="500dp"
android:layout_gravity="center_horizontal"
app:ckCaptureMode="standard"
app:ckContinuousFocus="true"
app:ckCropOutput="false"
app:ckFacing="back"
app:ckFlash="off"
app:ckTapToFocus="visible" />
app:ckFocus="continuous"
app:ckJpegQuality="100" />
<LinearLayout
android:layout_width="match_parent"

Loading…
Cancel
Save