diff --git a/README.md b/README.md
index 810a66e4..1b65d4b0 100644
--- a/README.md
+++ b/README.md
@@ -19,6 +19,7 @@ Try out all the unique features using the CameraKit Demo from the Google Play st
- [`ckFacing`](#ckfacing)
- [`ckFlash`](#ckflash)
- [`ckPictureMode`](#ckpicturemode)
+ - [`ckTapToFocus`](#cktaptofocus)
- [Capturing Images](#capturing-images)
- [Capturing Video](#capturing-video)
- [Automatic Permissions Behavior](#automatic-permissions-behavior)
@@ -43,6 +44,7 @@ Try out all the unique features using the CameraKit Demo from the Google Play st
- `PICTURE_MODE_QUALITY`: an image captured normally using the camera APIs.
- `PICTURE_MODE_SPEED`: 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.
## Setup
@@ -119,7 +121,8 @@ camera.setCameraListener(new CameraListener() {
camerakit:ckCropOutput="true"
camerakit:ckFacing="back"
camerakit:ckFlash="off"
- camerakit:ckPictureMode="quality" />
+ camerakit:ckPictureMode="quality"
+ camerakit:ckTapToFocus="on" />
```
#### `ckCropOutput`
@@ -148,6 +151,14 @@ camera.setCameraListener(new CameraListener() {
#### `ckPictureMode`
+| Value | Description |
+| --------------| -------------|
+| `on` | 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. |
+
+#### `ckTapToFocus`
+
| Value | Description |
| --------------| -------------|
| `quality` | Use normal Android Camera API image capturing. |
@@ -238,12 +249,18 @@ When you use `PICTURE_MODE_SPEED` (`camerakit:ckPictureMode="speed"`), images wi
[Insert GIF]
-## Auto
+### 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).
[Insert GIF]
+## Tap To 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.
+
+[Insert GIF]
+
## Credits
Dylan McIntyre
diff --git a/camerakit/src/main/java/com/flurgle/camerakit/Camera2.java b/camerakit/src/main/java/com/flurgle/camerakit/Camera2.java
index 437c41c1..11d74271 100644
--- a/camerakit/src/main/java/com/flurgle/camerakit/Camera2.java
+++ b/camerakit/src/main/java/com/flurgle/camerakit/Camera2.java
@@ -22,7 +22,6 @@ import android.util.SparseIntArray;
import android.view.Surface;
import android.view.View;
-import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.SortedSet;
import java.util.TreeSet;
@@ -37,8 +36,8 @@ public class Camera2 extends CameraViewImpl {
private static final SparseIntArray INTERNAL_FACINGS = new SparseIntArray();
static {
- INTERNAL_FACINGS.put(Constants.FACING_BACK, CameraCharacteristics.LENS_FACING_BACK);
- INTERNAL_FACINGS.put(Constants.FACING_FRONT, CameraCharacteristics.LENS_FACING_FRONT);
+ INTERNAL_FACINGS.put(CameraKit.Constants.FACING_BACK, CameraCharacteristics.LENS_FACING_BACK);
+ INTERNAL_FACINGS.put(CameraKit.Constants.FACING_FRONT, CameraCharacteristics.LENS_FACING_FRONT);
}
private CameraManager mCameraManager;
@@ -166,7 +165,7 @@ public class Camera2 extends CameraViewImpl {
@Override
void capturePicture() {
- if (mFacing == INTERNAL_FACINGS.get(Constants.FACING_BACK)) {
+ if (mFacing == INTERNAL_FACINGS.get(CameraKit.Constants.FACING_BACK)) {
lockFocus();
} else {
captureStillPicture();
@@ -198,15 +197,15 @@ public class Camera2 extends CameraViewImpl {
void updateFlash(CaptureRequest.Builder builder) {
switch (mFlash) {
- case Constants.FLASH_OFF:
+ case CameraKit.Constants.FLASH_OFF:
builder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON);
builder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_OFF);
break;
- case Constants.FLASH_ON:
+ case CameraKit.Constants.FLASH_ON:
builder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_ALWAYS_FLASH);
builder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_OFF);
break;
- case Constants.FLASH_AUTO:
+ case CameraKit.Constants.FLASH_AUTO:
builder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
builder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_OFF);
break;
@@ -259,7 +258,7 @@ public class Camera2 extends CameraViewImpl {
}
// The operation can reach here when the only camera device is an external one.
// We treat it as facing back.
- mFacing = Constants.FACING_BACK;
+ mFacing = CameraKit.Constants.FACING_BACK;
return true;
} catch (CameraAccessException e) {
throw new RuntimeException("Failed to get a list of camera devices", e);
@@ -308,7 +307,7 @@ public class Camera2 extends CameraViewImpl {
Size previewSize = getOptimalPreviewSize();
AspectRatio aspectRatio = AspectRatio.of(previewSize.getWidth(), previewSize.getHeight());
Size bestSize = findSizeClosestTo(1500000, aspectRatio, mCaptureSizes);
- mImageReader = ImageReader.newInstance(bestSize.getWidth(), bestSize.getHeight(), ImageFormat.JPEG, 1);
+ mImageReader = ImageReader.newInstance(bestSize.getWidth(), bestSize.getHeight(), ImageFormat.YUV_420_888, 3);
mImageReader.setOnImageAvailableListener(mOnImageAvailableListener, mBackgroundHandler);
}
@@ -377,6 +376,7 @@ public class Camera2 extends CameraViewImpl {
try {
mPreviewRequestBuilder = mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
mPreviewRequestBuilder.addTarget(surface);
+ mPreviewRequestBuilder.addTarget(mImageReader.getSurface());
mCamera.createCaptureSession(Arrays.asList(surface, mImageReader.getSurface()), mSessionCallback, mBackgroundHandler);
} catch (CameraAccessException e) {
throw new RuntimeException("Failed to start camera session");
@@ -406,7 +406,7 @@ public class Camera2 extends CameraViewImpl {
int sensorOrientation = mCameraCharacteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
captureRequestBuilder.set(CaptureRequest.JPEG_ORIENTATION,
(sensorOrientation +
- mDisplayOrientation * (mFacing == Constants.FACING_FRONT ? 1 : -1) +
+ mDisplayOrientation * (mFacing == CameraKit.Constants.FACING_FRONT ? 1 : -1) +
360) % 360);
// Stop preview and capture a still picture.
mCaptureSession.stopRepeating();
@@ -524,15 +524,20 @@ public class Camera2 extends CameraViewImpl {
@Override
public void onImageAvailable(ImageReader reader) {
- try (Image image = reader.acquireNextImage()) {
- Image.Plane[] planes = image.getPlanes();
- if (planes.length > 0) {
- ByteBuffer buffer = planes[0].getBuffer();
- byte[] data = new byte[buffer.remaining()];
- buffer.get(data);
- getCameraListener().onPictureTaken(data);
- }
- }
+ Image image = reader.acquireLatestImage();
+ // Process the image
+ image.close();
+
+// try (Image image = reader.acquireNextImage()) {
+// image.close();
+// Image.Plane[] planes = image.getPlanes();
+// if (planes.length > 0) {
+// ByteBuffer buffer = planes[0].getBuffer();
+// byte[] data = new byte[buffer.remaining()];
+// buffer.get(data);
+// //getCameraListener().onPictureTaken(data);
+// }
+// }
}
};
diff --git a/camerakit/src/main/java/com/flurgle/camerakit/CameraKit.java b/camerakit/src/main/java/com/flurgle/camerakit/CameraKit.java
new file mode 100644
index 00000000..69674ab3
--- /dev/null
+++ b/camerakit/src/main/java/com/flurgle/camerakit/CameraKit.java
@@ -0,0 +1,25 @@
+package com.flurgle.camerakit;
+
+public class CameraKit {
+
+ public static class Constants {
+
+ public static final int FACING_BACK = 0;
+ public static final int FACING_FRONT = 1;
+
+ public static final int FLASH_OFF = 0;
+ public static final int FLASH_ON = 1;
+ public static final int FLASH_AUTO = 2;
+
+ public static final int PICTURE_MODE_QUALITY = 0;
+ public static final int PICTURE_MODE_SPEED = 1;
+ public static final int PICTURE_MODE_AUTO = 2;
+
+ public static final int TAP_TO_FOCUS_ON = 0;
+ public static final int TAP_TO_FOCUS_INVISIBLE = 1;
+ public static final int TAP_TO_FOCUS_OFF = 2;
+
+ }
+
+
+}
diff --git a/camerakit/src/main/java/com/flurgle/camerakit/CameraView.java b/camerakit/src/main/java/com/flurgle/camerakit/CameraView.java
index ad213461..2bc6278b 100644
--- a/camerakit/src/main/java/com/flurgle/camerakit/CameraView.java
+++ b/camerakit/src/main/java/com/flurgle/camerakit/CameraView.java
@@ -27,33 +27,30 @@ import java.io.File;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import static com.flurgle.camerakit.CameraKit.Constants.*;
+
public class CameraView extends FrameLayout {
private static final int PERMISSION_REQUEST_CAMERA = 16;
- public static final int FACING_BACK = Constants.FACING_BACK;
- public static final int FACING_FRONT = Constants.FACING_FRONT;
-
@IntDef({FACING_BACK, FACING_FRONT})
@Retention(RetentionPolicy.SOURCE)
- public @interface Facing {
+ @interface Facing {
}
- public static final int FLASH_OFF = Constants.FLASH_OFF;
- public static final int FLASH_ON = Constants.FLASH_ON;
- public static final int FLASH_AUTO = Constants.FLASH_AUTO;
-
@Retention(RetentionPolicy.SOURCE)
@IntDef({FLASH_OFF, FLASH_ON, FLASH_AUTO})
- public @interface Flash {
+ @interface Flash {
}
- public static final int PICTURE_MODE_QUALITY = Constants.PICTURE_MODE_QUALITY;
- public static final int PICTURE_MODE_SPEED = Constants.PICTURE_MODE_SPEED;
-
@Retention(RetentionPolicy.SOURCE)
@IntDef({PICTURE_MODE_QUALITY, PICTURE_MODE_SPEED})
- public @interface PictureMode {
+ @interface PictureMode {
+ }
+
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({TAP_TO_FOCUS_ON, TAP_TO_FOCUS_INVISIBLE, TAP_TO_FOCUS_OFF})
+ @interface TapToFocus {
}
private int mFacing;
@@ -66,6 +63,8 @@ public class CameraView extends FrameLayout {
private boolean mCropOutput;
+ private int mTapToFocus;
+
private boolean mAdjustViewBounds;
private boolean mWaitingForPermission;
@@ -90,21 +89,25 @@ public class CameraView extends FrameLayout {
int attr = a.getIndex(i);
if (attr == R.styleable.CameraView_ckFacing) {
- mFacing = a.getInteger(R.styleable.CameraView_ckFacing, 0);
+ mFacing = a.getInteger(R.styleable.CameraView_ckFacing, FACING_BACK);
}
if (attr == R.styleable.CameraView_ckFlash) {
- mFlash = a.getInteger(R.styleable.CameraView_ckFlash, 0);
+ mFlash = a.getInteger(R.styleable.CameraView_ckFlash, FLASH_OFF);
}
if (attr == R.styleable.CameraView_ckPictureMode) {
- mPictureMode = a.getInteger(R.styleable.CameraView_ckPictureMode, 0);
+ mPictureMode = a.getInteger(R.styleable.CameraView_ckPictureMode, PICTURE_MODE_QUALITY);
}
if (attr == R.styleable.CameraView_ckCropOutput) {
mCropOutput = a.getBoolean(R.styleable.CameraView_ckCropOutput, false);
}
+ if (attr == R.styleable.CameraView_ckTapToFocus) {
+ mTapToFocus = a.getInteger(R.styleable.CameraView_ckTapToFocus, TAP_TO_FOCUS_ON);
+ }
+
if (attr == R.styleable.CameraView_android_adjustViewBounds) {
mAdjustViewBounds = a.getBoolean(R.styleable.CameraView_android_adjustViewBounds, false);
}
@@ -229,6 +232,10 @@ public class CameraView extends FrameLayout {
this.mCropOutput = cropOutput;
}
+ public void setTapToFocus(@TapToFocus int tapToFocus) {
+ this.mTapToFocus = tapToFocus;
+ }
+
public void setCameraListener(CameraListener cameraListener) {
this.mCameraListener = new CameraListenerMiddleWare(cameraListener);
mCameraImpl.setCameraListener(mCameraListener);
@@ -348,6 +355,10 @@ public class CameraView extends FrameLayout {
Bitmap bitmap = BitmapFactory.decodeByteArray(picture, 0, picture.length);
int previewWidth = mCameraImpl.mPreview.getWidth();
int previewHeight = mCameraImpl.mPreview.getWidth();
+
+ AspectRatio viewRatio = AspectRatio.of(getWidth(), getHeight());
+ AspectRatio previewRatio = AspectRatio.of(previewWidth, previewHeight);
+
mCameraListener.onPictureTaken(picture);
} else {
mCameraListener.onPictureTaken(picture);
diff --git a/camerakit/src/main/java/com/flurgle/camerakit/Constants.java b/camerakit/src/main/java/com/flurgle/camerakit/Constants.java
deleted file mode 100644
index 7e203fdb..00000000
--- a/camerakit/src/main/java/com/flurgle/camerakit/Constants.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.flurgle.camerakit;
-
-public class Constants {
-
- public static final int FACING_BACK = 0;
- public static final int FACING_FRONT = 1;
-
- public static final int FLASH_OFF = 0;
- public static final int FLASH_ON = 1;
- public static final int FLASH_AUTO = 2;
-
- public static final int PICTURE_MODE_QUALITY = 0;
- public static final int PICTURE_MODE_SPEED = 1;
-
-}
diff --git a/camerakit/src/main/res/values/attrs.xml b/camerakit/src/main/res/values/attrs.xml
index 7328910a..f646eda2 100644
--- a/camerakit/src/main/res/values/attrs.xml
+++ b/camerakit/src/main/res/values/attrs.xml
@@ -22,6 +22,12 @@
+
+
+
+
+
+
diff --git a/demo/src/main/java/com/flurgle/camerakit/demo/MainActivity.java b/demo/src/main/java/com/flurgle/camerakit/demo/MainActivity.java
index d4a61c54..a6496705 100644
--- a/demo/src/main/java/com/flurgle/camerakit/demo/MainActivity.java
+++ b/demo/src/main/java/com/flurgle/camerakit/demo/MainActivity.java
@@ -14,9 +14,9 @@ import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
+import com.flurgle.camerakit.CameraKit;
import com.flurgle.camerakit.CameraListener;
import com.flurgle.camerakit.CameraView;
-import com.flurgle.camerakit.Constants;
import butterknife.BindView;
import butterknife.ButterKnife;
@@ -57,7 +57,7 @@ public class MainActivity extends AppCompatActivity {
@BindView(R.id.height)
EditText height;
- int pictureMode = Constants.PICTURE_MODE_QUALITY;
+ int pictureMode = CameraKit.Constants.PICTURE_MODE_QUALITY;
boolean blockInvalidation;
@@ -116,11 +116,11 @@ public class MainActivity extends AppCompatActivity {
@OnClick(R.id.toggleCamera)
void toggleCamera() {
switch (camera.toggleFacing()) {
- case Constants.FACING_BACK:
+ case CameraKit.Constants.FACING_BACK:
Toast.makeText(this, "Switched to back camera!", Toast.LENGTH_SHORT).show();
break;
- case Constants.FACING_FRONT:
+ case CameraKit.Constants.FACING_FRONT:
Toast.makeText(this, "Switched to front camera!", Toast.LENGTH_SHORT).show();
break;
}
@@ -129,15 +129,15 @@ public class MainActivity extends AppCompatActivity {
@OnClick(R.id.toggleFlash)
void toggleFlash() {
switch (camera.toggleFlash()) {
- case Constants.FLASH_ON:
+ case CameraKit.Constants.FLASH_ON:
Toast.makeText(this, "Flash on!", Toast.LENGTH_SHORT).show();
break;
- case Constants.FLASH_OFF:
+ case CameraKit.Constants.FLASH_OFF:
Toast.makeText(this, "Flash off!", Toast.LENGTH_SHORT).show();
break;
- case Constants.FLASH_AUTO:
+ case CameraKit.Constants.FLASH_AUTO:
Toast.makeText(this, "Flash auto!", Toast.LENGTH_SHORT).show();
break;
}
@@ -147,7 +147,7 @@ public class MainActivity extends AppCompatActivity {
void modeQuality(CompoundButton buttonCompat, boolean checked) {
modeSpeed.setChecked(false);
if (checked) {
- camera.setPictureMode(CameraView.PICTURE_MODE_QUALITY);
+ camera.setPictureMode(CameraKit.Constants.PICTURE_MODE_QUALITY);
}
invalidateParameters();
@@ -157,7 +157,7 @@ public class MainActivity extends AppCompatActivity {
void modeSpeed(CompoundButton buttonCompat, boolean checked) {
modeQuality.setChecked(false);
if (checked) {
- camera.setPictureMode(CameraView.PICTURE_MODE_SPEED);
+ camera.setPictureMode(CameraKit.Constants.PICTURE_MODE_SPEED);
}
invalidateParameters();
diff --git a/demo/src/main/res/layout/activity_main.xml b/demo/src/main/res/layout/activity_main.xml
index 3fd3cf27..fde00098 100644
--- a/demo/src/main/res/layout/activity_main.xml
+++ b/demo/src/main/res/layout/activity_main.xml
@@ -21,7 +21,7 @@
app:ckCropOutput="true"
app:ckFacing="back"
app:ckFlash="off"
- app:ckPictureMode="quality" />
+ app:ckPictureMode="speed" />