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" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.google.zxing.client.android" package="com.google.zxing.client.android"
android:versionName="4.4 beta 1" android:versionName="4.4 beta 2"
android:versionCode="89" android:versionCode="90"
android:installLocation="auto"> android:installLocation="auto">
<uses-permission android:name="android.permission.CAMERA"/> <uses-permission android:name="android.permission.CAMERA"/>

View file

@ -9,9 +9,10 @@
<p>New in version 4.4:</p> <p>New in version 4.4:</p>
<ul> <ul>
<li>Android 2.3.3 is required now.</li> <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>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> </ul>
</body> </body>
</html> </html>

View file

@ -31,6 +31,7 @@ import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.Iterator;
import java.util.List; 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 // 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 // below will still select the default (presumably 320x240) size for these. This prevents
// accidental selection of very low resolution on some devices. // accidental selection of very low resolution on some devices.
private static final int MIN_PREVIEW_PIXELS = 470 * 320; // normal screen private static final int MIN_PREVIEW_PIXELS = 480 * 320; // normal screen
private static final int MAX_PREVIEW_PIXELS = 1280 * 800;
//private static final float MAX_EXPOSURE_COMPENSATION = 1.5f; //private static final float MAX_EXPOSURE_COMPENSATION = 1.5f;
//private static final float MIN_EXPOSURE_COMPENSATION = 0.0f; //private static final float MIN_EXPOSURE_COMPENSATION = 0.0f;
private static final double MAX_ASPECT_DISTORTION = 0.15;
private final Context context; private final Context context;
private Point screenResolution; private Point screenResolution;
@ -114,7 +115,7 @@ final class CameraConfigurationManager {
if (!safeMode && focusMode == null) { if (!safeMode && focusMode == null) {
focusMode = findSettableValue(parameters.getSupportedFocusModes(), focusMode = findSettableValue(parameters.getSupportedFocusModes(),
Camera.Parameters.FOCUS_MODE_MACRO, Camera.Parameters.FOCUS_MODE_MACRO,
"edof"); // Camera.Parameters.FOCUS_MODE_EDOF in 2.2+ Camera.Parameters.FOCUS_MODE_EDOF);
} }
if (focusMode != null) { if (focusMode != null) {
parameters.setFocusMode(focusMode); parameters.setFocusMode(focusMode);
@ -239,41 +240,51 @@ final class CameraConfigurationManager {
Log.i(TAG, "Supported preview sizes: " + previewSizesString); Log.i(TAG, "Supported preview sizes: " + previewSizesString);
} }
Point bestSize = null; double screenAspectRatio = (double) screenResolution.x / (double) screenResolution.y;
float screenAspectRatio = (float) screenResolution.x / (float) screenResolution.y;
float diff = Float.POSITIVE_INFINITY; // Remove sizes that are unsuitable
for (Camera.Size supportedPreviewSize : supportedPreviewSizes) { Iterator<Camera.Size> it = supportedPreviewSizes.iterator();
while (it.hasNext()) {
Camera.Size supportedPreviewSize = it.next();
int realWidth = supportedPreviewSize.width; int realWidth = supportedPreviewSize.width;
int realHeight = supportedPreviewSize.height; int realHeight = supportedPreviewSize.height;
int pixels = realWidth * realHeight; if (realWidth * realHeight < MIN_PREVIEW_PIXELS) {
if (pixels < MIN_PREVIEW_PIXELS || pixels > MAX_PREVIEW_PIXELS) { it.remove();
continue; continue;
} }
boolean isCandidatePortrait = realWidth < realHeight; boolean isCandidatePortrait = realWidth < realHeight;
int maybeFlippedWidth = isCandidatePortrait ? realHeight : realWidth; int maybeFlippedWidth = isCandidatePortrait ? realHeight : realWidth;
int maybeFlippedHeight = isCandidatePortrait ? realWidth : realHeight; 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) { if (maybeFlippedWidth == screenResolution.x && maybeFlippedHeight == screenResolution.y) {
Point exactPoint = new Point(realWidth, realHeight); Point exactPoint = new Point(realWidth, realHeight);
Log.i(TAG, "Found preview size exactly matching screen size: " + exactPoint); Log.i(TAG, "Found preview size exactly matching screen size: " + exactPoint);
return 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) { // If no exact match, use largest preview size. This was not a great idea on older devices because
Camera.Size defaultSize = parameters.getPreviewSize(); // of the additional computation needed. We're likely to get here on newer Android 4+ devices, where
bestSize = new Point(defaultSize.width, defaultSize.height); // the CPU is much more powerful.
Log.i(TAG, "No suitable preview sizes, using default: " + bestSize); 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); // If there is nothing at all suitable, return current preview size
return bestSize; 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, private static String findSettableValue(Collection<String> supportedValues,