From 0a4a60ac2f6478601ed35b68cbde81ac9576f69a Mon Sep 17 00:00:00 2001 From: Dylan McIntyre Date: Tue, 21 Feb 2017 00:01:34 -0500 Subject: [PATCH] overhaul --- README.md | 29 +- .../api16/com/flurgle/camerakit/Camera1.java | 508 ++++++------------ .../com/flurgle/camerakit/ConstantMapper.java | 62 +++ .../flurgle/camerakit/ProcessStillTask.java | 55 ++ .../api21/com/flurgle/camerakit/Camera2.java | 453 +--------------- .../com/flurgle/camerakit/CameraImpl.java | 10 +- .../com/flurgle/camerakit/PreviewImpl.java | 2 +- .../flurgle/camerakit/TextureViewPreview.java | 2 +- .../java/com/flurgle/camerakit/CameraKit.java | 9 + .../com/flurgle/camerakit/CameraView.java | 80 +-- camerakit/src/main/res/values/attrs.xml | 4 +- camerakit/src/main/res/values/strings.xml | 3 - .../com/flurgle/camerakit/CenterCrop.java | 5 +- .../{YuvUtils.java => Rotation.java} | 44 +- .../flurgle/camerakit/demo/MainActivity.java | 2 +- demo/src/main/res/layout/activity_main.xml | 3 +- 16 files changed, 398 insertions(+), 873 deletions(-) create mode 100644 camerakit/src/main/api16/com/flurgle/camerakit/ConstantMapper.java create mode 100644 camerakit/src/main/api16/com/flurgle/camerakit/ProcessStillTask.java delete mode 100644 camerakit/src/main/res/values/strings.xml rename camerakit/src/main/utils/com/flurgle/camerakit/{YuvUtils.java => Rotation.java} (56%) diff --git a/README.md b/README.md index fafbcaa9..41a58be3 100644 --- a/README.md +++ b/README.md @@ -24,9 +24,11 @@ Try out all the unique features using the CameraKit Demo from the Google Play st - [`ckFacing`](#ckfacing) - [`ckFlash`](#ckflash) - [`ckCaptureMode`](#ckcapturemode) + - [`ckPinchToZoom`](#ckpinchtozoom) - [`ckTapToFocus`](#cktaptofocus) - [`ckAutoFocus`](#ckautofocus) - [`ckCaptureSize`](#ckcapturesize) + - [`ckJpegCompression`](#ckjpegcompression) - [Capturing Images](#capturing-images) - [Capturing Video](#capturing-video) - [Automatic Permissions Behavior](#automatic-permissions-behavior) @@ -44,15 +46,17 @@ Try out all the unique features using the CameraKit Demo from the Google Play st ## Features - Image and video capture seamlessly working with the same preview session. +- Automatic use of both Camera and Camera2 APIs. - Automatic system permission handling. - 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_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. + - `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. - Automatic picture mode determination based on measured speed. - Built-in tap to focus and auto focus. +- Built-in pinch to zoom. ## Setup @@ -70,7 +74,7 @@ To use CameraKit, simply add a `CameraView` to your layout: + android:layout_height="wrap_content" /> ``` Make sure you override `onResume` and `onPause` in your activity, and make calls respectively to `CameraView.start()` and `CameraView.stop()`. @@ -130,9 +134,11 @@ camera.setCameraListener(new CameraListener() { camerakit:ckFacing="back" camerakit:ckFlash="off" camerakit:ckCaptureMode="quality" + camerakit:ckPinchToZoom="true" camerakit:ckTapToFocus="on" camerakit:ckAutoFocus="true" - camerakit:ckCaptureSize="8" /> + camerakit:ckCaptureSize="8" + camerakit:ckJpegCompression="100" /> ``` #### `ckCropOutput` @@ -149,7 +155,6 @@ camera.setCameraListener(new CameraListener() { | `back` | Default `CameraView` preview to back camera. | | `front` | Default `CameraView` preview to front camera. | - #### `ckFlash` | Value | Description | @@ -166,6 +171,13 @@ camera.setCameraListener(new CameraListener() { | `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` + +| Value | Description | +| --------------| -------------| +| `true` | User can zoom using pinching gestures with their fingers. | +| `false` | Default pinch to zoom behavior disabled. | + #### `ckTapToFocus` | Value | Description | @@ -188,6 +200,13 @@ camera.setCameraListener(new CameraListener() { | `n <= 0` | Capture at the highest quality possible. | | `n > 0` | Capture at a size of approximately `n` megapixels. | +#### `ckJpegCompression` + +| Value | Description | +| --------------| -------------| +| `0 <= n <= 100`| Percent quality for returned JPEG data. | + + ### Capturing Images To capture an image just call `CameraView.capturePicture()`. Make sure you setup a `CameraListener` to handle the image callback. diff --git a/camerakit/src/main/api16/com/flurgle/camerakit/Camera1.java b/camerakit/src/main/api16/com/flurgle/camerakit/Camera1.java index 6cb948cc..9e48cc94 100644 --- a/camerakit/src/main/api16/com/flurgle/camerakit/Camera1.java +++ b/camerakit/src/main/api16/com/flurgle/camerakit/Camera1.java @@ -2,179 +2,111 @@ package com.flurgle.camerakit; import android.graphics.YuvImage; import android.hardware.Camera; -import android.media.CamcorderProfile; -import android.media.MediaRecorder; -import android.os.Build; -import android.support.annotation.NonNull; -import android.support.v4.util.SparseArrayCompat; import android.view.SurfaceHolder; -import java.io.File; import java.io.IOException; +import java.util.HashSet; import java.util.Iterator; import java.util.List; -import java.util.SortedSet; +import java.util.Set; import java.util.TreeSet; +@SuppressWarnings("deprecation") public class Camera1 extends CameraImpl { - private static final SparseArrayCompat FLASH_MODES = 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); - } - - private static final SparseArrayCompat 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); - } - - private File mVideoFile; - private int mCameraId; private Camera mCamera; private Camera.Parameters mCameraParameters; - private final Camera.CameraInfo mCameraInfo = new Camera.CameraInfo(); + private Camera.CameraInfo mCameraInfo; private Size mPreviewSize; private Size mCaptureSize; - private boolean mShowingPreview; - private boolean mAutoFocus; private int mFacing; private int mFlash; + private boolean mContinuousFocus; private int mDisplayOrientation; - private TreeSet mPreviewSizes; - private TreeSet mCaptureSizes; - - private MediaRecorder mMediaRecorder; - - private CameraListener mCameraListener; - - Camera1(@NonNull CameraListener cameraListener, @NonNull PreviewImpl preview) { - super(cameraListener, preview); - - this.mCameraListener = cameraListener; - this.mPreviewSizes = new TreeSet<>(); - this.mCaptureSizes = new TreeSet<>(); - this.mVideoFile = new File(mPreview.getView().getContext().getExternalFilesDir(null), "video.mp4"); - + Camera1(CameraListener callback, PreviewImpl preview) { + super(callback, preview); preview.setCallback(new PreviewImpl.Callback() { @Override public void onSurfaceChanged() { if (mCamera != null) { - setUpPreview(); + setupPreview(); adjustCameraParameters(); } } }); + + mCameraInfo = new Camera.CameraInfo(); } + // CameraImpl: + @Override void start() { - setFacingInternal(mFacing); + setFacing(mFacing); openCamera(); - if (mPreview.isReady()) { - setUpPreview(); - } - mShowingPreview = true; + if (mPreview.isReady()) setupPreview(); mCamera.startPreview(); } @Override void stop() { - if (mCamera != null) { - mCamera.stopPreview(); - } - mShowingPreview = false; + if (mCamera != null) mCamera.stopPreview(); releaseCamera(); } @Override - boolean isCameraOpened() { - return mCamera != null; - } - - @Override - void setFacing(int facing) { - if (mFacing == facing) { + void setFacing(@Facing int facing) { + int internalFacing = new ConstantMapper.Facing(facing).map(); + if (internalFacing == -1) { return; } - if (setFacingInternal(facing) && isCameraOpened()) { - stop(); - start(); - } - } - - private boolean setFacingInternal(int facing) { - int trueValue = FACING_MODES.get(facing, -1); - if (trueValue == -1) { - return false; - } for (int i = 0, count = Camera.getNumberOfCameras(); i < count; i++) { Camera.getCameraInfo(i, mCameraInfo); - if (mCameraInfo.facing == trueValue) { + if (mCameraInfo.facing == internalFacing) { mCameraId = i; mFacing = facing; - return true; + break; } } - return false; - } - - @Override - void setFlash(int flash) { - if (flash == mFlash) { - return; - } - if (setFlashInternal(flash)) { - mCamera.setParameters(mCameraParameters); + if (mFacing == facing && isCameraOpened()) { + stop(); + start(); } } - private boolean setFlashInternal(int flash) { + @Override + void setFlash(@Flash int flash) { if (isCameraOpened()) { - List modes = mCameraParameters.getSupportedFlashModes(); - String mode = FLASH_MODES.get(flash); - if (modes != null && modes.contains(mode)) { - mCameraParameters.setFlashMode(mode); + List flashes = mCameraParameters.getSupportedFlashModes(); + String internalFlash = new ConstantMapper.Flash(flash).map(); + if (flashes != null && flashes.contains(internalFlash)) { + mCameraParameters.setFlashMode(internalFlash); mFlash = flash; - return true; - } - String currentMode = FLASH_MODES.get(mFlash); - if (modes == null || !modes.contains(currentMode)) { - mCameraParameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF); - mFlash = CameraKit.Constants.FLASH_OFF; - return true; + } else { + 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; + } } - return false; + + mCamera.setParameters(mCameraParameters); } else { mFlash = flash; - return false; } } @Override - void setAutoFocus(boolean autoFocus) { - if (autoFocus == mAutoFocus) { - return; - } - if (setAutoFocusInternal(autoFocus)) { - mCamera.setParameters(mCameraParameters); - } - } - - private boolean setAutoFocusInternal(boolean autoFocus) { - mAutoFocus = autoFocus; - if (isCameraOpened()) { + void setContinuousFocus(boolean continuousFocus) { + this.mContinuousFocus = continuousFocus; + if (mCameraParameters != null) { final List modes = mCameraParameters.getSupportedFocusModes(); - if (autoFocus && modes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) { + 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); @@ -183,33 +115,26 @@ public class Camera1 extends CameraImpl { } else { mCameraParameters.setFocusMode(modes.get(0)); } - - mCameraParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO); - return true; - } else { - return false; } } @Override - void captureStandard() { - if (!isCameraOpened()) { - throw new IllegalStateException("Camera is not ready. Call start() before takePicture()."); - } - if (mAutoFocus) { - mCamera.cancelAutoFocus(); - mCamera.autoFocus(new Camera.AutoFocusCallback() { - @Override - public void onAutoFocus(boolean success, Camera camera) { - takePictureInternal(); - } - }); - } else { - takePictureInternal(); - } + void setDisplayOrientation(int displayOrientation) { + this.mDisplayOrientation = displayOrientation; + } + + @Override + void focus() { + mCamera.autoFocus(null); + } + + @Override + void zoom(float percentZoom) { + } - void takePictureInternal() { + @Override + void captureStandard() { mCamera.takePicture(null, null, null, new Camera.PictureCallback() { @Override public void onPictureTaken(byte[] data, Camera camera) { @@ -227,155 +152,106 @@ public class Camera1 extends CameraImpl { new Thread(new ProcessStillTask(data, camera, mCameraInfo, new ProcessStillTask.OnStillProcessedListener() { @Override public void onStillProcessed(final YuvImage yuv) { - mPreview.getView().post(new Runnable() { - @Override - public void run() { - mCameraListener.onPictureTaken(yuv); - } - }); + mCameraListener.onPictureTaken(yuv); } })).start(); } }); } - static class ProcessStillTask implements Runnable { + @Override + void startVideo() { - byte[] data; - Camera camera; - Camera.CameraInfo cameraInfo; - OnStillProcessedListener onStillProcessedListener; + } - public ProcessStillTask(byte[] data, Camera camera, Camera.CameraInfo cameraInfo, OnStillProcessedListener onStillProcessedListener) { - this.data = data; - this.camera = camera; - this.cameraInfo = cameraInfo; - this.onStillProcessedListener = onStillProcessedListener; - } + @Override + void endVideo() { - @Override - public void run() { - Camera.Parameters parameters = camera.getParameters(); - int width = parameters.getPreviewSize().width; - int height = parameters.getPreviewSize().height; - int rotation = cameraInfo.orientation; - byte[] rotatedData = YuvUtils.rotateNV21(data, width, height, rotation); - - int postWidth; - int postHeight; - - switch (rotation) { - case 90: - case 270: - postWidth = height; - postHeight = width; - break; + } - case 0: - case 180: - default: - postWidth = width; - postHeight = height; - break; + @Override + Size getCaptureResolution() { + if (mCaptureSize == null && mCameraParameters != null) { + TreeSet sizes = new TreeSet<>(); + for (Camera.Size size : mCameraParameters.getSupportedPictureSizes()) { + sizes.add(new Size(size.width, size.height)); } - YuvImage yuv = new YuvImage(rotatedData, parameters.getPreviewFormat(), postWidth, postHeight, null); - - onStillProcessedListener.onStillProcessed(yuv); - } - - interface OnStillProcessedListener { - void onStillProcessed(YuvImage yuv); + TreeSet aspectRatios = findCommonAspectRatios( + mCameraParameters.getSupportedPreviewSizes(), + mCameraParameters.getSupportedPictureSizes() + ); + AspectRatio targetRatio = aspectRatios.last(); + + Iterator descendingSizes = sizes.descendingIterator(); + Size size; + while (descendingSizes.hasNext() && mCaptureSize == null) { + size = descendingSizes.next(); + if (targetRatio.matches(size)) { + mCaptureSize = size; + break; + } + } } + return mCaptureSize; } @Override - void startVideo() { - try { - prepareMediaRecorder(); - } catch (IOException e) { - if (mMediaRecorder != null) { - mMediaRecorder.release(); + Size getPreviewResolution() { + if (mPreviewSize == null && mCameraParameters != null) { + TreeSet sizes = new TreeSet<>(); + for (Camera.Size size : mCameraParameters.getSupportedPreviewSizes()) { + sizes.add(new Size(size.width, size.height)); } - return; + TreeSet aspectRatios = findCommonAspectRatios( + mCameraParameters.getSupportedPreviewSizes(), + mCameraParameters.getSupportedPictureSizes() + ); + AspectRatio targetRatio = aspectRatios.last(); + + Iterator descendingSizes = sizes.descendingIterator(); + Size size; + while (descendingSizes.hasNext() && mPreviewSize == null) { + size = descendingSizes.next(); + if (targetRatio.matches(size)) { + mPreviewSize = size; + break; + } + } } - } - - void prepareMediaRecorder() throws IOException { - mCamera.unlock(); - mMediaRecorder = new MediaRecorder(); - mMediaRecorder.setCamera(mCamera); - - mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER); - mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); - mMediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_480P)); - - mMediaRecorder.setOutputFile(mVideoFile.getAbsolutePath()); - mMediaRecorder.setOrientationHint(mCameraInfo.orientation); - - mMediaRecorder.prepare(); - mMediaRecorder.start(); + return mPreviewSize; } @Override - void endVideo() { - if (mMediaRecorder != null) { - mMediaRecorder.stop(); - mMediaRecorder = null; - } - - mCameraListener.onVideoTaken(mVideoFile); - + boolean isCameraOpened() { + return mCamera != null; } - @Override - void focus() { - mCamera.autoFocus(null); - } + // Internal: - @Override - void setDisplayOrientation(int displayOrientation) { - if (mDisplayOrientation == displayOrientation) { - return; - } - mDisplayOrientation = displayOrientation; - if (isCameraOpened()) { - int cameraRotation = calcCameraRotation(displayOrientation); - mCameraParameters.setRotation(cameraRotation); - mCamera.setParameters(mCameraParameters); - final boolean needsToStopPreview = mShowingPreview && Build.VERSION.SDK_INT < 14; - if (needsToStopPreview) { - mCamera.stopPreview(); - } - mCamera.setDisplayOrientation(cameraRotation); - if (needsToStopPreview) { - mCamera.startPreview(); - } + private void openCamera() { + if (mCamera != null) { + releaseCamera(); } - } - private int calcCameraRotation(int rotation) { - if (mCameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { - return (360 - (mCameraInfo.orientation + rotation) % 360) % 360; - } else { - return (mCameraInfo.orientation - rotation + 360) % 360; - } + mCamera = Camera.open(mCameraId); + mCameraParameters = mCamera.getParameters(); + + adjustCameraParameters(); + mCamera.setDisplayOrientation( + calculateCameraRotation(mDisplayOrientation) + ); + + mCameraListener.onCameraOpened(); } - private void setUpPreview() { + private void setupPreview() { try { if (mPreview.getOutputClass() == SurfaceHolder.class) { - final boolean needsToStopPreview = mShowingPreview && Build.VERSION.SDK_INT < 14; - if (needsToStopPreview) { - mCamera.stopPreview(); - } mCamera.setPreviewDisplay(mPreview.getSurfaceHolder()); - if (needsToStopPreview) { - mCamera.startPreview(); - } } else { mCamera.setPreviewTexture(mPreview.getSurfaceTexture()); } @@ -384,110 +260,70 @@ public class Camera1 extends CameraImpl { } } - private void adjustCameraParameters() { - SortedSet sizes = mPreviewSizes; - mPreviewSize = chooseOptimalSize(sizes); - final Camera.Size currentSize = mCameraParameters.getPictureSize(); - if (currentSize.width != mPreviewSize.getWidth() || currentSize.height != mPreviewSize.getHeight()) { - Iterator iterator = mCaptureSizes.descendingIterator(); - Size pictureSize; - while ((pictureSize = iterator.next()) != null) { - if (AspectRatio.of(mPreviewSize.getWidth(), mPreviewSize.getHeight()).matches(pictureSize)) { - break; - } - } - - if (pictureSize == null) { - pictureSize = mCaptureSizes.last(); - } - - mCaptureSize = pictureSize; - - if (mShowingPreview) { - mCamera.stopPreview(); - } - - mCameraParameters.setPreviewSize(mPreviewSize.getWidth(), mPreviewSize.getHeight()); - mPreview.setTruePreviewSize(mPreviewSize.getWidth(), mPreviewSize.getHeight()); - mCameraParameters.setPictureSize(pictureSize.getWidth(), pictureSize.getHeight()); - mCameraParameters.setRotation(calcCameraRotation(mDisplayOrientation) + (mFacing == CameraKit.Constants.FACING_FRONT ? 180 : 0)); - - setAutoFocusInternal(mAutoFocus); - - //setFlashInternal(mFlash); - - mCamera.setParameters(mCameraParameters); - if (mShowingPreview) { - mCamera.startPreview(); - } + private void releaseCamera() { + if (mCamera != null) { + mCamera.release(); + mCamera = null; + mCameraListener.onCameraClosed(); } } - private Size chooseOptimalSize(SortedSet sizes) { - if (!mPreview.isReady()) { // Not yet laid out - return sizes.last(); // Return the smallest size - } - - int desiredWidth; - int desiredHeight; - final int surfaceWidth = mPreview.getWidth(); - final int surfaceHeight = mPreview.getHeight(); - if (mDisplayOrientation == 90 || mDisplayOrientation == 270) { - desiredWidth = surfaceHeight; - desiredHeight = surfaceWidth; + private int calculateCameraRotation(int rotation) { + if (mCameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { + return (360 - (mCameraInfo.orientation + rotation) % 360) % 360; } else { - desiredWidth = surfaceWidth; - desiredHeight = surfaceHeight; + return (mCameraInfo.orientation - rotation + 360) % 360; } - Size result = null; - for (Size size : sizes) { // Iterate from small to large - if (desiredWidth <= size.getWidth() && desiredHeight <= size.getHeight()) { - return size; + } - } - result = size; - } - return result; + private void adjustCameraParameters() { + mCameraParameters.setPreviewSize( + getPreviewResolution().getWidth(), + getPreviewResolution().getHeight() + ); + + mPreview.setTruePreviewSize( + getPreviewResolution().getWidth(), + getPreviewResolution().getHeight() + ); + + mCameraParameters.setPictureSize( + getCaptureResolution().getWidth(), + getCaptureResolution().getHeight() + ); + + mCameraParameters.setRotation( + calculateCameraRotation(mDisplayOrientation) + + (mFacing == CameraKit.Constants.FACING_FRONT ? 180 : 0) + ); + + setContinuousFocus(mContinuousFocus); + setFlash(mFlash); + + mCamera.setParameters(mCameraParameters); } - private void openCamera() { - if (mCamera != null) { - releaseCamera(); - } - mCamera = Camera.open(mCameraId); - mCameraParameters = mCamera.getParameters(); - // Supported preview sizes - mPreviewSizes.clear(); - for (Camera.Size size : mCameraParameters.getSupportedPreviewSizes()) { - mPreviewSizes.add(new Size(size.width, size.height)); - } - // Supported picture sizes; - mCaptureSizes.clear(); - for (Camera.Size size : mCameraParameters.getSupportedPictureSizes()) { - mCaptureSizes.add(new Size(size.width, size.height)); + private TreeSet findCommonAspectRatios(List previewSizes, List captureSizes) { + Set previewAspectRatios = new HashSet<>(); + for (Camera.Size size : previewSizes) { + if (size.width >= CameraKit.Internal.screenHeight && size.height >= CameraKit.Internal.screenWidth) { + previewAspectRatios.add(AspectRatio.of(size.width, size.height)); + } } - adjustCameraParameters(); - mCamera.setDisplayOrientation(calcCameraRotation(mDisplayOrientation)); - - mCameraListener.onCameraOpened(); - } + Set captureAspectRatios = new HashSet<>(); + for (Camera.Size size : captureSizes) { + captureAspectRatios.add(AspectRatio.of(size.width, size.height)); + } - private void releaseCamera() { - if (mCamera != null) { - mCamera.release(); - mCamera = null; - mCameraListener.onCameraClosed(); + TreeSet output = new TreeSet<>(); + for (AspectRatio aspectRatio : previewAspectRatios) { + if (captureAspectRatios.contains(aspectRatio)) { + output.add(aspectRatio); + } } - } - @Override - Size getCaptureResolution() { - return mCaptureSize; + return output; } - @Override - Size getPreviewResolution() { - return mPreviewSize; - } } diff --git a/camerakit/src/main/api16/com/flurgle/camerakit/ConstantMapper.java b/camerakit/src/main/api16/com/flurgle/camerakit/ConstantMapper.java new file mode 100644 index 00000000..51dbcbb7 --- /dev/null +++ b/camerakit/src/main/api16/com/flurgle/camerakit/ConstantMapper.java @@ -0,0 +1,62 @@ +package com.flurgle.camerakit; + +import android.hardware.Camera; +import android.support.v4.util.SparseArrayCompat; + +public class ConstantMapper { + + private abstract static class BaseMapper { + + protected int mCameraKitConstant; + + protected BaseMapper(int cameraKitConstant) { + this.mCameraKitConstant = cameraKitConstant; + } + + abstract T map(); + + } + + public static class Flash extends BaseMapper { + + private static final SparseArrayCompat FLASH_MODES = 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); + } + + protected Flash(int cameraKitConstant) { + super(cameraKitConstant); + } + + @Override + String map() { + return FLASH_MODES.get(mCameraKitConstant, FLASH_MODES.get(CameraKit.Constants.FLASH_OFF)); + } + + } + + public static class Facing extends BaseMapper { + + private static final SparseArrayCompat 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); + } + + @Override + Integer map() { + return FACING_MODES.get(mCameraKitConstant, FACING_MODES.get(Camera.CameraInfo.CAMERA_FACING_BACK)); + } + + } + + +} diff --git a/camerakit/src/main/api16/com/flurgle/camerakit/ProcessStillTask.java b/camerakit/src/main/api16/com/flurgle/camerakit/ProcessStillTask.java new file mode 100644 index 00000000..3a6386ce --- /dev/null +++ b/camerakit/src/main/api16/com/flurgle/camerakit/ProcessStillTask.java @@ -0,0 +1,55 @@ +package com.flurgle.camerakit; + +import android.graphics.YuvImage; +import android.hardware.Camera; + +class ProcessStillTask implements Runnable { + + private byte[] data; + private Camera camera; + private Camera.CameraInfo cameraInfo; + private OnStillProcessedListener onStillProcessedListener; + + public ProcessStillTask(byte[] data, Camera camera, Camera.CameraInfo cameraInfo, OnStillProcessedListener onStillProcessedListener) { + this.data = data; + this.camera = camera; + this.cameraInfo = cameraInfo; + this.onStillProcessedListener = onStillProcessedListener; + } + + @Override + public void run() { + Camera.Parameters parameters = camera.getParameters(); + int width = parameters.getPreviewSize().width; + int height = parameters.getPreviewSize().height; + int rotation = cameraInfo.orientation; + byte[] rotatedData = new Rotation(data, width, height, rotation).getYuv(); + + int postWidth; + int postHeight; + + switch (rotation) { + case 90: + case 270: + postWidth = height; + postHeight = width; + break; + + case 0: + case 180: + default: + postWidth = width; + postHeight = height; + break; + } + + YuvImage yuv = new YuvImage(rotatedData, parameters.getPreviewFormat(), postWidth, postHeight, null); + + onStillProcessedListener.onStillProcessed(yuv); + } + + interface OnStillProcessedListener { + void onStillProcessed(YuvImage yuv); + } + +} \ No newline at end of file diff --git a/camerakit/src/main/api21/com/flurgle/camerakit/Camera2.java b/camerakit/src/main/api21/com/flurgle/camerakit/Camera2.java index 69fb49cf..3d01c0d3 100644 --- a/camerakit/src/main/api21/com/flurgle/camerakit/Camera2.java +++ b/camerakit/src/main/api21/com/flurgle/camerakit/Camera2.java @@ -1,493 +1,84 @@ package com.flurgle.camerakit; -import android.graphics.YuvImage; -import android.hardware.Camera; -import android.media.CamcorderProfile; -import android.media.MediaRecorder; -import android.os.Build; -import android.support.annotation.NonNull; -import android.support.v4.util.SparseArrayCompat; -import android.view.SurfaceHolder; +class Camera2 extends CameraImpl { -import java.io.File; -import java.io.IOException; -import java.util.Iterator; -import java.util.List; -import java.util.SortedSet; -import java.util.TreeSet; - -public class Camera2 extends CameraImpl { - - private static final SparseArrayCompat FLASH_MODES = 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); - } - - private static final SparseArrayCompat 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); - } - - private File mVideoFile; - - private int mCameraId; - private Camera mCamera; - private Camera.Parameters mCameraParameters; - private final Camera.CameraInfo mCameraInfo = new Camera.CameraInfo(); - private Size mPreviewSize; - private Size mCaptureSize; - - private boolean mShowingPreview; - private boolean mAutoFocus; - private int mFacing; - private int mFlash; - private int mDisplayOrientation; - - private TreeSet mPreviewSizes; - private TreeSet mCaptureSizes; - - private MediaRecorder mMediaRecorder; - - private CameraListener mCameraListener; - - Camera2(@NonNull CameraListener cameraListener, @NonNull PreviewImpl preview) { - super(cameraListener, preview); - - this.mCameraListener = cameraListener; - this.mPreviewSizes = new TreeSet<>(); - this.mCaptureSizes = new TreeSet<>(); - this.mVideoFile = new File(mPreview.getView().getContext().getExternalFilesDir(null), "video.mp4"); - - preview.setCallback(new PreviewImpl.Callback() { - @Override - public void onSurfaceChanged() { - if (mCamera != null) { - setUpPreview(); - adjustCameraParameters(); - } - } - }); + Camera2(CameraListener callback, PreviewImpl preview) { + super(callback, preview); } @Override void start() { - setFacingInternal(mFacing); - openCamera(); - if (mPreview.isReady()) { - setUpPreview(); - } - mShowingPreview = true; - mCamera.startPreview(); + } @Override void stop() { - if (mCamera != null) { - mCamera.stopPreview(); - } - mShowingPreview = false; - releaseCamera(); + } @Override - boolean isCameraOpened() { - return mCamera != null; + void setFacing(@Facing int facing) { + } @Override - void setFacing(int facing) { - if (mFacing == facing) { - return; - } - if (setFacingInternal(facing) && isCameraOpened()) { - stop(); - start(); - } - } + void setFlash(@Flash int flash) { - private boolean setFacingInternal(int facing) { - int trueValue = FACING_MODES.get(facing, -1); - if (trueValue == -1) { - return false; - } + } - for (int i = 0, count = Camera.getNumberOfCameras(); i < count; i++) { - Camera.getCameraInfo(i, mCameraInfo); - if (mCameraInfo.facing == trueValue) { - mCameraId = i; - mFacing = facing; - return true; - } - } + @Override + void setContinuousFocus(boolean autoFocus) { - return false; } @Override - void setFlash(int flash) { - if (flash == mFlash) { - return; - } - if (setFlashInternal(flash)) { - mCamera.setParameters(mCameraParameters); - } - } + void setDisplayOrientation(int displayOrientation) { - private boolean setFlashInternal(int flash) { - if (isCameraOpened()) { - List modes = mCameraParameters.getSupportedFlashModes(); - String mode = FLASH_MODES.get(flash); - if (modes != null && modes.contains(mode)) { - mCameraParameters.setFlashMode(mode); - mFlash = flash; - return true; - } - String currentMode = FLASH_MODES.get(mFlash); - if (modes == null || !modes.contains(currentMode)) { - mCameraParameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF); - mFlash = CameraKit.Constants.FLASH_OFF; - return true; - } - return false; - } else { - mFlash = flash; - return false; - } } @Override - void setAutoFocus(boolean autoFocus) { - if (autoFocus == mAutoFocus) { - return; - } - if (setAutoFocusInternal(autoFocus)) { - mCamera.setParameters(mCameraParameters); - } + void focus() { + } - private boolean setAutoFocusInternal(boolean autoFocus) { - mAutoFocus = autoFocus; - if (isCameraOpened()) { - final List modes = mCameraParameters.getSupportedFocusModes(); - if (autoFocus && 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)); - } + @Override + void zoom(float percentZoom) { - mCameraParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO); - return true; - } else { - return false; - } } @Override void captureStandard() { - if (!isCameraOpened()) { - throw new IllegalStateException("Camera is not ready. Call start() before takePicture()."); - } - if (mAutoFocus) { - mCamera.cancelAutoFocus(); - mCamera.autoFocus(new Camera.AutoFocusCallback() { - @Override - public void onAutoFocus(boolean success, Camera camera) { - takePictureInternal(); - } - }); - } else { - takePictureInternal(); - } - } - void takePictureInternal() { - mCamera.takePicture(null, null, null, new Camera.PictureCallback() { - @Override - public void onPictureTaken(byte[] data, Camera camera) { - mCameraListener.onPictureTaken(data); - camera.startPreview(); - } - }); } @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() { - @Override - public void onStillProcessed(final YuvImage yuv) { - mPreview.getView().post(new Runnable() { - @Override - public void run() { - mCameraListener.onPictureTaken(yuv); - } - }); - } - })).start(); - } - }); - } - - static class ProcessStillTask implements Runnable { - - byte[] data; - Camera camera; - Camera.CameraInfo cameraInfo; - OnStillProcessedListener onStillProcessedListener; - - public ProcessStillTask(byte[] data, Camera camera, Camera.CameraInfo cameraInfo, OnStillProcessedListener onStillProcessedListener) { - this.data = data; - this.camera = camera; - this.cameraInfo = cameraInfo; - this.onStillProcessedListener = onStillProcessedListener; - } - - @Override - public void run() { - Camera.Parameters parameters = camera.getParameters(); - int width = parameters.getPreviewSize().width; - int height = parameters.getPreviewSize().height; - int rotation = cameraInfo.orientation; - byte[] rotatedData = YuvUtils.rotateNV21(data, width, height, rotation); - - int postWidth; - int postHeight; - - switch (rotation) { - case 90: - case 270: - postWidth = height; - postHeight = width; - break; - - case 0: - case 180: - default: - postWidth = width; - postHeight = height; - break; - } - - YuvImage yuv = new YuvImage(rotatedData, parameters.getPreviewFormat(), postWidth, postHeight, null); - - onStillProcessedListener.onStillProcessed(yuv); - } - - interface OnStillProcessedListener { - void onStillProcessed(YuvImage yuv); - } } @Override void startVideo() { - try { - prepareMediaRecorder(); - } catch (IOException e) { - if (mMediaRecorder != null) { - mMediaRecorder.release(); - } - return; - } - } - - void prepareMediaRecorder() throws IOException { - mCamera.unlock(); - - mMediaRecorder = new MediaRecorder(); - mMediaRecorder.setCamera(mCamera); - - mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER); - mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); - mMediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_480P)); - - mMediaRecorder.setOutputFile(mVideoFile.getAbsolutePath()); - mMediaRecorder.setOrientationHint(mCameraInfo.orientation); - - mMediaRecorder.prepare(); - mMediaRecorder.start(); } @Override void endVideo() { - if (mMediaRecorder != null) { - mMediaRecorder.stop(); - mMediaRecorder = null; - } - - mCameraListener.onVideoTaken(mVideoFile); } @Override - void focus() { - mCamera.autoFocus(null); + Size getCaptureResolution() { + return null; } @Override - void setDisplayOrientation(int displayOrientation) { - if (mDisplayOrientation == displayOrientation) { - return; - } - mDisplayOrientation = displayOrientation; - if (isCameraOpened()) { - int cameraRotation = calcCameraRotation(displayOrientation); - mCameraParameters.setRotation(cameraRotation); - mCamera.setParameters(mCameraParameters); - final boolean needsToStopPreview = mShowingPreview && Build.VERSION.SDK_INT < 14; - if (needsToStopPreview) { - mCamera.stopPreview(); - } - mCamera.setDisplayOrientation(cameraRotation); - if (needsToStopPreview) { - mCamera.startPreview(); - } - } - } - - private int calcCameraRotation(int rotation) { - if (mCameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { - return (360 - (mCameraInfo.orientation + rotation) % 360) % 360; - } else { - return (mCameraInfo.orientation - rotation + 360) % 360; - } - } - - private void setUpPreview() { - try { - if (mPreview.getOutputClass() == SurfaceHolder.class) { - final boolean needsToStopPreview = mShowingPreview && Build.VERSION.SDK_INT < 14; - if (needsToStopPreview) { - mCamera.stopPreview(); - } - mCamera.setPreviewDisplay(mPreview.getSurfaceHolder()); - if (needsToStopPreview) { - mCamera.startPreview(); - } - } else { - mCamera.setPreviewTexture(mPreview.getSurfaceTexture()); - } - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - private void adjustCameraParameters() { - SortedSet sizes = mPreviewSizes; - mPreviewSize = chooseOptimalSize(sizes); - final Camera.Size currentSize = mCameraParameters.getPictureSize(); - if (currentSize.width != mPreviewSize.getWidth() || currentSize.height != mPreviewSize.getHeight()) { - Iterator iterator = mCaptureSizes.descendingIterator(); - Size pictureSize; - while ((pictureSize = iterator.next()) != null) { - if (AspectRatio.of(mPreviewSize.getWidth(), mPreviewSize.getHeight()).matches(pictureSize)) { - break; - } - } - - if (pictureSize == null) { - pictureSize = mCaptureSizes.last(); - } - - mCaptureSize = pictureSize; - - if (mShowingPreview) { - mCamera.stopPreview(); - } - - mCameraParameters.setPreviewSize(mPreviewSize.getWidth(), mPreviewSize.getHeight()); - mPreview.setTruePreviewSize(mPreviewSize.getWidth(), mPreviewSize.getHeight()); - mCameraParameters.setPictureSize(pictureSize.getWidth(), pictureSize.getHeight()); - mCameraParameters.setRotation(calcCameraRotation(mDisplayOrientation) + (mFacing == CameraKit.Constants.FACING_FRONT ? 180 : 0)); - - setAutoFocusInternal(mAutoFocus); - - //setFlashInternal(mFlash); - - mCamera.setParameters(mCameraParameters); - if (mShowingPreview) { - mCamera.startPreview(); - } - } - } - - private Size chooseOptimalSize(SortedSet sizes) { - if (!mPreview.isReady()) { // Not yet laid out - return sizes.last(); // Return the smallest size - } - - int desiredWidth; - int desiredHeight; - final int surfaceWidth = mPreview.getWidth(); - final int surfaceHeight = mPreview.getHeight(); - if (mDisplayOrientation == 90 || mDisplayOrientation == 270) { - desiredWidth = surfaceHeight; - desiredHeight = surfaceWidth; - } else { - desiredWidth = surfaceWidth; - desiredHeight = surfaceHeight; - } - Size result = null; - for (Size size : sizes) { // Iterate from small to large - if (desiredWidth <= size.getWidth() && desiredHeight <= size.getHeight()) { - return size; - - } - result = size; - } - return result; - } - - private void openCamera() { - if (mCamera != null) { - releaseCamera(); - } - mCamera = Camera.open(mCameraId); - mCameraParameters = mCamera.getParameters(); - // Supported preview sizes - mPreviewSizes.clear(); - for (Camera.Size size : mCameraParameters.getSupportedPreviewSizes()) { - mPreviewSizes.add(new Size(size.width, size.height)); - } - // Supported picture sizes; - mCaptureSizes.clear(); - for (Camera.Size size : mCameraParameters.getSupportedPictureSizes()) { - mCaptureSizes.add(new Size(size.width, size.height)); - } - - adjustCameraParameters(); - mCamera.setDisplayOrientation(calcCameraRotation(mDisplayOrientation)); - - mCameraListener.onCameraOpened(); - } - - private void releaseCamera() { - if (mCamera != null) { - mCamera.release(); - mCamera = null; - mCameraListener.onCameraClosed(); - } + Size getPreviewResolution() { + return null; } @Override - Size getCaptureResolution() { - return mCaptureSize; + boolean isCameraOpened() { + return false; } - @Override - Size getPreviewResolution() { - return mPreviewSize; - } } diff --git a/camerakit/src/main/base/com/flurgle/camerakit/CameraImpl.java b/camerakit/src/main/base/com/flurgle/camerakit/CameraImpl.java index df04432d..ade7ca15 100644 --- a/camerakit/src/main/base/com/flurgle/camerakit/CameraImpl.java +++ b/camerakit/src/main/base/com/flurgle/camerakit/CameraImpl.java @@ -1,8 +1,8 @@ package com.flurgle.camerakit; -public abstract class CameraImpl { +abstract class CameraImpl { - protected CameraListener mCameraListener; + protected final CameraListener mCameraListener; protected final PreviewImpl mPreview; CameraImpl(CameraListener callback, PreviewImpl preview) { @@ -13,14 +13,13 @@ public abstract class CameraImpl { abstract void start(); abstract void stop(); - abstract boolean isCameraOpened(); - abstract void setFacing(@Facing int facing); abstract void setFlash(@Flash int flash); - abstract void setAutoFocus(boolean autoFocus); + abstract void setContinuousFocus(boolean autoFocus); abstract void setDisplayOrientation(int displayOrientation); abstract void focus(); + abstract void zoom(float percentZoom); abstract void captureStandard(); abstract void captureStill(); @@ -30,5 +29,6 @@ public abstract class CameraImpl { abstract Size getCaptureResolution(); abstract Size getPreviewResolution(); + abstract boolean isCameraOpened(); } diff --git a/camerakit/src/main/base/com/flurgle/camerakit/PreviewImpl.java b/camerakit/src/main/base/com/flurgle/camerakit/PreviewImpl.java index 3850416f..25823927 100644 --- a/camerakit/src/main/base/com/flurgle/camerakit/PreviewImpl.java +++ b/camerakit/src/main/base/com/flurgle/camerakit/PreviewImpl.java @@ -5,7 +5,7 @@ import android.view.Surface; import android.view.SurfaceHolder; import android.view.View; -public abstract class PreviewImpl { +abstract class PreviewImpl { interface Callback { void onSurfaceChanged(); diff --git a/camerakit/src/main/base/com/flurgle/camerakit/TextureViewPreview.java b/camerakit/src/main/base/com/flurgle/camerakit/TextureViewPreview.java index bca38e64..a0d5e57b 100644 --- a/camerakit/src/main/base/com/flurgle/camerakit/TextureViewPreview.java +++ b/camerakit/src/main/base/com/flurgle/camerakit/TextureViewPreview.java @@ -10,7 +10,7 @@ import android.view.View; import android.view.ViewGroup; @TargetApi(14) -public class TextureViewPreview extends PreviewImpl { +class TextureViewPreview extends PreviewImpl { private final TextureView mTextureView; diff --git a/camerakit/src/main/java/com/flurgle/camerakit/CameraKit.java b/camerakit/src/main/java/com/flurgle/camerakit/CameraKit.java index 16b30b92..c08abbab 100644 --- a/camerakit/src/main/java/com/flurgle/camerakit/CameraKit.java +++ b/camerakit/src/main/java/com/flurgle/camerakit/CameraKit.java @@ -1,7 +1,16 @@ package com.flurgle.camerakit; +import android.content.res.Resources; + public class CameraKit { + static class Internal { + + static final int screenWidth = Resources.getSystem().getDisplayMetrics().widthPixels; + static final int screenHeight = Resources.getSystem().getDisplayMetrics().heightPixels; + + } + public static class Constants { public static final int FACING_BACK = 0; diff --git a/camerakit/src/main/java/com/flurgle/camerakit/CameraView.java b/camerakit/src/main/java/com/flurgle/camerakit/CameraView.java index 7cfc6e53..a749b2a4 100644 --- a/camerakit/src/main/java/com/flurgle/camerakit/CameraView.java +++ b/camerakit/src/main/java/com/flurgle/camerakit/CameraView.java @@ -27,13 +27,13 @@ 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.CAPTURE_MODE_STANDARD; -import static com.flurgle.camerakit.CameraKit.Constants.CAPTURE_MODE_STILL; import static com.flurgle.camerakit.CameraKit.Constants.TAP_TO_FOCUS_VISIBLE; public class CameraView extends FrameLayout { @@ -56,7 +56,7 @@ public class CameraView extends FrameLayout { private boolean mCropOutput; - private boolean mAutoFocus; + private boolean mContinuousFocus; private float mCaptureSize; @@ -80,49 +80,26 @@ public class CameraView extends FrameLayout { public CameraView(@NonNull Context context, @Nullable AttributeSet attrs) { super(context, attrs); + if (attrs != null) { - TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.CameraView); - final int n = a.getIndexCount(); - for (int i = 0; i < n; ++i) { - int attr = a.getIndex(i); - - if (attr == R.styleable.CameraView_ckFacing) { - mFacing = a.getInteger(R.styleable.CameraView_ckFacing, FACING_BACK); - } - - if (attr == R.styleable.CameraView_ckFlash) { - mFlash = a.getInteger(R.styleable.CameraView_ckFlash, FLASH_OFF); - } - - if (attr == R.styleable.CameraView_ckTapToFocus) { - mTapToFocus = a.getInteger(R.styleable.CameraView_ckTapToFocus, TAP_TO_FOCUS_VISIBLE); - } - - if (attr == R.styleable.CameraView_ckCaptureMode) { - mCaptureMode = a.getInteger(R.styleable.CameraView_ckCaptureMode, CAPTURE_MODE_STANDARD); - } - - if (attr == R.styleable.CameraView_ckCropOutput) { - mCropOutput = a.getBoolean(R.styleable.CameraView_ckCropOutput, false); - } - - if (attr == R.styleable.CameraView_ckAutoFocus) { - mAutoFocus = a.getBoolean(R.styleable.CameraView_ckAutoFocus, true); - } - - if (attr == R.styleable.CameraView_ckCaptureSize) { - mCaptureSize = a.getFloat(R.styleable.CameraView_ckCaptureSize, DEFAULT_CAPTURE_SIZE); - } - - if (attr == R.styleable.CameraView_ckJpegCompression) { - mJpegCompression = a.getInteger(R.styleable.CameraView_ckJpegCompression, DEFAULT_JPEG_COMPRESSION); - } - - if (attr == R.styleable.CameraView_android_adjustViewBounds) { - mAdjustViewBounds = a.getBoolean(R.styleable.CameraView_android_adjustViewBounds, false); - } + TypedArray a = context.getTheme().obtainStyledAttributes( + attrs, + R.styleable.CameraView, + 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); + } finally { + a.recycle(); } - a.recycle(); } mCameraListener = new CameraListenerMiddleWare(); @@ -132,10 +109,10 @@ public class CameraView extends FrameLayout { setFacing(mFacing); setFlash(mFlash); - setPictureMode(mCaptureMode); + setCaptureMode(mCaptureMode); setCropOutput(mCropOutput); setTapToFocus(mTapToFocus); - setAutoFocus(mAutoFocus); + setContinuousFocus(mContinuousFocus); setCaptureSize(mCaptureSize); mDisplayOrientationDetector = new DisplayOrientationDetector(context) { @@ -241,12 +218,12 @@ public class CameraView extends FrameLayout { return mFlash; } - public void setPictureMode(@CaptureMode int pictureMode) { - this.mCaptureMode = pictureMode; + public void setCaptureMode(@CaptureMode int captureMode) { + this.mCaptureMode = captureMode; } @CaptureMode - public int getPictureMode() { + public int getCaptureMode() { return mCaptureMode; } @@ -263,8 +240,9 @@ public class CameraView extends FrameLayout { } } - public void setAutoFocus(boolean autoFocus) { - this.mAutoFocus = autoFocus; + public void setContinuousFocus(boolean continuousFocus) { + this.mContinuousFocus = continuousFocus; + mCameraImpl.setContinuousFocus(continuousFocus); } public void setCaptureSize(float captureSize) { diff --git a/camerakit/src/main/res/values/attrs.xml b/camerakit/src/main/res/values/attrs.xml index 62ab920e..c16347e0 100644 --- a/camerakit/src/main/res/values/attrs.xml +++ b/camerakit/src/main/res/values/attrs.xml @@ -22,13 +22,15 @@ + + - + diff --git a/camerakit/src/main/res/values/strings.xml b/camerakit/src/main/res/values/strings.xml deleted file mode 100644 index 252d7984..00000000 --- a/camerakit/src/main/res/values/strings.xml +++ /dev/null @@ -1,3 +0,0 @@ - - CameraKit - diff --git a/camerakit/src/main/utils/com/flurgle/camerakit/CenterCrop.java b/camerakit/src/main/utils/com/flurgle/camerakit/CenterCrop.java index 6b10bf7e..c368d2a2 100644 --- a/camerakit/src/main/utils/com/flurgle/camerakit/CenterCrop.java +++ b/camerakit/src/main/utils/com/flurgle/camerakit/CenterCrop.java @@ -17,7 +17,7 @@ public class CenterCrop { public CenterCrop(YuvImage yuv, AspectRatio targetRatio, int jpegCompression) { Rect crop = getCrop(yuv.getWidth(), yuv.getHeight(), targetRatio); ByteArrayOutputStream out = new ByteArrayOutputStream(); - yuv.compressToJpeg(crop, 100, out); + yuv.compressToJpeg(crop, jpegCompression, out); this.croppedJpeg = out.toByteArray(); } @@ -36,11 +36,10 @@ public class CenterCrop { ).decodeRegion(crop, null); ByteArrayOutputStream out = new ByteArrayOutputStream(); - bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out); + bitmap.compress(Bitmap.CompressFormat.JPEG, jpegCompression, out); this.croppedJpeg = out.toByteArray(); } catch (IOException e) { Log.e("CameraKit", e.toString()); - return; } } diff --git a/camerakit/src/main/utils/com/flurgle/camerakit/YuvUtils.java b/camerakit/src/main/utils/com/flurgle/camerakit/Rotation.java similarity index 56% rename from camerakit/src/main/utils/com/flurgle/camerakit/YuvUtils.java rename to camerakit/src/main/utils/com/flurgle/camerakit/Rotation.java index a41d82ab..4e6ee6e9 100644 --- a/camerakit/src/main/utils/com/flurgle/camerakit/YuvUtils.java +++ b/camerakit/src/main/utils/com/flurgle/camerakit/Rotation.java @@ -1,40 +1,11 @@ package com.flurgle.camerakit; -import android.media.Image; -import android.util.Log; +public class Rotation { -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.nio.ByteBuffer; + private byte[] rotatedYuv; -public class YuvUtils { - - public static byte[] getYUVData(Image image) { - ByteBuffer bufferY = image.getPlanes()[0].getBuffer(); - byte[] y = new byte[bufferY.remaining()]; - bufferY.get(y); - - ByteBuffer bufferU = image.getPlanes()[1].getBuffer(); - byte[] u = new byte[bufferU.remaining()]; - bufferU.get(u); - - ByteBuffer bufferV = image.getPlanes()[2].getBuffer(); - byte[] v = new byte[bufferV.remaining()]; - bufferV.get(v); - - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - try { - outputStream.write(y); - outputStream.write(v); - outputStream.write(u); - } catch (IOException e) { - Log.e("CameraKit", e.toString()); - } - return outputStream.toByteArray(); - } - - public static byte[] rotateNV21(final byte[] yuv, final int width, final int height, final int rotation) { - if (rotation == 0) return yuv; + public Rotation(final byte[] yuv, final int width, final int height, final int rotation) { + if (rotation == 0) this.rotatedYuv = yuv; if (rotation % 90 != 0 || rotation < 0 || rotation > 270) { throw new IllegalArgumentException("0 <= rotation < 360, rotation % 90 == 0"); } @@ -67,7 +38,12 @@ public class YuvUtils { output[vOut] = (byte) (0xff & yuv[vIn]); } } - return output; + + this.rotatedYuv = output; + } + + public byte[] getYuv() { + return this.rotatedYuv; } } 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 3aabf61d..0dabfaf8 100644 --- a/demo/src/main/java/com/flurgle/camerakit/demo/MainActivity.java +++ b/demo/src/main/java/com/flurgle/camerakit/demo/MainActivity.java @@ -191,7 +191,7 @@ public class MainActivity extends AppCompatActivity { RadioGroup.OnCheckedChangeListener captureModeChangedListener = new RadioGroup.OnCheckedChangeListener() { @Override public void onCheckedChanged(RadioGroup group, int checkedId) { - camera.setPictureMode( + camera.setCaptureMode( checkedId == R.id.modeCaptureQuality ? CameraKit.Constants.CAPTURE_MODE_STANDARD : CameraKit.Constants.CAPTURE_MODE_STILL diff --git a/demo/src/main/res/layout/activity_main.xml b/demo/src/main/res/layout/activity_main.xml index a48ee39f..6643a168 100644 --- a/demo/src/main/res/layout/activity_main.xml +++ b/demo/src/main/res/layout/activity_main.xml @@ -18,10 +18,11 @@ android:layout_width="match_parent" 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:ckCaptureMode="standard" app:ckTapToFocus="visible" />