Since preview size will not match preview size in Android 4+ with soft nav bar, prefer large preview that is roughly the right aspect ratio

git-svn-id: https://zxing.googlecode.com/svn/trunk@2828 59b500cc-1b3d-0410-9834-0bbf25fbcc57
This commit is contained in:
srowen@gmail.com 2013-06-22 21:39:25 +00:00
parent 874aade197
commit 0ad4759e14
3 changed files with 37 additions and 25 deletions

View file

@ -16,8 +16,8 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.google.zxing.client.android"
android:versionName="4.4 beta 1"
android:versionCode="89"
android:versionName="4.4 beta 2"
android:versionCode="90"
android:installLocation="auto">
<uses-permission android:name="android.permission.CAMERA"/>

View file

@ -9,9 +9,10 @@
<p>New in version 4.4:</p>
<ul>
<li>Android 2.3.3 is required now.</li>
<li>The Holo theme is enabled on Android 3 and Android 4 devices</li>
<li>The Holo theme is enabled on Android 3 and Android 4 devices.</li>
<li>The barcode scanning rectangle has been enlarged slightly on some devices.</li>
<li>Minor fixes.</li>
<li>The chosen preview size has changed on some Android 4 devices,
in order to accommodate the space taken by the soft navigation bar.</li>
</ul>
</body>
</html>

View file

@ -31,6 +31,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
/**
@ -44,10 +45,10 @@ final class CameraConfigurationManager {
// 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 = 470 * 320; // normal screen
private static final int MAX_PREVIEW_PIXELS = 1280 * 800;
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 final Context context;
private Point screenResolution;
@ -114,7 +115,7 @@ final class CameraConfigurationManager {
if (!safeMode && focusMode == null) {
focusMode = findSettableValue(parameters.getSupportedFocusModes(),
Camera.Parameters.FOCUS_MODE_MACRO,
"edof"); // Camera.Parameters.FOCUS_MODE_EDOF in 2.2+
Camera.Parameters.FOCUS_MODE_EDOF);
}
if (focusMode != null) {
parameters.setFocusMode(focusMode);
@ -239,41 +240,51 @@ final class CameraConfigurationManager {
Log.i(TAG, "Supported preview sizes: " + previewSizesString);
}
Point bestSize = null;
float screenAspectRatio = (float) screenResolution.x / (float) screenResolution.y;
double screenAspectRatio = (double) screenResolution.x / (double) screenResolution.y;
float diff = Float.POSITIVE_INFINITY;
for (Camera.Size supportedPreviewSize : supportedPreviewSizes) {
// Remove sizes that are unsuitable
Iterator<Camera.Size> it = supportedPreviewSizes.iterator();
while (it.hasNext()) {
Camera.Size supportedPreviewSize = it.next();
int realWidth = supportedPreviewSize.width;
int realHeight = supportedPreviewSize.height;
int pixels = realWidth * realHeight;
if (pixels < MIN_PREVIEW_PIXELS || pixels > MAX_PREVIEW_PIXELS) {
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;
}
float aspectRatio = (float) maybeFlippedWidth / (float) maybeFlippedHeight;
float newDiff = Math.abs(aspectRatio - screenAspectRatio);
if (newDiff < diff) {
bestSize = new Point(realWidth, realHeight);
diff = newDiff;
}
}
if (bestSize == null) {
Camera.Size defaultSize = parameters.getPreviewSize();
bestSize = new Point(defaultSize.width, defaultSize.height);
Log.i(TAG, "No suitable preview sizes, using default: " + bestSize);
// 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;
}
Log.i(TAG, "Found best approximate preview size: " + bestSize);
return bestSize;
// 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<String> supportedValues,