diff --git a/android-core/pom.xml b/android-core/pom.xml
new file mode 100644
index 000000000..4776d540c
--- /dev/null
+++ b/android-core/pom.xml
@@ -0,0 +1,40 @@
+
+
+
+ 4.0.0
+
+ android-core
+ 3.0.2-SNAPSHOT
+ jar
+
+
+
+ com.google.android
+ android
+
+
+
+
+ com.google.zxing
+ zxing-parent
+ 3.0.2-SNAPSHOT
+
+
+ ZXing Android Core
+ Code common to Android applications
+
+
diff --git a/android-core/src/main/java/com/google/zxing/client/android/camera/CameraConfigurationUtils.java b/android-core/src/main/java/com/google/zxing/client/android/camera/CameraConfigurationUtils.java
new file mode 100644
index 000000000..4fd44f6cf
--- /dev/null
+++ b/android-core/src/main/java/com/google/zxing/client/android/camera/CameraConfigurationUtils.java
@@ -0,0 +1,383 @@
+/*
+ * Copyright (C) 2014 ZXing authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.zxing.client.android.camera;
+
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.hardware.Camera;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Utility methods for configuring the Android camera.
+ *
+ * @author Sean Owen
+ */
+public final class CameraConfigurationUtils {
+
+ private static final String TAG = "CameraConfiguration";
+
+ private static final int MIN_PREVIEW_PIXELS = 480 * 320; // normal screen
+ private static final float MAX_EXPOSURE_COMPENSATION = 1.5f;
+ private static final float MIN_EXPOSURE_COMPENSATION = 0.0f;
+ private static final double MAX_ASPECT_DISTORTION = 0.15;
+ private static final int MIN_FPS = 10;
+ private static final int AREA_PER_1000 = 400;
+
+ private CameraConfigurationUtils() {
+ }
+
+ public static void setFocus(Camera.Parameters parameters,
+ boolean autoFocus,
+ boolean disableContinuous,
+ boolean safeMode) {
+ List supportedFocusModes = parameters.getSupportedFocusModes();
+ String focusMode = null;
+ if (autoFocus) {
+ if (safeMode || disableContinuous) {
+ focusMode = CameraConfigurationUtils.findSettableValue("focus mode",
+ supportedFocusModes,
+ Camera.Parameters.FOCUS_MODE_AUTO);
+ } else {
+ focusMode = CameraConfigurationUtils.findSettableValue("focus mode",
+ supportedFocusModes,
+ Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE,
+ Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO,
+ Camera.Parameters.FOCUS_MODE_AUTO);
+ }
+ }
+ // Maybe selected auto-focus but not available, so fall through here:
+ if (!safeMode && focusMode == null) {
+ focusMode = CameraConfigurationUtils.findSettableValue("focus mode",
+ supportedFocusModes,
+ Camera.Parameters.FOCUS_MODE_MACRO,
+ Camera.Parameters.FOCUS_MODE_EDOF);
+ }
+ if (focusMode != null) {
+ if (focusMode.equals(parameters.getFocusMode())) {
+ Log.i(TAG, "Focus mode already set to " + focusMode);
+ } else {
+ parameters.setFocusMode(focusMode);
+ }
+ }
+ }
+
+ public static void setTorch(Camera.Parameters parameters, boolean on) {
+ List supportedFlashModes = parameters.getSupportedFlashModes();
+ String flashMode;
+ if (on) {
+ flashMode = CameraConfigurationUtils.findSettableValue("flash mode",
+ supportedFlashModes,
+ Camera.Parameters.FLASH_MODE_TORCH,
+ Camera.Parameters.FLASH_MODE_ON);
+ } else {
+ flashMode = CameraConfigurationUtils.findSettableValue("flash mode",
+ supportedFlashModes,
+ Camera.Parameters.FLASH_MODE_OFF);
+ }
+ if (flashMode != null) {
+ if (flashMode.equals(parameters.getFlashMode())) {
+ Log.i(TAG, "Flash mode already set to " + flashMode);
+ } else {
+ Log.i(TAG, "Setting flash mode to " + flashMode);
+ parameters.setFlashMode(flashMode);
+ }
+ }
+ }
+
+ public static void setBestExposure(Camera.Parameters parameters, boolean lightOn) {
+ int minExposure = parameters.getMinExposureCompensation();
+ int maxExposure = parameters.getMaxExposureCompensation();
+ float step = parameters.getExposureCompensationStep();
+ if ((minExposure != 0 || maxExposure != 0) && step > 0.0f) {
+ // Set low when light is on
+ float targetCompensation = lightOn ? MIN_EXPOSURE_COMPENSATION : MAX_EXPOSURE_COMPENSATION;
+ int compensationSteps = Math.round(targetCompensation / step);
+ float actualCompensation = step * compensationSteps;
+ // Clamp value:
+ compensationSteps = Math.max(Math.min(compensationSteps, maxExposure), minExposure);
+ if (parameters.getExposureCompensation() == compensationSteps) {
+ Log.i(TAG, "Exposure compensation already set to " + compensationSteps + " / " + actualCompensation);
+ } else {
+ Log.i(TAG, "Setting exposure compensation to " + compensationSteps + " / " + actualCompensation);
+ parameters.setExposureCompensation(compensationSteps);
+ }
+ } else {
+ Log.i(TAG, "Camera does not support exposure compensation");
+ }
+ }
+
+ public static void setBestPreviewFPS(Camera.Parameters parameters) {
+ setBestPreviewFPS(parameters, MIN_FPS);
+ }
+
+ public static void setBestPreviewFPS(Camera.Parameters parameters, int minFPS) {
+ List supportedPreviewFpsRanges = parameters.getSupportedPreviewFpsRange();
+ Log.i(TAG, "Supported FPS ranges: " + toString(supportedPreviewFpsRanges));
+ if (supportedPreviewFpsRanges != null && !supportedPreviewFpsRanges.isEmpty()) {
+ int[] minimumSuitableFpsRange = null;
+ for (int[] fpsRange : supportedPreviewFpsRanges) {
+ int fpsMax = fpsRange[Camera.Parameters.PREVIEW_FPS_MAX_INDEX];
+ if (fpsMax >= minFPS * 1000 &&
+ (minimumSuitableFpsRange == null ||
+ fpsMax > minimumSuitableFpsRange[Camera.Parameters.PREVIEW_FPS_MAX_INDEX])) {
+ minimumSuitableFpsRange = fpsRange;
+ }
+ }
+ if (minimumSuitableFpsRange == null) {
+ Log.i(TAG, "No suitable FPS range?");
+ } else {
+ int[] currentFpsRange = new int[2];
+ parameters.getPreviewFpsRange(currentFpsRange);
+ if (Arrays.equals(currentFpsRange, minimumSuitableFpsRange)) {
+ Log.i(TAG, "FPS range already set to " + Arrays.toString(minimumSuitableFpsRange));
+ } else {
+ Log.i(TAG, "Setting FPS range to " + Arrays.toString(minimumSuitableFpsRange));
+ parameters.setPreviewFpsRange(minimumSuitableFpsRange[Camera.Parameters.PREVIEW_FPS_MIN_INDEX],
+ minimumSuitableFpsRange[Camera.Parameters.PREVIEW_FPS_MAX_INDEX]);
+ }
+ }
+ }
+ }
+
+ public static void setFocusArea(Camera.Parameters parameters) {
+ if (parameters.getMaxNumFocusAreas() > 0) {
+ Log.i(TAG, "Old focus areas: " + toString(parameters.getFocusAreas()));
+ List middleArea = buildMiddleArea(AREA_PER_1000);
+ Log.i(TAG, "Setting focus area to : " + toString(middleArea));
+ parameters.setFocusAreas(middleArea);
+ } else {
+ Log.i(TAG, "Device does not support focus areas");
+ }
+ }
+
+ public static void setMetering(Camera.Parameters parameters) {
+ if (parameters.getMaxNumMeteringAreas() > 0) {
+ Log.i(TAG, "Old metering areas: " + parameters.getMeteringAreas());
+ List middleArea = buildMiddleArea(AREA_PER_1000);
+ Log.i(TAG, "Setting metering area to : " + toString(middleArea));
+ parameters.setMeteringAreas(middleArea);
+ } else {
+ Log.i(TAG, "Device does not support metering areas");
+ }
+ }
+
+ private static List buildMiddleArea(int areaPer1000) {
+ return Collections.singletonList(
+ new Camera.Area(new Rect(-areaPer1000, -areaPer1000, areaPer1000, areaPer1000), 1));
+ }
+
+ public static void setVideoStabilization(Camera.Parameters parameters) {
+ if (parameters.isVideoStabilizationSupported()) {
+ if (parameters.getVideoStabilization()) {
+ Log.i(TAG, "Video stabilization already enabled");
+ } else {
+ Log.i(TAG, "Enabling video stabilization...");
+ parameters.setVideoStabilization(true);
+ }
+ } else {
+ Log.i(TAG, "This device does not support video stabilization");
+ }
+ }
+
+ public static void setBarcodeSceneMode(Camera.Parameters parameters) {
+ if (Camera.Parameters.SCENE_MODE_BARCODE.equals(parameters.getSceneMode())) {
+ Log.i(TAG, "Barcode scene mode already set");
+ return;
+ }
+ String sceneMode = findSettableValue("scene mode",
+ parameters.getSupportedSceneModes(),
+ Camera.Parameters.SCENE_MODE_BARCODE);
+ if (sceneMode != null) {
+ parameters.setSceneMode(sceneMode);
+ }
+ }
+
+ public static void setMaxZoom(Camera.Parameters parameters) {
+ int maxZoom = parameters.getMaxZoom();
+ Log.i(TAG, "Setting zoom to max of " + maxZoom);
+ setZoom(parameters, maxZoom);
+ }
+
+ public static void setZoom(Camera.Parameters parameters, int zoom) {
+ if (parameters.isZoomSupported()) {
+ if (parameters.getZoom() == zoom) {
+ Log.i(TAG, "Zoom is already set to " + zoom);
+ } else {
+ Log.i(TAG, "Setting zoom to " + zoom);
+ parameters.setZoom(zoom);
+ }
+ } else {
+ Log.i(TAG, "Zoom is not supported");
+ }
+ }
+
+ public static void setInvertColor(Camera.Parameters parameters) {
+ if (Camera.Parameters.EFFECT_NEGATIVE.equals(parameters.getColorEffect())) {
+ Log.i(TAG, "Negative effect already set");
+ return;
+ }
+ String colorMode =
+ CameraConfigurationUtils.findSettableValue("color effect",
+ parameters.getSupportedColorEffects(),
+ Camera.Parameters.EFFECT_NEGATIVE);
+ if (colorMode != null) {
+ parameters.setColorEffect(colorMode);
+ }
+ }
+
+ public static Point findBestPreviewSizeValue(Camera.Parameters parameters, Point screenResolution) {
+
+ List rawSupportedSizes = parameters.getSupportedPreviewSizes();
+ if (rawSupportedSizes == null) {
+ Log.w(TAG, "Device returned no supported preview sizes; using default");
+ Camera.Size defaultSize = parameters.getPreviewSize();
+ if (defaultSize == null) {
+ throw new IllegalStateException("Parameters contained no preview size!");
+ }
+ return new Point(defaultSize.width, defaultSize.height);
+ }
+
+ // Sort by size, descending
+ List supportedPreviewSizes = new ArrayList<>(rawSupportedSizes);
+ Collections.sort(supportedPreviewSizes, new Comparator() {
+ @Override
+ public int compare(Camera.Size a, Camera.Size b) {
+ int aPixels = a.height * a.width;
+ int bPixels = b.height * b.width;
+ if (bPixels < aPixels) {
+ return -1;
+ }
+ if (bPixels > aPixels) {
+ return 1;
+ }
+ return 0;
+ }
+ });
+
+ if (Log.isLoggable(TAG, Log.INFO)) {
+ StringBuilder previewSizesString = new StringBuilder();
+ for (Camera.Size supportedPreviewSize : supportedPreviewSizes) {
+ previewSizesString.append(supportedPreviewSize.width).append('x')
+ .append(supportedPreviewSize.height).append(' ');
+ }
+ Log.i(TAG, "Supported preview sizes: " + previewSizesString);
+ }
+
+ double screenAspectRatio = (double) screenResolution.x / (double) screenResolution.y;
+
+ // Remove sizes that are unsuitable
+ Iterator it = supportedPreviewSizes.iterator();
+ while (it.hasNext()) {
+ Camera.Size supportedPreviewSize = it.next();
+ int realWidth = supportedPreviewSize.width;
+ int realHeight = supportedPreviewSize.height;
+ if (realWidth * realHeight < MIN_PREVIEW_PIXELS) {
+ it.remove();
+ continue;
+ }
+
+ boolean isCandidatePortrait = realWidth < realHeight;
+ int maybeFlippedWidth = isCandidatePortrait ? realHeight : realWidth;
+ int maybeFlippedHeight = isCandidatePortrait ? realWidth : realHeight;
+ double aspectRatio = (double) maybeFlippedWidth / (double) maybeFlippedHeight;
+ double distortion = Math.abs(aspectRatio - screenAspectRatio);
+ if (distortion > MAX_ASPECT_DISTORTION) {
+ it.remove();
+ continue;
+ }
+
+ if (maybeFlippedWidth == screenResolution.x && maybeFlippedHeight == screenResolution.y) {
+ Point exactPoint = new Point(realWidth, realHeight);
+ Log.i(TAG, "Found preview size exactly matching screen size: " + exactPoint);
+ return exactPoint;
+ }
+ }
+
+ // If no exact match, use largest preview size. This was not a great idea on older devices because
+ // of the additional computation needed. We're likely to get here on newer Android 4+ devices, where
+ // the CPU is much more powerful.
+ if (!supportedPreviewSizes.isEmpty()) {
+ Camera.Size largestPreview = supportedPreviewSizes.get(0);
+ Point largestSize = new Point(largestPreview.width, largestPreview.height);
+ Log.i(TAG, "Using largest suitable preview size: " + largestSize);
+ return largestSize;
+ }
+
+ // If there is nothing at all suitable, return current preview size
+ Camera.Size defaultPreview = parameters.getPreviewSize();
+ if (defaultPreview == null) {
+ throw new IllegalStateException("Parameters contained no preview size!");
+ }
+ Point defaultSize = new Point(defaultPreview.width, defaultPreview.height);
+ Log.i(TAG, "No suitable preview sizes, using default: " + defaultSize);
+ return defaultSize;
+ }
+
+ private static String findSettableValue(String name,
+ Collection supportedValues,
+ String... desiredValues) {
+ Log.i(TAG, "Requesting " + name + " value from among: " + Arrays.toString(desiredValues));
+ Log.i(TAG, "Supported " + name + " values: " + supportedValues);
+ if (supportedValues != null) {
+ for (String desiredValue : desiredValues) {
+ if (supportedValues.contains(desiredValue)) {
+ Log.i(TAG, "Can set " + name + " to: " + desiredValue);
+ return desiredValue;
+ }
+ }
+ }
+ Log.i(TAG, "No supported values match");
+ return null;
+ }
+
+ private static String toString(Collection arrays) {
+ if (arrays == null || arrays.isEmpty()) {
+ return "[]";
+ }
+ StringBuilder buffer = new StringBuilder();
+ buffer.append('[');
+ Iterator it = arrays.iterator();
+ while (it.hasNext()) {
+ buffer.append(Arrays.toString(it.next()));
+ if (it.hasNext()) {
+ buffer.append(", ");
+ }
+ }
+ buffer.append(']');
+ return buffer.toString();
+ }
+
+ private static String toString(Iterable areas) {
+ if (areas == null) {
+ return null;
+ }
+ StringBuilder result = new StringBuilder();
+ for (Camera.Area area : areas) {
+ result.append(area.rect).append(':').append(area.weight).append(' ');
+ }
+ return result.toString();
+ }
+
+}
diff --git a/android/pom.xml b/android/pom.xml
index 51b019777..3b3a338ef 100644
--- a/android/pom.xml
+++ b/android/pom.xml
@@ -27,6 +27,11 @@
core
${project.parent.version}
+
+ com.google.zxing
+ android-core
+ ${project.parent.version}
+
com.google.android
android
diff --git a/android/src/com/google/zxing/client/android/camera/CameraConfigurationManager.java b/android/src/com/google/zxing/client/android/camera/CameraConfigurationManager.java
index c3bb3c4d3..24bd4e8fa 100644
--- a/android/src/com/google/zxing/client/android/camera/CameraConfigurationManager.java
+++ b/android/src/com/google/zxing/client/android/camera/CameraConfigurationManager.java
@@ -26,15 +26,6 @@ import android.view.Display;
import android.view.WindowManager;
import com.google.zxing.client.android.PreferencesActivity;
-import com.google.zxing.client.android.camera.metering.MeteringInterface;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Iterator;
-import java.util.List;
/**
* A class which deals with reading, parsing, and setting the camera parameters which are used to
@@ -44,15 +35,6 @@ final class CameraConfigurationManager {
private static final String TAG = "CameraConfiguration";
- // This is bigger than the size of a small screen, which is still supported. The routine
- // below will still select the default (presumably 320x240) size for these. This prevents
- // accidental selection of very low resolution on some devices.
- private static final int MIN_PREVIEW_PIXELS = 480 * 320; // normal screen
- private static final float MAX_EXPOSURE_COMPENSATION = 1.5f;
- private static final float MIN_EXPOSURE_COMPENSATION = 0.0f;
- private static final double MAX_ASPECT_DISTORTION = 0.15;
- private static final int MIN_FPS = 5;
-
private final Context context;
private Point screenResolution;
private Point cameraResolution;
@@ -72,7 +54,7 @@ final class CameraConfigurationManager {
display.getSize(theScreenResolution);
screenResolution = theScreenResolution;
Log.i(TAG, "Screen resolution: " + screenResolution);
- cameraResolution = findBestPreviewSizeValue(parameters, screenResolution);
+ cameraResolution = CameraConfigurationUtils.findBestPreviewSizeValue(parameters, screenResolution);
Log.i(TAG, "Camera resolution: " + cameraResolution);
}
@@ -94,57 +76,27 @@ final class CameraConfigurationManager {
initializeTorch(parameters, prefs, safeMode);
- setBestPreviewFPS(parameters);
+ CameraConfigurationUtils.setBestPreviewFPS(parameters);
- String focusMode = null;
- if (prefs.getBoolean(PreferencesActivity.KEY_AUTO_FOCUS, true)) {
- if (safeMode || prefs.getBoolean(PreferencesActivity.KEY_DISABLE_CONTINUOUS_FOCUS, true)) {
- focusMode = findSettableValue(parameters.getSupportedFocusModes(),
- Camera.Parameters.FOCUS_MODE_AUTO);
- } else {
- focusMode = findSettableValue(parameters.getSupportedFocusModes(),
- Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE,
- Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO,
- Camera.Parameters.FOCUS_MODE_AUTO);
- }
- }
- // Maybe selected auto-focus but not available, so fall through here:
- if (!safeMode && focusMode == null) {
- focusMode = findSettableValue(parameters.getSupportedFocusModes(),
- Camera.Parameters.FOCUS_MODE_MACRO,
- Camera.Parameters.FOCUS_MODE_EDOF);
- }
- if (focusMode != null) {
- parameters.setFocusMode(focusMode);
- }
+ CameraConfigurationUtils.setFocus(
+ parameters,
+ prefs.getBoolean(PreferencesActivity.KEY_AUTO_FOCUS, true),
+ prefs.getBoolean(PreferencesActivity.KEY_DISABLE_CONTINUOUS_FOCUS, true),
+ safeMode);
if (!safeMode) {
if (prefs.getBoolean(PreferencesActivity.KEY_INVERT_SCAN, false)) {
- String colorMode = findSettableValue(parameters.getSupportedColorEffects(),
- Camera.Parameters.EFFECT_NEGATIVE);
- if (colorMode != null) {
- parameters.setColorEffect(colorMode);
- }
+ CameraConfigurationUtils.setInvertColor(parameters);
}
if (!prefs.getBoolean(PreferencesActivity.KEY_DISABLE_BARCODE_SCENE_MODE, true)) {
- String sceneMode = findSettableValue(parameters.getSupportedSceneModes(),
- Camera.Parameters.SCENE_MODE_BARCODE);
- if (sceneMode != null) {
- parameters.setSceneMode(sceneMode);
- }
+ CameraConfigurationUtils.setBarcodeSceneMode(parameters);
}
if (!prefs.getBoolean(PreferencesActivity.KEY_DISABLE_METERING, true)) {
- if (parameters.isVideoStabilizationSupported()) {
- Log.i(TAG, "Enabling video stabilization...");
- parameters.setVideoStabilization(true);
- } else {
- Log.i(TAG, "This device does not support video stabilization");
- }
-
- MeteringInterface.setFocusArea(parameters);
- MeteringInterface.setMetering(parameters);
+ CameraConfigurationUtils.setVideoStabilization(parameters);
+ CameraConfigurationUtils.setFocusArea(parameters);
+ CameraConfigurationUtils.setMetering(parameters);
}
}
@@ -195,185 +147,11 @@ final class CameraConfigurationManager {
}
private void doSetTorch(Camera.Parameters parameters, boolean newSetting, boolean safeMode) {
- String flashMode;
- if (newSetting) {
- flashMode = findSettableValue(parameters.getSupportedFlashModes(),
- Camera.Parameters.FLASH_MODE_TORCH,
- Camera.Parameters.FLASH_MODE_ON);
- } else {
- flashMode = findSettableValue(parameters.getSupportedFlashModes(),
- Camera.Parameters.FLASH_MODE_OFF);
- }
- if (flashMode != null) {
- parameters.setFlashMode(flashMode);
- }
-
+ CameraConfigurationUtils.setTorch(parameters, newSetting);
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
- if (!prefs.getBoolean(PreferencesActivity.KEY_DISABLE_EXPOSURE, true)) {
- if (!safeMode) {
- int minExposure = parameters.getMinExposureCompensation();
- int maxExposure = parameters.getMaxExposureCompensation();
- if (minExposure != 0 || maxExposure != 0) {
- float step = parameters.getExposureCompensationStep();
- int desiredCompensation;
- if (newSetting) {
- // Light on; set low exposure compensation
- desiredCompensation = Math.max((int) (MIN_EXPOSURE_COMPENSATION / step), minExposure);
- } else {
- // Light off; set high compensation
- desiredCompensation = Math.min((int) (MAX_EXPOSURE_COMPENSATION / step), maxExposure);
- }
- Log.i(TAG, "Setting exposure compensation to " + desiredCompensation + " / " + (step * desiredCompensation));
- parameters.setExposureCompensation(desiredCompensation);
- } else {
- Log.i(TAG, "Camera does not support exposure compensation");
- }
- }
+ if (!safeMode && !prefs.getBoolean(PreferencesActivity.KEY_DISABLE_EXPOSURE, true)) {
+ CameraConfigurationUtils.setBestExposure(parameters, newSetting);
}
}
- private static void setBestPreviewFPS(Camera.Parameters parameters) {
- // Required for Glass compatibility; also improves battery/CPU performance a tad
- List supportedPreviewFpsRanges = parameters.getSupportedPreviewFpsRange();
- Log.i(TAG, "Supported FPS ranges: " + toString(supportedPreviewFpsRanges));
- if (supportedPreviewFpsRanges != null && !supportedPreviewFpsRanges.isEmpty()) {
- int[] minimumSuitableFpsRange = null;
- for (int[] fpsRange : supportedPreviewFpsRanges) {
- int fpsMax = fpsRange[Camera.Parameters.PREVIEW_FPS_MAX_INDEX];
- if (fpsMax >= MIN_FPS * 1000 &&
- (minimumSuitableFpsRange == null ||
- fpsMax > minimumSuitableFpsRange[Camera.Parameters.PREVIEW_FPS_MAX_INDEX])) {
- minimumSuitableFpsRange = fpsRange;
- }
- }
- if (minimumSuitableFpsRange == null) {
- Log.i(TAG, "No suitable FPS range?");
- } else {
- int[] currentFpsRange = new int[2];
- parameters.getPreviewFpsRange(currentFpsRange);
- if (!Arrays.equals(currentFpsRange, minimumSuitableFpsRange)) {
- Log.i(TAG, "Setting FPS range to " + Arrays.toString(minimumSuitableFpsRange));
- parameters.setPreviewFpsRange(minimumSuitableFpsRange[Camera.Parameters.PREVIEW_FPS_MIN_INDEX],
- minimumSuitableFpsRange[Camera.Parameters.PREVIEW_FPS_MAX_INDEX]);
- }
- }
- }
- }
-
- // Actually prints the arrays properly:
- private static String toString(Collection arrays) {
- if (arrays == null || arrays.isEmpty()) {
- return "[]";
- }
- StringBuilder buffer = new StringBuilder();
- buffer.append('[');
- Iterator it = arrays.iterator();
- while (it.hasNext()) {
- buffer.append(Arrays.toString(it.next()));
- if (it.hasNext()) {
- buffer.append(", ");
- }
- }
- buffer.append(']');
- return buffer.toString();
- }
-
- private Point findBestPreviewSizeValue(Camera.Parameters parameters, Point screenResolution) {
-
- List rawSupportedSizes = parameters.getSupportedPreviewSizes();
- if (rawSupportedSizes == null) {
- Log.w(TAG, "Device returned no supported preview sizes; using default");
- Camera.Size defaultSize = parameters.getPreviewSize();
- return new Point(defaultSize.width, defaultSize.height);
- }
-
- // Sort by size, descending
- List supportedPreviewSizes = new ArrayList<>(rawSupportedSizes);
- Collections.sort(supportedPreviewSizes, new Comparator() {
- @Override
- public int compare(Camera.Size a, Camera.Size b) {
- int aPixels = a.height * a.width;
- int bPixels = b.height * b.width;
- if (bPixels < aPixels) {
- return -1;
- }
- if (bPixels > aPixels) {
- return 1;
- }
- return 0;
- }
- });
-
- if (Log.isLoggable(TAG, Log.INFO)) {
- StringBuilder previewSizesString = new StringBuilder();
- for (Camera.Size supportedPreviewSize : supportedPreviewSizes) {
- previewSizesString.append(supportedPreviewSize.width).append('x')
- .append(supportedPreviewSize.height).append(' ');
- }
- Log.i(TAG, "Supported preview sizes: " + previewSizesString);
- }
-
- double screenAspectRatio = (double) screenResolution.x / (double) screenResolution.y;
-
- // Remove sizes that are unsuitable
- Iterator it = supportedPreviewSizes.iterator();
- while (it.hasNext()) {
- Camera.Size supportedPreviewSize = it.next();
- int realWidth = supportedPreviewSize.width;
- int realHeight = supportedPreviewSize.height;
- if (realWidth * realHeight < MIN_PREVIEW_PIXELS) {
- it.remove();
- continue;
- }
-
- boolean isCandidatePortrait = realWidth < realHeight;
- int maybeFlippedWidth = isCandidatePortrait ? realHeight : realWidth;
- int maybeFlippedHeight = isCandidatePortrait ? realWidth : realHeight;
- double aspectRatio = (double) maybeFlippedWidth / (double) maybeFlippedHeight;
- double distortion = Math.abs(aspectRatio - screenAspectRatio);
- if (distortion > MAX_ASPECT_DISTORTION) {
- it.remove();
- continue;
- }
-
- if (maybeFlippedWidth == screenResolution.x && maybeFlippedHeight == screenResolution.y) {
- Point exactPoint = new Point(realWidth, realHeight);
- Log.i(TAG, "Found preview size exactly matching screen size: " + exactPoint);
- return exactPoint;
- }
- }
-
- // If no exact match, use largest preview size. This was not a great idea on older devices because
- // of the additional computation needed. We're likely to get here on newer Android 4+ devices, where
- // the CPU is much more powerful.
- if (!supportedPreviewSizes.isEmpty()) {
- Camera.Size largestPreview = supportedPreviewSizes.get(0);
- Point largestSize = new Point(largestPreview.width, largestPreview.height);
- Log.i(TAG, "Using largest suitable preview size: " + largestSize);
- return largestSize;
- }
-
- // If there is nothing at all suitable, return current preview size
- Camera.Size defaultPreview = parameters.getPreviewSize();
- Point defaultSize = new Point(defaultPreview.width, defaultPreview.height);
- Log.i(TAG, "No suitable preview sizes, using default: " + defaultSize);
- return defaultSize;
- }
-
- private static String findSettableValue(Collection supportedValues,
- String... desiredValues) {
- Log.i(TAG, "Supported values: " + supportedValues);
- String result = null;
- if (supportedValues != null) {
- for (String desiredValue : desiredValues) {
- if (supportedValues.contains(desiredValue)) {
- result = desiredValue;
- break;
- }
- }
- }
- Log.i(TAG, "Settable value: " + result);
- return result;
- }
-
}
diff --git a/android/src/com/google/zxing/client/android/camera/metering/MeteringInterface.java b/android/src/com/google/zxing/client/android/camera/metering/MeteringInterface.java
deleted file mode 100644
index aad310850..000000000
--- a/android/src/com/google/zxing/client/android/camera/metering/MeteringInterface.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2014 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing.client.android.camera.metering;
-
-import java.util.Collections;
-import java.util.List;
-
-import android.graphics.Rect;
-import android.hardware.Camera;
-import android.util.Log;
-
-public final class MeteringInterface {
-
- private static final String TAG = MeteringInterface.class.getSimpleName();
- private static final int AREA_PER_1000 = 400;
-
- private MeteringInterface() {
- }
-
- public static void setFocusArea(Camera.Parameters parameters) {
- if (parameters.getMaxNumFocusAreas() > 0) {
- Log.i(TAG, "Old focus areas: " + toString(parameters.getFocusAreas()));
- List middleArea = buildMiddleArea();
- Log.i(TAG, "Setting focus area to : " + toString(middleArea));
- parameters.setFocusAreas(middleArea);
- } else {
- Log.i(TAG, "Device does not support focus areas");
- }
- }
-
- public static void setMetering(Camera.Parameters parameters) {
- if (parameters.getMaxNumMeteringAreas() > 0) {
- Log.i(TAG, "Old metering areas: " + parameters.getMeteringAreas());
- List middleArea = buildMiddleArea();
- Log.i(TAG, "Setting metering area to : " + toString(middleArea));
- parameters.setMeteringAreas(middleArea);
- } else {
- Log.i(TAG, "Device does not support metering areas");
- }
- }
-
- private static List buildMiddleArea() {
- return Collections.singletonList(
- new Camera.Area(new Rect(-AREA_PER_1000, -AREA_PER_1000, AREA_PER_1000, AREA_PER_1000), 1));
- }
-
- private static String toString(Iterable areas) {
- if (areas == null) {
- return null;
- }
- StringBuilder result = new StringBuilder();
- for (Camera.Area area : areas) {
- result.append(area.rect).append(':').append(area.weight).append(' ');
- }
- return result.toString();
- }
-
-}
diff --git a/glass/pom.xml b/glass/pom.xml
index a33e70258..930b383b1 100644
--- a/glass/pom.xml
+++ b/glass/pom.xml
@@ -27,6 +27,11 @@
core
${project.parent.version}
+
+ com.google.zxing
+ android-core
+ ${project.parent.version}
+
com.google.android
android
diff --git a/glass/src/com/google/zxing/client/glass/CameraConfigurationManager.java b/glass/src/com/google/zxing/client/glass/CameraConfigurationManager.java
index d343946c0..4af3b4dbf 100644
--- a/glass/src/com/google/zxing/client/glass/CameraConfigurationManager.java
+++ b/glass/src/com/google/zxing/client/glass/CameraConfigurationManager.java
@@ -16,24 +16,15 @@
package com.google.zxing.client.glass;
-import android.graphics.Rect;
import android.hardware.Camera;
-import android.util.Log;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
+import com.google.zxing.client.android.camera.CameraConfigurationUtils;
/**
* @author Sean Owen
*/
final class CameraConfigurationManager {
- private static final String TAG = "CameraConfiguration";
- private static final int AREA_PER_1000 = 400;
- private static final int MIN_FPS = 10;
-
private CameraConfigurationManager() {
}
@@ -46,83 +37,11 @@ final class CameraConfigurationManager {
}
private static void configureAdvanced(Camera.Parameters parameters) {
-
- setBestPreviewFPS(parameters);
-
- String sceneMode = findSettableValue(parameters.getSupportedSceneModes(),
- Camera.Parameters.SCENE_MODE_BARCODE);
- if (sceneMode != null) {
- parameters.setSceneMode(sceneMode);
- } else {
- Log.i(TAG, "Scene mode is not supported");
- }
-
- if (parameters.isVideoStabilizationSupported()) {
- Log.i(TAG, "Enabling video stabilization...");
- parameters.setVideoStabilization(true);
- } else {
- Log.i(TAG, "This device does not support video stabilization");
- }
-
- if (parameters.getMaxNumMeteringAreas() > 0) {
- Log.i(TAG, "Old metering areas: " + parameters.getMeteringAreas());
- List middleArea = Collections.singletonList(
- new Camera.Area(new Rect(-AREA_PER_1000, -AREA_PER_1000, AREA_PER_1000, AREA_PER_1000), 1));
- parameters.setMeteringAreas(middleArea);
- } else {
- Log.i(TAG, "Device does not support metering areas");
- }
-
- if (parameters.isZoomSupported()) {
- Log.i(TAG, "Setting to max zoom");
- parameters.setZoom(parameters.getMaxZoom());
- } else {
- Log.i(TAG, "Zoom is not supported");
- }
-
- }
-
- private static String findSettableValue(Collection supportedValues,
- String... desiredValues) {
- Log.i(TAG, "Supported values: " + supportedValues);
- String result = null;
- if (supportedValues != null) {
- for (String desiredValue : desiredValues) {
- if (supportedValues.contains(desiredValue)) {
- result = desiredValue;
- break;
- }
- }
- }
- Log.i(TAG, "Settable value: " + result);
- return result;
- }
-
- private static void setBestPreviewFPS(Camera.Parameters parameters) {
- // Required for Glass compatibility; also improves battery/CPU performance a tad
- List supportedPreviewFpsRanges = parameters.getSupportedPreviewFpsRange();
- if (supportedPreviewFpsRanges != null && !supportedPreviewFpsRanges.isEmpty()) {
- int[] minimumSuitableFpsRange = null;
- for (int[] fpsRange : supportedPreviewFpsRanges) {
- int fpsMax = fpsRange[Camera.Parameters.PREVIEW_FPS_MAX_INDEX];
- if (fpsMax >= MIN_FPS * 1000 &&
- (minimumSuitableFpsRange == null ||
- fpsMax > minimumSuitableFpsRange[Camera.Parameters.PREVIEW_FPS_MAX_INDEX])) {
- minimumSuitableFpsRange = fpsRange;
- }
- }
- if (minimumSuitableFpsRange == null) {
- Log.i(TAG, "No suitable FPS range?");
- } else {
- int[] currentFpsRange = new int[2];
- parameters.getPreviewFpsRange(currentFpsRange);
- if (!Arrays.equals(currentFpsRange, minimumSuitableFpsRange)) {
- Log.i(TAG, "Setting FPS range to " + Arrays.toString(minimumSuitableFpsRange));
- parameters.setPreviewFpsRange(minimumSuitableFpsRange[Camera.Parameters.PREVIEW_FPS_MIN_INDEX],
- minimumSuitableFpsRange[Camera.Parameters.PREVIEW_FPS_MAX_INDEX]);
- }
- }
- }
+ CameraConfigurationUtils.setBestPreviewFPS(parameters);
+ CameraConfigurationUtils.setBarcodeSceneMode(parameters);
+ CameraConfigurationUtils.setVideoStabilization(parameters);
+ CameraConfigurationUtils.setMetering(parameters);
+ CameraConfigurationUtils.setMaxZoom(parameters);
}
}
diff --git a/pom.xml b/pom.xml
index 6d8bbd065..c53207ce1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -507,6 +507,7 @@
+ android-core
android
androidtest
glass