From 782efedc6b3d526d2e874f029be1dee877a981b1 Mon Sep 17 00:00:00 2001 From: Dylan McIntyre Date: Thu, 16 Feb 2017 19:19:44 -0500 Subject: [PATCH] reorganize --- README.md | 13 +- camerakit/build.gradle | 7 + .../com/flurgle/camerakit/Camera1.java | 29 +- .../api21/com/flurgle/camerakit/Camera2.java | 493 ++++++++++++++++++ .../com/flurgle/camerakit/CameraImpl.java | 29 +- .../com/flurgle/camerakit/PreviewImpl.java | 2 - .../flurgle/camerakit/TextureViewPreview.java | 0 .../java/com/flurgle/camerakit/CameraKit.java | 4 +- .../com/flurgle/camerakit/CameraView.java | 74 ++- .../flurgle/camerakit/types/PictureMode.java | 14 - camerakit/src/main/res/values/attrs.xml | 8 +- .../com/flurgle/camerakit/CaptureMode.java | 14 + .../com/flurgle/camerakit}/Facing.java | 2 +- .../com/flurgle/camerakit}/Flash.java | 2 +- .../com/flurgle/camerakit}/TapToFocus.java | 2 +- .../com/flurgle/camerakit}/AspectRatio.java | 2 +- .../com/flurgle/camerakit}/CenterCrop.java | 6 +- .../DisplayOrientationDetector.java | 2 +- .../com/flurgle/camerakit}/Size.java | 2 +- .../com/flurgle/camerakit}/YuvUtils.java | 5 +- .../flurgle/camerakit/demo/MainActivity.java | 4 +- .../camerakit/demo/PreviewActivity.java | 4 +- .../flurgle/camerakit/demo/ResultHolder.java | 2 +- demo/src/main/res/layout/activity_main.xml | 2 +- 24 files changed, 596 insertions(+), 126 deletions(-) rename camerakit/src/main/{java => api16}/com/flurgle/camerakit/Camera1.java (95%) create mode 100644 camerakit/src/main/api21/com/flurgle/camerakit/Camera2.java rename camerakit/src/main/{java => base}/com/flurgle/camerakit/CameraImpl.java (66%) rename camerakit/src/main/{java => base}/com/flurgle/camerakit/PreviewImpl.java (97%) rename camerakit/src/main/{java => base}/com/flurgle/camerakit/TextureViewPreview.java (100%) delete mode 100644 camerakit/src/main/java/com/flurgle/camerakit/types/PictureMode.java create mode 100644 camerakit/src/main/types/com/flurgle/camerakit/CaptureMode.java rename camerakit/src/main/{java/com/flurgle/camerakit/types => types/com/flurgle/camerakit}/Facing.java (90%) rename camerakit/src/main/{java/com/flurgle/camerakit/types => types/com/flurgle/camerakit}/Flash.java (91%) rename camerakit/src/main/{java/com/flurgle/camerakit/types => types/com/flurgle/camerakit}/TapToFocus.java (92%) rename camerakit/src/main/{java/com/flurgle/camerakit/utils => utils/com/flurgle/camerakit}/AspectRatio.java (98%) rename camerakit/src/main/{java/com/flurgle/camerakit/utils => utils/com/flurgle/camerakit}/CenterCrop.java (91%) rename camerakit/src/main/{java/com/flurgle/camerakit/utils => utils/com/flurgle/camerakit}/DisplayOrientationDetector.java (98%) rename camerakit/src/main/{java/com/flurgle/camerakit/utils => utils/com/flurgle/camerakit}/Size.java (96%) rename camerakit/src/main/{java/com/flurgle/camerakit/utils => utils/com/flurgle/camerakit}/YuvUtils.java (96%) diff --git a/README.md b/README.md index 01982535..fd84dafb 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,7 @@ Try out all the unique features using the CameraKit Demo from the Google Play st Get it on Google Play + ## Table of Contents @@ -19,7 +20,7 @@ Try out all the unique features using the CameraKit Demo from the Google Play st - [`ckCropOutput`](#ckcropoutput) - [`ckFacing`](#ckfacing) - [`ckFlash`](#ckflash) - - [`ckPictureMode`](#ckpicturemode) + - [`ckCaptureMode`](#ckcapturemode) - [`ckTapToFocus`](#cktaptofocus) - [`ckAutoFocus`](#ckautofocus) - [`ckCaptureSize`](#ckcapturesize) @@ -125,7 +126,7 @@ camera.setCameraListener(new CameraListener() { camerakit:ckCropOutput="true" camerakit:ckFacing="back" camerakit:ckFlash="off" - camerakit:ckPictureMode="quality" + camerakit:ckCaptureMode="quality" camerakit:ckTapToFocus="on" camerakit:ckAutoFocus="true" camerakit:ckCaptureSize="8" /> @@ -154,13 +155,13 @@ camera.setCameraListener(new CameraListener() { | `on` | Default `CameraView` flash to on. | | `auto` | Default `CameraView` flash to automatic. | -#### `ckPictureMode` +#### `ckCaptureMode` | Value | Description | | --------------| -------------| -| `quality` | Use normal Android Camera API image capturing. | -| `speed` | Freeze the `CameraView` preview and grab a `Bitmap` of the frame. | -| `auto` | Default picture mode to `quality`, but fallback to `speed` if capturing is determined to be too slow. | +| `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. | #### `ckTapToFocus` diff --git a/camerakit/build.gradle b/camerakit/build.gradle index 9b89961e..8f29dda8 100644 --- a/camerakit/build.gradle +++ b/camerakit/build.gradle @@ -22,6 +22,13 @@ android { proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } + sourceSets { + main.java.srcDirs += 'src/main/base' + main.java.srcDirs += 'src/main/api16' + main.java.srcDirs += 'src/main/api21' + main.java.srcDirs += 'src/main/types' + main.java.srcDirs += 'src/main/utils' + } } dependencies { diff --git a/camerakit/src/main/java/com/flurgle/camerakit/Camera1.java b/camerakit/src/main/api16/com/flurgle/camerakit/Camera1.java similarity index 95% rename from camerakit/src/main/java/com/flurgle/camerakit/Camera1.java rename to camerakit/src/main/api16/com/flurgle/camerakit/Camera1.java index c414b9ff..6cb948cc 100644 --- a/camerakit/src/main/java/com/flurgle/camerakit/Camera1.java +++ b/camerakit/src/main/api16/com/flurgle/camerakit/Camera1.java @@ -9,10 +9,6 @@ import android.support.annotation.NonNull; import android.support.v4.util.SparseArrayCompat; import android.view.SurfaceHolder; -import com.flurgle.camerakit.utils.AspectRatio; -import com.flurgle.camerakit.utils.Size; -import com.flurgle.camerakit.utils.YuvUtils; - import java.io.File; import java.io.IOException; import java.util.Iterator; @@ -23,6 +19,7 @@ import java.util.TreeSet; 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); @@ -30,6 +27,7 @@ public class Camera1 extends CameraImpl { } 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); @@ -59,11 +57,11 @@ public class Camera1 extends CameraImpl { 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(getView().getContext().getExternalFilesDir(null), "video.mp4"); + this.mVideoFile = new File(mPreview.getView().getContext().getExternalFilesDir(null), "video.mp4"); preview.setCallback(new PreviewImpl.Callback() { @Override @@ -194,20 +192,11 @@ public class Camera1 extends CameraImpl { } @Override - boolean getAutoFocus() { - if (!isCameraOpened()) { - return mAutoFocus; - } - String focusMode = mCameraParameters.getFocusMode(); - return focusMode != null && focusMode.contains("continuous"); - } - - @Override - void capturePicture() { + void captureStandard() { if (!isCameraOpened()) { throw new IllegalStateException("Camera is not ready. Call start() before takePicture()."); } - if (getAutoFocus()) { + if (mAutoFocus) { mCamera.cancelAutoFocus(); mCamera.autoFocus(new Camera.AutoFocusCallback() { @Override @@ -238,7 +227,7 @@ public class Camera1 extends CameraImpl { new Thread(new ProcessStillTask(data, camera, mCameraInfo, new ProcessStillTask.OnStillProcessedListener() { @Override public void onStillProcessed(final YuvImage yuv) { - getView().post(new Runnable() { + mPreview.getView().post(new Runnable() { @Override public void run() { mCameraListener.onPictureTaken(yuv); @@ -493,12 +482,12 @@ public class Camera1 extends CameraImpl { } @Override - Size getCaptureSize() { + Size getCaptureResolution() { return mCaptureSize; } @Override - Size getPreviewSize() { + Size getPreviewResolution() { return mPreviewSize; } } diff --git a/camerakit/src/main/api21/com/flurgle/camerakit/Camera2.java b/camerakit/src/main/api21/com/flurgle/camerakit/Camera2.java new file mode 100644 index 00000000..69fb49cf --- /dev/null +++ b/camerakit/src/main/api21/com/flurgle/camerakit/Camera2.java @@ -0,0 +1,493 @@ +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.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(); + } + } + }); + } + + @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; + } + + @Override + void setFacing(int facing) { + if (mFacing == facing) { + 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) { + mCameraId = i; + mFacing = facing; + return true; + } + } + + return false; + } + + @Override + void setFlash(int flash) { + if (flash == mFlash) { + return; + } + if (setFlashInternal(flash)) { + mCamera.setParameters(mCameraParameters); + } + } + + 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); + } + } + + 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)); + } + + 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); + } + + @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(); + } + } + + @Override + Size getCaptureResolution() { + return mCaptureSize; + } + + @Override + Size getPreviewResolution() { + return mPreviewSize; + } +} diff --git a/camerakit/src/main/java/com/flurgle/camerakit/CameraImpl.java b/camerakit/src/main/base/com/flurgle/camerakit/CameraImpl.java similarity index 66% rename from camerakit/src/main/java/com/flurgle/camerakit/CameraImpl.java rename to camerakit/src/main/base/com/flurgle/camerakit/CameraImpl.java index 1ee663cd..df04432d 100644 --- a/camerakit/src/main/java/com/flurgle/camerakit/CameraImpl.java +++ b/camerakit/src/main/base/com/flurgle/camerakit/CameraImpl.java @@ -1,11 +1,5 @@ package com.flurgle.camerakit; -import android.view.View; - -import com.flurgle.camerakit.types.Facing; -import com.flurgle.camerakit.types.Flash; -import com.flurgle.camerakit.utils.Size; - public abstract class CameraImpl { protected CameraListener mCameraListener; @@ -16,38 +10,25 @@ public abstract class CameraImpl { mPreview = preview; } - View getView() { - return mPreview.getView(); - } - 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 boolean getAutoFocus(); - - abstract void capturePicture(); + abstract void setDisplayOrientation(int displayOrientation); + abstract void focus(); + abstract void captureStandard(); abstract void captureStill(); abstract void startVideo(); - abstract void endVideo(); - abstract void focus(); - - abstract void setDisplayOrientation(int displayOrientation); - - abstract Size getCaptureSize(); - - abstract Size getPreviewSize(); + abstract Size getCaptureResolution(); + abstract Size getPreviewResolution(); } diff --git a/camerakit/src/main/java/com/flurgle/camerakit/PreviewImpl.java b/camerakit/src/main/base/com/flurgle/camerakit/PreviewImpl.java similarity index 97% rename from camerakit/src/main/java/com/flurgle/camerakit/PreviewImpl.java rename to camerakit/src/main/base/com/flurgle/camerakit/PreviewImpl.java index 67902178..3850416f 100644 --- a/camerakit/src/main/java/com/flurgle/camerakit/PreviewImpl.java +++ b/camerakit/src/main/base/com/flurgle/camerakit/PreviewImpl.java @@ -5,8 +5,6 @@ import android.view.Surface; import android.view.SurfaceHolder; import android.view.View; -import com.flurgle.camerakit.utils.AspectRatio; - public abstract class PreviewImpl { interface Callback { diff --git a/camerakit/src/main/java/com/flurgle/camerakit/TextureViewPreview.java b/camerakit/src/main/base/com/flurgle/camerakit/TextureViewPreview.java similarity index 100% rename from camerakit/src/main/java/com/flurgle/camerakit/TextureViewPreview.java rename to camerakit/src/main/base/com/flurgle/camerakit/TextureViewPreview.java diff --git a/camerakit/src/main/java/com/flurgle/camerakit/CameraKit.java b/camerakit/src/main/java/com/flurgle/camerakit/CameraKit.java index aa805f59..16b30b92 100644 --- a/camerakit/src/main/java/com/flurgle/camerakit/CameraKit.java +++ b/camerakit/src/main/java/com/flurgle/camerakit/CameraKit.java @@ -11,8 +11,8 @@ public class CameraKit { 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 CAPTURE_MODE_STANDARD = 0; + public static final int CAPTURE_MODE_STILL = 1; public static final int PICTURE_MODE_AUTO = 2; public static final int TAP_TO_FOCUS_VISIBLE = 0; diff --git a/camerakit/src/main/java/com/flurgle/camerakit/CameraView.java b/camerakit/src/main/java/com/flurgle/camerakit/CameraView.java index 34f6446f..7cfc6e53 100644 --- a/camerakit/src/main/java/com/flurgle/camerakit/CameraView.java +++ b/camerakit/src/main/java/com/flurgle/camerakit/CameraView.java @@ -24,15 +24,6 @@ import android.view.MotionEvent; import android.view.View; import android.widget.FrameLayout; -import com.flurgle.camerakit.types.Facing; -import com.flurgle.camerakit.types.Flash; -import com.flurgle.camerakit.types.PictureMode; -import com.flurgle.camerakit.types.TapToFocus; -import com.flurgle.camerakit.utils.AspectRatio; -import com.flurgle.camerakit.utils.CenterCrop; -import com.flurgle.camerakit.utils.DisplayOrientationDetector; -import com.flurgle.camerakit.utils.Size; - import java.io.ByteArrayOutputStream; import java.io.File; @@ -41,14 +32,15 @@ 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.PICTURE_MODE_QUALITY; -import static com.flurgle.camerakit.CameraKit.Constants.PICTURE_MODE_SPEED; +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 { 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; @@ -56,18 +48,20 @@ public class CameraView extends FrameLayout { @Flash private int mFlash; - @PictureMode - private int mPictureMode; - - private boolean mCropOutput; - @TapToFocus private int mTapToFocus; + @CaptureMode + private int mCaptureMode; + + private boolean mCropOutput; + private boolean mAutoFocus; private float mCaptureSize; + private int mJpegCompression; + private boolean mAdjustViewBounds; private boolean mWaitingForPermission; @@ -100,18 +94,18 @@ public class CameraView extends FrameLayout { mFlash = a.getInteger(R.styleable.CameraView_ckFlash, FLASH_OFF); } - if (attr == R.styleable.CameraView_ckPictureMode) { - mPictureMode = a.getInteger(R.styleable.CameraView_ckPictureMode, PICTURE_MODE_QUALITY); + 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_ckTapToFocus) { - mTapToFocus = a.getInteger(R.styleable.CameraView_ckTapToFocus, TAP_TO_FOCUS_VISIBLE); - } - if (attr == R.styleable.CameraView_ckAutoFocus) { mAutoFocus = a.getBoolean(R.styleable.CameraView_ckAutoFocus, true); } @@ -120,6 +114,10 @@ public class CameraView extends FrameLayout { 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); } @@ -134,7 +132,7 @@ public class CameraView extends FrameLayout { setFacing(mFacing); setFlash(mFlash); - setPictureMode(mPictureMode); + setPictureMode(mCaptureMode); setCropOutput(mCropOutput); setTapToFocus(mTapToFocus); setAutoFocus(mAutoFocus); @@ -243,13 +241,13 @@ public class CameraView extends FrameLayout { return mFlash; } - public void setPictureMode(@PictureMode int pictureMode) { - this.mPictureMode = pictureMode; + public void setPictureMode(@CaptureMode int pictureMode) { + this.mCaptureMode = pictureMode; } - @PictureMode + @CaptureMode public int getPictureMode() { - return mPictureMode; + return mCaptureMode; } public void setCropOutput(boolean cropOutput) { @@ -278,11 +276,11 @@ public class CameraView extends FrameLayout { } public void capturePicture() { - switch (mPictureMode) { - case PICTURE_MODE_QUALITY: - mCameraImpl.capturePicture(); + switch (mCaptureMode) { + case CAPTURE_MODE_STANDARD: + mCameraImpl.captureStandard(); break; - case PICTURE_MODE_SPEED: + case CAPTURE_MODE_STILL: mCameraImpl.captureStill(); break; } @@ -297,11 +295,11 @@ public class CameraView extends FrameLayout { } public Size getPreviewSize() { - return mCameraImpl != null ? mCameraImpl.getPreviewSize() : null; + return mCameraImpl != null ? mCameraImpl.getPreviewResolution() : null; } public Size getCaptureSize() { - return mCameraImpl != null ? mCameraImpl.getCaptureSize() : null; + return mCameraImpl != null ? mCameraImpl.getCaptureResolution() : null; } private void requestCameraPermission() { @@ -405,10 +403,10 @@ public class CameraView extends FrameLayout { public void onPictureTaken(byte[] jpeg) { super.onPictureTaken(jpeg); if (mCropOutput) { - int width = mPictureMode == PICTURE_MODE_QUALITY ? mCameraImpl.getCaptureSize().getWidth() : mCameraImpl.getPreviewSize().getWidth(); - int height = mPictureMode == PICTURE_MODE_QUALITY ? mCameraImpl.getCaptureSize().getHeight() : mCameraImpl.getPreviewSize().getHeight(); + int width = mCaptureMode == CAPTURE_MODE_STANDARD ? mCameraImpl.getCaptureResolution().getWidth() : mCameraImpl.getPreviewResolution().getWidth(); + int height = mCaptureMode == CAPTURE_MODE_STANDARD ? mCameraImpl.getCaptureResolution().getHeight() : mCameraImpl.getPreviewResolution().getHeight(); AspectRatio outputRatio = AspectRatio.of(getWidth(), getHeight()); - getCameraListener().onPictureTaken(new CenterCrop(jpeg, outputRatio).getJpeg()); + getCameraListener().onPictureTaken(new CenterCrop(jpeg, outputRatio, mJpegCompression).getJpeg()); } else { getCameraListener().onPictureTaken(jpeg); } @@ -419,10 +417,10 @@ public class CameraView extends FrameLayout { super.onPictureTaken(yuv); if (mCropOutput) { AspectRatio outputRatio = AspectRatio.of(getWidth(), getHeight()); - getCameraListener().onPictureTaken(new CenterCrop(yuv, outputRatio).getJpeg()); + getCameraListener().onPictureTaken(new CenterCrop(yuv, outputRatio, mJpegCompression).getJpeg()); } else { ByteArrayOutputStream out = new ByteArrayOutputStream(); - yuv.compressToJpeg(new Rect(0, 0, yuv.getWidth(), yuv.getHeight()), 50, out); + yuv.compressToJpeg(new Rect(0, 0, yuv.getWidth(), yuv.getHeight()), mJpegCompression, out); getCameraListener().onPictureTaken(out.toByteArray()); } } diff --git a/camerakit/src/main/java/com/flurgle/camerakit/types/PictureMode.java b/camerakit/src/main/java/com/flurgle/camerakit/types/PictureMode.java deleted file mode 100644 index 7317e096..00000000 --- a/camerakit/src/main/java/com/flurgle/camerakit/types/PictureMode.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.flurgle.camerakit.types; - -import android.support.annotation.IntDef; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -import static com.flurgle.camerakit.CameraKit.Constants.PICTURE_MODE_QUALITY; -import static com.flurgle.camerakit.CameraKit.Constants.PICTURE_MODE_SPEED; - -@Retention(RetentionPolicy.SOURCE) -@IntDef({PICTURE_MODE_QUALITY, PICTURE_MODE_SPEED}) -public @interface PictureMode { -} diff --git a/camerakit/src/main/res/values/attrs.xml b/camerakit/src/main/res/values/attrs.xml index 62d49bce..62ab920e 100644 --- a/camerakit/src/main/res/values/attrs.xml +++ b/camerakit/src/main/res/values/attrs.xml @@ -14,9 +14,9 @@ - - - + + + @@ -32,6 +32,8 @@ + + diff --git a/camerakit/src/main/types/com/flurgle/camerakit/CaptureMode.java b/camerakit/src/main/types/com/flurgle/camerakit/CaptureMode.java new file mode 100644 index 00000000..a6e923c2 --- /dev/null +++ b/camerakit/src/main/types/com/flurgle/camerakit/CaptureMode.java @@ -0,0 +1,14 @@ +package com.flurgle.camerakit; + +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; + +@Retention(RetentionPolicy.SOURCE) +@IntDef({CAPTURE_MODE_STANDARD, CAPTURE_MODE_STILL}) +public @interface CaptureMode { +} diff --git a/camerakit/src/main/java/com/flurgle/camerakit/types/Facing.java b/camerakit/src/main/types/com/flurgle/camerakit/Facing.java similarity index 90% rename from camerakit/src/main/java/com/flurgle/camerakit/types/Facing.java rename to camerakit/src/main/types/com/flurgle/camerakit/Facing.java index 690f9536..15a555f7 100644 --- a/camerakit/src/main/java/com/flurgle/camerakit/types/Facing.java +++ b/camerakit/src/main/types/com/flurgle/camerakit/Facing.java @@ -1,4 +1,4 @@ -package com.flurgle.camerakit.types; +package com.flurgle.camerakit; import android.support.annotation.IntDef; diff --git a/camerakit/src/main/java/com/flurgle/camerakit/types/Flash.java b/camerakit/src/main/types/com/flurgle/camerakit/Flash.java similarity index 91% rename from camerakit/src/main/java/com/flurgle/camerakit/types/Flash.java rename to camerakit/src/main/types/com/flurgle/camerakit/Flash.java index a65dee85..08055486 100644 --- a/camerakit/src/main/java/com/flurgle/camerakit/types/Flash.java +++ b/camerakit/src/main/types/com/flurgle/camerakit/Flash.java @@ -1,4 +1,4 @@ -package com.flurgle.camerakit.types; +package com.flurgle.camerakit; import android.support.annotation.IntDef; diff --git a/camerakit/src/main/java/com/flurgle/camerakit/types/TapToFocus.java b/camerakit/src/main/types/com/flurgle/camerakit/TapToFocus.java similarity index 92% rename from camerakit/src/main/java/com/flurgle/camerakit/types/TapToFocus.java rename to camerakit/src/main/types/com/flurgle/camerakit/TapToFocus.java index 10920134..9e6860d4 100644 --- a/camerakit/src/main/java/com/flurgle/camerakit/types/TapToFocus.java +++ b/camerakit/src/main/types/com/flurgle/camerakit/TapToFocus.java @@ -1,4 +1,4 @@ -package com.flurgle.camerakit.types; +package com.flurgle.camerakit; import android.support.annotation.IntDef; diff --git a/camerakit/src/main/java/com/flurgle/camerakit/utils/AspectRatio.java b/camerakit/src/main/utils/com/flurgle/camerakit/AspectRatio.java similarity index 98% rename from camerakit/src/main/java/com/flurgle/camerakit/utils/AspectRatio.java rename to camerakit/src/main/utils/com/flurgle/camerakit/AspectRatio.java index e425f318..2f153510 100644 --- a/camerakit/src/main/java/com/flurgle/camerakit/utils/AspectRatio.java +++ b/camerakit/src/main/utils/com/flurgle/camerakit/AspectRatio.java @@ -1,4 +1,4 @@ -package com.flurgle.camerakit.utils; +package com.flurgle.camerakit; import android.os.Parcel; import android.os.Parcelable; diff --git a/camerakit/src/main/java/com/flurgle/camerakit/utils/CenterCrop.java b/camerakit/src/main/utils/com/flurgle/camerakit/CenterCrop.java similarity index 91% rename from camerakit/src/main/java/com/flurgle/camerakit/utils/CenterCrop.java rename to camerakit/src/main/utils/com/flurgle/camerakit/CenterCrop.java index e7a88fd3..6b10bf7e 100644 --- a/camerakit/src/main/java/com/flurgle/camerakit/utils/CenterCrop.java +++ b/camerakit/src/main/utils/com/flurgle/camerakit/CenterCrop.java @@ -1,4 +1,4 @@ -package com.flurgle.camerakit.utils; +package com.flurgle.camerakit; import android.graphics.Bitmap; import android.graphics.BitmapFactory; @@ -14,14 +14,14 @@ public class CenterCrop { private byte[] croppedJpeg; - public CenterCrop(YuvImage yuv, AspectRatio targetRatio) { + 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); this.croppedJpeg = out.toByteArray(); } - public CenterCrop(byte[] jpeg, AspectRatio targetRatio) { + public CenterCrop(byte[] jpeg, AspectRatio targetRatio, int jpegCompression) { BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeByteArray(jpeg, 0, jpeg.length, options); diff --git a/camerakit/src/main/java/com/flurgle/camerakit/utils/DisplayOrientationDetector.java b/camerakit/src/main/utils/com/flurgle/camerakit/DisplayOrientationDetector.java similarity index 98% rename from camerakit/src/main/java/com/flurgle/camerakit/utils/DisplayOrientationDetector.java rename to camerakit/src/main/utils/com/flurgle/camerakit/DisplayOrientationDetector.java index e21054ac..28caef8a 100644 --- a/camerakit/src/main/java/com/flurgle/camerakit/utils/DisplayOrientationDetector.java +++ b/camerakit/src/main/utils/com/flurgle/camerakit/DisplayOrientationDetector.java @@ -1,4 +1,4 @@ -package com.flurgle.camerakit.utils; +package com.flurgle.camerakit; import android.content.Context; import android.util.SparseIntArray; diff --git a/camerakit/src/main/java/com/flurgle/camerakit/utils/Size.java b/camerakit/src/main/utils/com/flurgle/camerakit/Size.java similarity index 96% rename from camerakit/src/main/java/com/flurgle/camerakit/utils/Size.java rename to camerakit/src/main/utils/com/flurgle/camerakit/Size.java index 1fc108ac..08e54a8f 100644 --- a/camerakit/src/main/java/com/flurgle/camerakit/utils/Size.java +++ b/camerakit/src/main/utils/com/flurgle/camerakit/Size.java @@ -1,4 +1,4 @@ -package com.flurgle.camerakit.utils; +package com.flurgle.camerakit; import android.support.annotation.NonNull; diff --git a/camerakit/src/main/java/com/flurgle/camerakit/utils/YuvUtils.java b/camerakit/src/main/utils/com/flurgle/camerakit/YuvUtils.java similarity index 96% rename from camerakit/src/main/java/com/flurgle/camerakit/utils/YuvUtils.java rename to camerakit/src/main/utils/com/flurgle/camerakit/YuvUtils.java index ef7251f9..a41d82ab 100644 --- a/camerakit/src/main/java/com/flurgle/camerakit/utils/YuvUtils.java +++ b/camerakit/src/main/utils/com/flurgle/camerakit/YuvUtils.java @@ -1,6 +1,7 @@ -package com.flurgle.camerakit.utils; +package com.flurgle.camerakit; import android.media.Image; +import android.util.Log; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -27,7 +28,7 @@ public class YuvUtils { outputStream.write(v); outputStream.write(u); } catch (IOException e) { - + Log.e("CameraKit", e.toString()); } return outputStream.toByteArray(); } 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 a586b1e7..3aabf61d 100644 --- a/demo/src/main/java/com/flurgle/camerakit/demo/MainActivity.java +++ b/demo/src/main/java/com/flurgle/camerakit/demo/MainActivity.java @@ -193,8 +193,8 @@ public class MainActivity extends AppCompatActivity { public void onCheckedChanged(RadioGroup group, int checkedId) { camera.setPictureMode( checkedId == R.id.modeCaptureQuality ? - CameraKit.Constants.PICTURE_MODE_QUALITY : - CameraKit.Constants.PICTURE_MODE_SPEED + CameraKit.Constants.CAPTURE_MODE_STANDARD : + CameraKit.Constants.CAPTURE_MODE_STILL ); Toast.makeText(MainActivity.this, "Picture capture set to" + (checkedId == R.id.modeCaptureQuality ? " quality!" : " speed!"), Toast.LENGTH_SHORT).show(); diff --git a/demo/src/main/java/com/flurgle/camerakit/demo/PreviewActivity.java b/demo/src/main/java/com/flurgle/camerakit/demo/PreviewActivity.java index f61368d3..996d3741 100644 --- a/demo/src/main/java/com/flurgle/camerakit/demo/PreviewActivity.java +++ b/demo/src/main/java/com/flurgle/camerakit/demo/PreviewActivity.java @@ -7,8 +7,8 @@ import android.support.annotation.Nullable; import android.widget.ImageView; import android.widget.TextView; -import com.flurgle.camerakit.utils.AspectRatio; -import com.flurgle.camerakit.utils.Size; +import com.flurgle.camerakit.AspectRatio; +import com.flurgle.camerakit.Size; import butterknife.BindView; import butterknife.ButterKnife; diff --git a/demo/src/main/java/com/flurgle/camerakit/demo/ResultHolder.java b/demo/src/main/java/com/flurgle/camerakit/demo/ResultHolder.java index 46be0ad9..2679785e 100644 --- a/demo/src/main/java/com/flurgle/camerakit/demo/ResultHolder.java +++ b/demo/src/main/java/com/flurgle/camerakit/demo/ResultHolder.java @@ -3,7 +3,7 @@ package com.flurgle.camerakit.demo; import android.graphics.Bitmap; import android.support.annotation.Nullable; -import com.flurgle.camerakit.utils.Size; +import com.flurgle.camerakit.Size; import java.lang.ref.WeakReference; diff --git a/demo/src/main/res/layout/activity_main.xml b/demo/src/main/res/layout/activity_main.xml index b1822ebf..a48ee39f 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="false" app:ckFacing="back" app:ckFlash="off" - app:ckPictureMode="quality" + app:ckCaptureMode="standard" app:ckTapToFocus="visible" />