Skip to content

Commit

Permalink
Change formula of optimal preview size to fix Huawei devices camera i…
Browse files Browse the repository at this point in the history
…ssue.

Adapted patch suggested by @vagrant1991.
See discussion at dm77#287
  • Loading branch information
katox committed Oct 11, 2018
1 parent a4fe1cd commit fdd5002
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 37 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Change Log

## [1.9.9-leafclick] - Oct 11, 2018
* Update build for Android Studio 3.2 and gradle-4.6.
* Change formula of optimal preview size to fix Huawei devices camera issue.

## [1.9.8] - August 18, 2017
* One more attempt to fix Nexus 5x portrait scanning problems

Expand Down
19 changes: 11 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,18 @@ Introduction

Android library projects that provides easy to use and extensible Barcode Scanner views based on ZXing and ZBar.

Changes
=========
See the [Changelog](https://github.com/leafclick/barcodescanner/blob/master/CHANGELOG.md).


Screenshots
===========
<img src="https://raw.github.com/dm77/barcodescanner/master/screenshots/main_activity.png" width="266">
<img src="https://raw.github.com/dm77/barcodescanner/master/screenshots/scanner.png" width="266">
<img src="https://raw.github.com/dm77/barcodescanner/master/screenshots/scan_results.png" width="266">


Minor BREAKING CHANGE in 1.8.4
==============================
Version 1.8.4 introduces a couple of new changes:

* Open Camera and handle preview frames in a separate HandlerThread (#1, #99): Though this has worked fine in my testing on 3 devices, I would advise you to test on your own devices before blindly releasing apps with this version. If you run into any issues please file a bug report.
* Do not automatically stopCamera after a result is found #115: This means that upon a successful scan only the cameraPreview is stopped but the camera is not released. So previously if your code was calling mScannerView.startCamera() in the handleResult() method, please replace that with a call to mScannerView.resumeCameraPreview(this);

ZXing
=====

Expand All @@ -25,7 +23,11 @@ Installation

Add the following dependency to your build.gradle file.

`compile 'me.dm7.barcodescanner:zxing:1.9.8'`
`./gradlew build`

To install new build into the local maven repository, run

`./gradlew publishToMavenLocal`

Simple Usage
------------
Expand Down Expand Up @@ -282,6 +284,7 @@ Contributors
============

https://github.com/dm77/barcodescanner/graphs/contributors
Kamil Toman <kamil.toman@leafclick.com>

License
=======
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ public final void setupLayout(CameraWrapper cameraWrapper) {
mPreview = new CameraPreview(getContext(), cameraWrapper, this);
mPreview.setAspectTolerance(mAspectTolerance);
mPreview.setShouldScaleToFill(mShouldScaleToFill);
mPreview.setSquareViewFinder(mSquaredFinder);
if (!mShouldScaleToFill) {
RelativeLayout relativeLayout = new RelativeLayout(getContext());
relativeLayout.setGravity(Gravity.CENTER);
Expand Down
89 changes: 66 additions & 23 deletions core/src/main/java/me/dm7/barcodescanner/core/CameraPreview.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
import android.view.ViewGroup;
import android.view.WindowManager;

import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
Expand All @@ -28,6 +30,7 @@ public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback
private boolean mShouldScaleToFill = true;
private Camera.PreviewCallback mPreviewCallback;
private float mAspectTolerance = 0.1f;
protected boolean mSquareViewFinder;

public CameraPreview(Context context, CameraWrapper cameraWrapper, Camera.PreviewCallback previewCallback) {
super(context);
Expand Down Expand Up @@ -59,14 +62,18 @@ public void setAspectTolerance(float aspectTolerance) {
mAspectTolerance = aspectTolerance;
}

public void setSquareViewFinder(boolean squareViewFinder) {
this.mSquareViewFinder = squareViewFinder;
}

@Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
mSurfaceCreated = true;
}

@Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i2, int i3) {
if(surfaceHolder.getSurface() == null) {
if (surfaceHolder.getSurface() == null) {
return;
}
stopCameraPreview();
Expand All @@ -80,7 +87,7 @@ public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
}

public void showCameraPreview() {
if(mCameraWrapper != null) {
if (mCameraWrapper != null) {
try {
getHolder().addCallback(this);
mPreviewing = true;
Expand All @@ -89,7 +96,7 @@ public void showCameraPreview() {
mCameraWrapper.mCamera.setDisplayOrientation(getDisplayOrientation());
mCameraWrapper.mCamera.setOneShotPreviewCallback(mPreviewCallback);
mCameraWrapper.mCamera.startPreview();
if(mAutoFocus) {
if (mAutoFocus) {
if (mSurfaceCreated) { // check if surface created before using autofocus
safeAutoFocus();
} else {
Expand All @@ -113,14 +120,14 @@ public void safeAutoFocus() {
}

public void stopCameraPreview() {
if(mCameraWrapper != null) {
if (mCameraWrapper != null) {
try {
mPreviewing = false;
getHolder().removeCallback(this);
mCameraWrapper.mCamera.cancelAutoFocus();
mCameraWrapper.mCamera.setOneShotPreviewCallback(null);
mCameraWrapper.mCamera.stopPreview();
} catch(Exception e) {
} catch (Exception e) {
Log.e(TAG, e.toString(), e);
}
}
Expand Down Expand Up @@ -198,7 +205,7 @@ public int getDisplayOrientation() {
}

Camera.CameraInfo info = new Camera.CameraInfo();
if(mCameraWrapper.mCameraId == -1) {
if (mCameraWrapper.mCameraId == -1) {
Camera.getCameraInfo(Camera.CameraInfo.CAMERA_FACING_BACK, info);
} else {
Camera.getCameraInfo(mCameraWrapper.mCameraId, info);
Expand All @@ -210,10 +217,18 @@ public int getDisplayOrientation() {
int rotation = display.getRotation();
int degrees = 0;
switch (rotation) {
case Surface.ROTATION_0: degrees = 0; break;
case Surface.ROTATION_90: degrees = 90; break;
case Surface.ROTATION_180: degrees = 180; break;
case Surface.ROTATION_270: degrees = 270; break;
case Surface.ROTATION_0:
degrees = 0;
break;
case Surface.ROTATION_90:
degrees = 90;
break;
case Surface.ROTATION_180:
degrees = 180;
break;
case Surface.ROTATION_270:
degrees = 270;
break;
}

int result;
Expand All @@ -227,10 +242,9 @@ public int getDisplayOrientation() {
}

private Camera.Size getOptimalPreviewSize() {
if(mCameraWrapper == null) {
if (mCameraWrapper == null) {
return null;
}

List<Camera.Size> sizes = mCameraWrapper.mCamera.getParameters().getSupportedPreviewSizes();
int w = getWidth();
int h = getHeight();
Expand All @@ -240,25 +254,54 @@ private Camera.Size getOptimalPreviewSize() {
w = portraitWidth;
}

double targetRatio = (double) w / h;
if (sizes == null) return null;

Camera.Size optimalSize = null;
double minDiff = Double.MAX_VALUE;

int targetHeight = h;
Collections.sort(sizes, new Comparator<Camera.Size>() {
@Override
public int compare(Camera.Size lhs, Camera.Size rhs) {
return lhs.height - rhs.height;
}
});

int orientation = DisplayUtils.getScreenOrientation(getContext());
int width;
int height;
if (mSquareViewFinder) {
if (orientation != Configuration.ORIENTATION_PORTRAIT) {
height = (int) (getHeight() * ViewFinderView.DEFAULT_SQUARE_DIMENSION_RATIO);
width = height;
} else {
width = (int) (getWidth() * ViewFinderView.DEFAULT_SQUARE_DIMENSION_RATIO);
height = width;
}
} else {
if (orientation != Configuration.ORIENTATION_PORTRAIT) {
height = (int) (getHeight() * ViewFinderView.LANDSCAPE_HEIGHT_RATIO);
width = (int) (ViewFinderView.LANDSCAPE_WIDTH_HEIGHT_RATIO * height);
} else {
width = (int) (getWidth() * ViewFinderView.PORTRAIT_WIDTH_RATIO);
height = (int) (ViewFinderView.PORTRAIT_WIDTH_HEIGHT_RATIO * width);
}
}

if (width > getWidth()) {
width = getWidth() - ViewFinderView.MIN_DIMENSION_DIFF;
}
if (height > getHeight()) {
height = getHeight() - ViewFinderView.MIN_DIMENSION_DIFF;
}

// Try to find an size match aspect ratio and size
for (Camera.Size size : sizes) {
double ratio = (double) size.width / size.height;
if (Math.abs(ratio - targetRatio) > mAspectTolerance) continue;
if (Math.abs(size.height - targetHeight) < minDiff) {
if (size.height > height && size.width > width) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
break;
}
}

// Cannot find the one match the aspect ratio, ignore the requirement
if (optimalSize == null) {
minDiff = Double.MAX_VALUE;
for (Camera.Size size : sizes) {
Expand All @@ -272,12 +315,12 @@ private Camera.Size getOptimalPreviewSize() {
}

public void setAutoFocus(boolean state) {
if(mCameraWrapper != null && mPreviewing) {
if(state == mAutoFocus) {
if (mCameraWrapper != null && mPreviewing) {
if (state == mAutoFocus) {
return;
}
mAutoFocus = state;
if(mAutoFocus) {
if (mAutoFocus) {
if (mSurfaceCreated) { // check if surface created before using autofocus
Log.v(TAG, "Starting autofocus");
safeAutoFocus();
Expand All @@ -293,7 +336,7 @@ public void setAutoFocus(boolean state) {

private Runnable doAutoFocus = new Runnable() {
public void run() {
if(mCameraWrapper != null && mPreviewing && mAutoFocus && mSurfaceCreated) {
if (mCameraWrapper != null && mPreviewing && mAutoFocus && mSurfaceCreated) {
safeAutoFocus();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@ public class ViewFinderView extends View implements IViewFinder {

private Rect mFramingRect;

private static final float PORTRAIT_WIDTH_RATIO = 6f/8;
private static final float PORTRAIT_WIDTH_HEIGHT_RATIO = 0.75f;
public static final float PORTRAIT_WIDTH_RATIO = 6f/8;
public static final float PORTRAIT_WIDTH_HEIGHT_RATIO = 0.75f;

private static final float LANDSCAPE_HEIGHT_RATIO = 5f/8;
private static final float LANDSCAPE_WIDTH_HEIGHT_RATIO = 1.4f;
private static final int MIN_DIMENSION_DIFF = 50;
public static final float LANDSCAPE_HEIGHT_RATIO = 5f/8;
public static final float LANDSCAPE_WIDTH_HEIGHT_RATIO = 1.4f;
public static final int MIN_DIMENSION_DIFF = 50;

private static final float DEFAULT_SQUARE_DIMENSION_RATIO = 5f / 8;
public static final float DEFAULT_SQUARE_DIMENSION_RATIO = 5f / 8;

private static final int[] SCANNER_ALPHA = {0, 64, 128, 192, 255, 192, 128, 64};
private int scannerAlpha;
Expand Down

0 comments on commit fdd5002

Please sign in to comment.