支持扫二维码过小时,自动缩放
This commit is contained in:
BIN
.idea/caches/build_file_checksums.ser
generated
BIN
.idea/caches/build_file_checksums.ser
generated
Binary file not shown.
19
README.md
19
README.md
@@ -45,17 +45,17 @@ ZXingLite for Android 是ZXing的精简版,基于ZXing库优化扫码和生成
|
||||
<dependency>
|
||||
<groupId>com.king.zxing</groupId>
|
||||
<artifactId>zxing-lite</artifactId>
|
||||
<version>1.1.0</version>
|
||||
<version>1.1.1</version>
|
||||
<type>pom</type>
|
||||
</dependency>
|
||||
```
|
||||
### Gradle:
|
||||
```gradle
|
||||
implementation 'com.king.zxing:zxing-lite:1.1.0'
|
||||
implementation 'com.king.zxing:zxing-lite:1.1.1'
|
||||
```
|
||||
### Lvy:
|
||||
```lvy
|
||||
<dependency org='com.king.zxing' name='zxing-lite' rev='1.1.0'>
|
||||
<dependency org='com.king.zxing' name='zxing-lite' rev='1.1.1'>
|
||||
<artifact name='$AID' ext='pom'></artifact>
|
||||
</dependency>
|
||||
```
|
||||
@@ -106,6 +106,13 @@ api 'com.google.zxing:core:3.3.3'
|
||||
CodeUtils.createBarCode(content, BarcodeFormat.CODE_128,800,200);
|
||||
```
|
||||
|
||||
如果直接使用CaptureActivity需在您项目的AndroidManifest中添加如下配置
|
||||
```Xml
|
||||
<activity
|
||||
android:name="com.king.zxing.CaptureActivity"
|
||||
android:screenOrientation="portrait"/>
|
||||
```
|
||||
|
||||
### 快速实现扫码有以下几种方式:
|
||||
|
||||
> 1、直接使用CaptureActivity或者CaptureFragment。(纯洁的扫码,无任何添加剂)
|
||||
@@ -121,8 +128,12 @@ api 'com.google.zxing:core:3.3.3'
|
||||
|
||||
## 版本记录
|
||||
|
||||
#### v1.1.1:2019-5-20
|
||||
* 支持扫二维码过小时,自动缩放
|
||||
* 支持垂直条形码识别(增强条形码识别,默认不支持,需CaptureHelper.supportVerticalCode(true)开启)
|
||||
|
||||
#### v1.1.0:2019-4-19
|
||||
* 将扫码相关逻辑与界面分离,ZXingLite使用更容易扩展。
|
||||
* 将扫码相关逻辑与界面分离,ZXingLite使用更容易扩展
|
||||
* 新增CaptureFragment
|
||||
|
||||
#### v1.0.7:2019-4-9
|
||||
|
||||
Binary file not shown.
@@ -1 +1 @@
|
||||
[{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":9,"versionName":"1.1.0","enabled":true,"outputFile":"app-release.apk","fullName":"release","baseName":"release"},"path":"app-release.apk","properties":{}}]
|
||||
[{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":10,"versionName":"1.1.1","enabled":true,"outputFile":"app-release.apk","fullName":"release","baseName":"release"},"path":"app-release.apk","properties":{}}]
|
||||
@@ -29,8 +29,7 @@
|
||||
android:name=".EasyCaptureActivity"
|
||||
android:screenOrientation="portrait"/>
|
||||
<activity
|
||||
android:name=".CustomCaptureActivity"
|
||||
android:screenOrientation="portrait"/>
|
||||
android:name=".CustomCaptureActivity"/>
|
||||
|
||||
<activity
|
||||
android:name=".CaptureFragmentActivity"
|
||||
|
||||
@@ -57,7 +57,10 @@ public class CustomActivity extends AppCompatActivity implements OnCaptureCallba
|
||||
mCaptureHelper = new CaptureHelper(this,surfaceView,viewfinderView);
|
||||
mCaptureHelper.onCreate();
|
||||
mCaptureHelper.vibrate(true)
|
||||
.fullScreenScan(true)//全屏扫码
|
||||
.supportVerticalCode(true)//支持扫垂直条码,建议有此需求时才使用。
|
||||
.continuousScan(isContinuousScan);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -50,7 +50,9 @@ public class CustomCaptureActivity extends CaptureActivity {
|
||||
//获取CaptureHelper,里面有扫码相关的配置设置
|
||||
getCaptureHelper().playBeep(true)//播放音效
|
||||
.vibrate(true)//震动
|
||||
.supportVerticalCode(true)//支持扫垂直条码,建议有此需求时才使用。
|
||||
.continuousScan(isContinuousScan);//是否连扫
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -222,7 +222,7 @@ public class MainActivity extends AppCompatActivity implements EasyPermissions.P
|
||||
checkCameraPermissions();
|
||||
break;
|
||||
case R.id.btn3:
|
||||
this.cls = CustomCaptureActivity.class;
|
||||
this.cls = EasyCaptureActivity.class;
|
||||
this.title = ((Button)v).getText().toString();
|
||||
checkCameraPermissions();
|
||||
break;
|
||||
|
||||
@@ -1,22 +1,21 @@
|
||||
package com.king.zxing;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.net.Uri;
|
||||
import android.graphics.Point;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.provider.Browser;
|
||||
import android.util.Log;
|
||||
import android.view.Display;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
import com.google.zxing.DecodeHintType;
|
||||
import com.google.zxing.Result;
|
||||
import com.google.zxing.ResultPoint;
|
||||
import com.google.zxing.ResultPointCallback;
|
||||
import com.king.zxing.camera.CameraManager;
|
||||
|
||||
import java.util.Collection;
|
||||
@@ -25,7 +24,7 @@ import java.util.Map;
|
||||
/**
|
||||
* @author <a href="mailto:jenly1314@gmail.com">Jenly</a>
|
||||
*/
|
||||
public class CaptureHandler extends Handler {
|
||||
public class CaptureHandler extends Handler implements ResultPointCallback {
|
||||
|
||||
private static final String TAG = CaptureHandler.class.getSimpleName();
|
||||
|
||||
@@ -35,6 +34,20 @@ public class CaptureHandler extends Handler {
|
||||
private final CameraManager cameraManager;
|
||||
private final Activity activity;
|
||||
private final ViewfinderView viewfinderView;
|
||||
/**
|
||||
* 是否支持垂直的条形码
|
||||
*/
|
||||
private boolean isSupportVerticalCode;
|
||||
|
||||
/**
|
||||
* 是否返回扫码原图
|
||||
*/
|
||||
private boolean isReturnBitmap;
|
||||
|
||||
/**
|
||||
* 是否支持自动缩放
|
||||
*/
|
||||
private boolean isSupportAutoZoom;
|
||||
|
||||
|
||||
private enum State {
|
||||
@@ -51,8 +64,7 @@ public class CaptureHandler extends Handler {
|
||||
this.activity = activity;
|
||||
this.viewfinderView = viewfinderView;
|
||||
this.onCaptureListener = onCaptureListener;
|
||||
decodeThread = new DecodeThread(activity,cameraManager,this, decodeFormats, baseHints, characterSet,
|
||||
new ViewfinderResultPointCallback(viewfinderView));
|
||||
decodeThread = new DecodeThread(activity,cameraManager,this, decodeFormats, baseHints, characterSet, this);
|
||||
decodeThread.start();
|
||||
state = State.SUCCESS;
|
||||
|
||||
@@ -83,47 +95,11 @@ public class CaptureHandler extends Handler {
|
||||
}
|
||||
onCaptureListener.onHandleDecode((Result) message.obj, barcode, scaleFactor);
|
||||
|
||||
|
||||
} else if (message.what == R.id.decode_failed) {// We're decoding as fast as possible, so when one decode fails, start another.
|
||||
state = State.PREVIEW;
|
||||
cameraManager.requestPreviewFrame(decodeThread.getHandler(), R.id.decode);
|
||||
|
||||
} else if (message.what == R.id.return_scan_result) {
|
||||
activity.setResult(Activity.RESULT_OK, (Intent) message.obj);
|
||||
activity.finish();
|
||||
|
||||
} else if (message.what == R.id.launch_product_query) {
|
||||
String url = (String) message.obj;
|
||||
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||
intent.addFlags(Intents.FLAG_NEW_DOC);
|
||||
intent.setData(Uri.parse(url));
|
||||
|
||||
ResolveInfo resolveInfo =
|
||||
activity.getPackageManager().resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);
|
||||
String browserPackageName = null;
|
||||
if (resolveInfo != null && resolveInfo.activityInfo != null) {
|
||||
browserPackageName = resolveInfo.activityInfo.packageName;
|
||||
Log.d(TAG, "Using browser in package " + browserPackageName);
|
||||
}
|
||||
|
||||
// Needed for default Android browser / Chrome only apparently
|
||||
if (browserPackageName != null) {
|
||||
switch (browserPackageName) {
|
||||
case "com.android.browser":
|
||||
case "com.android.chrome":
|
||||
intent.setPackage(browserPackageName);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
intent.putExtra(Browser.EXTRA_APPLICATION_ID, browserPackageName);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
activity.startActivity(intent);
|
||||
} catch (ActivityNotFoundException ignored) {
|
||||
Log.w(TAG, "Can't find anything to handle VIEW of URI " + url);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,4 +127,75 @@ public class CaptureHandler extends Handler {
|
||||
viewfinderView.drawViewfinder();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void foundPossibleResultPoint(ResultPoint point) {
|
||||
if(viewfinderView!=null){
|
||||
ResultPoint resultPoint = transform(point);
|
||||
viewfinderView.addPossibleResultPoint(resultPoint);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isScreenPortrait(Context context){
|
||||
WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
|
||||
Display display = manager.getDefaultDisplay();
|
||||
Point screenResolution = new Point();
|
||||
display.getSize(screenResolution);
|
||||
return screenResolution.x < screenResolution.y;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private ResultPoint transform(ResultPoint originPoint) {
|
||||
Point screenPoint = cameraManager.getScreenResolution();
|
||||
Point cameraPoint = cameraManager.getCameraResolution();
|
||||
|
||||
float scaleX;
|
||||
float scaleY;
|
||||
float x;
|
||||
float y;
|
||||
|
||||
if(screenPoint.x < screenPoint.y){
|
||||
scaleX = 1.0f * screenPoint.x / cameraPoint.y;
|
||||
scaleY = 1.0f * screenPoint.y / cameraPoint.x;
|
||||
|
||||
x = originPoint.getX() * scaleX - Math.max(screenPoint.x,cameraPoint.y)/2;
|
||||
y = originPoint.getY() * scaleY - Math.min(screenPoint.y,cameraPoint.x)/2;
|
||||
}else{
|
||||
scaleX = 1.0f * screenPoint.x / cameraPoint.x;
|
||||
scaleY = 1.0f * screenPoint.y / cameraPoint.y;
|
||||
|
||||
x = originPoint.getX() * scaleX - Math.min(screenPoint.y,cameraPoint.y)/2;
|
||||
y = originPoint.getY() * scaleY - Math.max(screenPoint.x,cameraPoint.x)/2;
|
||||
}
|
||||
|
||||
|
||||
return new ResultPoint(x,y);
|
||||
}
|
||||
|
||||
public boolean isSupportVerticalCode() {
|
||||
return isSupportVerticalCode;
|
||||
}
|
||||
|
||||
public void setSupportVerticalCode(boolean supportVerticalCode) {
|
||||
isSupportVerticalCode = supportVerticalCode;
|
||||
}
|
||||
|
||||
public boolean isReturnBitmap() {
|
||||
return isReturnBitmap;
|
||||
}
|
||||
|
||||
public void setReturnBitmap(boolean returnBitmap) {
|
||||
isReturnBitmap = returnBitmap;
|
||||
}
|
||||
|
||||
public boolean isSupportAutoZoom() {
|
||||
return isSupportAutoZoom;
|
||||
}
|
||||
|
||||
public void setSupportAutoZoom(boolean supportAutoZoom) {
|
||||
isSupportAutoZoom = supportAutoZoom;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,6 +75,12 @@ public class CaptureHelper implements CaptureLifecycle,CaptureTouchEvent,Capture
|
||||
*/
|
||||
private boolean isSupportZoom = true;
|
||||
private float oldDistance;
|
||||
|
||||
/**
|
||||
* 是否支持自动缩放(变焦),默认支持
|
||||
*/
|
||||
private boolean isSupportAutoZoom = true;
|
||||
|
||||
/**
|
||||
* 是否支持连扫,默认不支持
|
||||
*/
|
||||
@@ -92,6 +98,21 @@ public class CaptureHelper implements CaptureLifecycle,CaptureTouchEvent,Capture
|
||||
*/
|
||||
private boolean isVibrate;
|
||||
|
||||
/**
|
||||
* 是否支持垂直的条形码
|
||||
*/
|
||||
private boolean isSupportVerticalCode;
|
||||
|
||||
/**
|
||||
* 是否返回扫码原图
|
||||
*/
|
||||
private boolean isReturnBitmap;
|
||||
|
||||
/**
|
||||
* 是否支持全屏扫码识别
|
||||
*/
|
||||
private boolean isFullScreenScan;
|
||||
|
||||
private OnCaptureCallback onCaptureCallback;
|
||||
|
||||
|
||||
@@ -115,7 +136,7 @@ public class CaptureHelper implements CaptureLifecycle,CaptureTouchEvent,Capture
|
||||
ambientLightManager = new AmbientLightManager(activity);
|
||||
|
||||
cameraManager = new CameraManager(activity);
|
||||
|
||||
cameraManager.setFullScreenScan(isFullScreenScan);
|
||||
callback = new SurfaceHolder.Callback() {
|
||||
@Override
|
||||
public void surfaceCreated(SurfaceHolder holder) {
|
||||
@@ -236,6 +257,10 @@ public class CaptureHelper implements CaptureLifecycle,CaptureTouchEvent,Capture
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化Camera
|
||||
* @param surfaceHolder
|
||||
*/
|
||||
private void initCamera(SurfaceHolder surfaceHolder) {
|
||||
if (surfaceHolder == null) {
|
||||
throw new IllegalStateException("No SurfaceHolder provided");
|
||||
@@ -249,6 +274,9 @@ public class CaptureHelper implements CaptureLifecycle,CaptureTouchEvent,Capture
|
||||
// Creating the handler starts the preview, which can also throw a RuntimeException.
|
||||
if (captureHandler == null) {
|
||||
captureHandler = new CaptureHandler(activity,viewfinderView,onCaptureListener, decodeFormats, decodeHints, characterSet, cameraManager);
|
||||
captureHandler.setSupportVerticalCode(isSupportVerticalCode);
|
||||
captureHandler.setReturnBitmap(isReturnBitmap);
|
||||
captureHandler.setSupportAutoZoom(isSupportAutoZoom);
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
Log.w(TAG, ioe);
|
||||
@@ -388,10 +416,10 @@ public class CaptureHelper implements CaptureLifecycle,CaptureTouchEvent,Capture
|
||||
public void onResult(Result result){
|
||||
String text = result.getText();
|
||||
if(isContinuousScan){
|
||||
if(onCaptureCallback!=null){
|
||||
onCaptureCallback.onResultCallback(text);
|
||||
}
|
||||
if(isAutoRestartPreviewAndDecode){
|
||||
if(onCaptureCallback!=null){
|
||||
onCaptureCallback.onResultCallback(text);
|
||||
}
|
||||
restartPreviewAndDecode();
|
||||
}
|
||||
}else{
|
||||
@@ -461,7 +489,7 @@ public class CaptureHelper implements CaptureLifecycle,CaptureTouchEvent,Capture
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* 设置支持的解码一/二维码格式,默认常规的码都支持
|
||||
* @param decodeFormats
|
||||
* @return
|
||||
*/
|
||||
@@ -471,7 +499,7 @@ public class CaptureHelper implements CaptureLifecycle,CaptureTouchEvent,Capture
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* {@link DecodeHintType}
|
||||
* @param decodeHints
|
||||
* @return
|
||||
*/
|
||||
@@ -481,7 +509,7 @@ public class CaptureHelper implements CaptureLifecycle,CaptureTouchEvent,Capture
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* 设置解码时编码字符集
|
||||
* @param characterSet
|
||||
* @return
|
||||
*/
|
||||
@@ -490,6 +518,60 @@ public class CaptureHelper implements CaptureLifecycle,CaptureTouchEvent,Capture
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置是否支持扫垂直的条码
|
||||
* @param supportVerticalCode 默认为false,想要增强扫条码识别度时可使用,相应的会增加性能消耗。
|
||||
* @return
|
||||
*/
|
||||
public CaptureHelper supportVerticalCode(boolean supportVerticalCode) {
|
||||
this.isSupportVerticalCode = supportVerticalCode;
|
||||
if(captureHandler!=null){
|
||||
captureHandler.setSupportVerticalCode(isSupportVerticalCode);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置返回扫码原图
|
||||
* @param returnBitmap 默认为false,当返回true表示扫码就结果会返回扫码原图,相应的会增加性能消耗。
|
||||
* @return
|
||||
*/
|
||||
public CaptureHelper returnBitmap(boolean returnBitmap) {
|
||||
isReturnBitmap = returnBitmap;
|
||||
if(captureHandler!=null){
|
||||
captureHandler.setReturnBitmap(isReturnBitmap);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 设置是否支持自动缩放
|
||||
* @param supportAutoZoom
|
||||
* @return
|
||||
*/
|
||||
public CaptureHelper supportAutoZoom(boolean supportAutoZoom) {
|
||||
isSupportAutoZoom = supportAutoZoom;
|
||||
if(captureHandler!=null){
|
||||
captureHandler.setSupportAutoZoom(isSupportAutoZoom);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置是否支持全屏扫码识别
|
||||
* @param fullScreenScan
|
||||
* @return
|
||||
*/
|
||||
public CaptureHelper fullScreenScan(boolean fullScreenScan) {
|
||||
isFullScreenScan = fullScreenScan;
|
||||
if(cameraManager!=null){
|
||||
cameraManager.setFullScreenScan(isFullScreenScan);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 设置扫码回调
|
||||
* @param callback
|
||||
|
||||
@@ -18,17 +18,9 @@ package com.king.zxing;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import com.google.zxing.BinaryBitmap;
|
||||
import com.google.zxing.DecodeHintType;
|
||||
import com.google.zxing.MultiFormatReader;
|
||||
import com.google.zxing.NotFoundException;
|
||||
import com.google.zxing.PlanarYUVLuminanceSource;
|
||||
import com.google.zxing.Result;
|
||||
import com.google.zxing.common.GlobalHistogramBinarizer;
|
||||
import com.google.zxing.common.HybridBinarizer;
|
||||
import com.king.zxing.camera.CameraManager;
|
||||
|
||||
import android.graphics.Point;
|
||||
import android.graphics.PointF;
|
||||
import android.hardware.Camera;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
@@ -37,6 +29,16 @@ import android.util.Log;
|
||||
import android.view.Display;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
import com.google.zxing.BinaryBitmap;
|
||||
import com.google.zxing.DecodeHintType;
|
||||
import com.google.zxing.MultiFormatReader;
|
||||
import com.google.zxing.PlanarYUVLuminanceSource;
|
||||
import com.google.zxing.Result;
|
||||
import com.google.zxing.ResultPoint;
|
||||
import com.google.zxing.common.HybridBinarizer;
|
||||
import com.king.zxing.camera.CameraManager;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -46,11 +48,13 @@ final class DecodeHandler extends Handler {
|
||||
|
||||
private final Context context;
|
||||
private final CameraManager cameraManager;
|
||||
private final Handler handler;
|
||||
private final CaptureHandler handler;
|
||||
private final MultiFormatReader multiFormatReader;
|
||||
private boolean running = true;
|
||||
|
||||
DecodeHandler(Context context, CameraManager cameraManager,Handler handler, Map<DecodeHintType,Object> hints) {
|
||||
private long lastZoomTime;
|
||||
|
||||
DecodeHandler(Context context, CameraManager cameraManager,CaptureHandler handler, Map<DecodeHintType,Object> hints) {
|
||||
multiFormatReader = new MultiFormatReader();
|
||||
multiFormatReader.setHints(hints);
|
||||
this.context = context;
|
||||
@@ -64,7 +68,7 @@ final class DecodeHandler extends Handler {
|
||||
return;
|
||||
}
|
||||
if (message.what == R.id.decode) {
|
||||
decode((byte[]) message.obj, message.arg1, message.arg2,isScreenPortrait());
|
||||
decode((byte[]) message.obj, message.arg1, message.arg2,isScreenPortrait(),handler.isSupportVerticalCode());
|
||||
|
||||
} else if (message.what == R.id.quit) {
|
||||
running = false;
|
||||
@@ -89,11 +93,85 @@ final class DecodeHandler extends Handler {
|
||||
* @param width The width of the preview frame.
|
||||
* @param height The height of the preview frame.
|
||||
*/
|
||||
private void decode(byte[] data, int width, int height,boolean isScreenPortrait) {
|
||||
private void decode(byte[] data, int width, int height,boolean isScreenPortrait,boolean isSupportVerticalCode) {
|
||||
long start = System.currentTimeMillis();
|
||||
Result rawResult = null;
|
||||
PlanarYUVLuminanceSource source = buildPlanarYUVLuminanceSource(data,width,height,isScreenPortrait);
|
||||
|
||||
if (source != null) {
|
||||
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
|
||||
try {
|
||||
rawResult = multiFormatReader.decodeWithState(bitmap);
|
||||
} catch (Exception e) {
|
||||
if(isSupportVerticalCode){
|
||||
source = buildPlanarYUVLuminanceSource(data,width,height,!isScreenPortrait);
|
||||
if(source!=null){
|
||||
BinaryBitmap bitmap1 = new BinaryBitmap(new HybridBinarizer(source));
|
||||
try{
|
||||
rawResult = multiFormatReader.decodeWithState(bitmap1);
|
||||
}catch (Exception e1){
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} finally {
|
||||
multiFormatReader.reset();
|
||||
}
|
||||
}
|
||||
|
||||
if (rawResult != null) {
|
||||
// Don't log the barcode contents for security.
|
||||
long end = System.currentTimeMillis();
|
||||
Log.d(TAG, "Found barcode in " + (end - start) + " ms");
|
||||
|
||||
BarcodeFormat barcodeFormat = rawResult.getBarcodeFormat();
|
||||
if(handler!=null && handler.isSupportAutoZoom() && barcodeFormat == BarcodeFormat.QR_CODE){
|
||||
|
||||
ResultPoint[] resultPoints = rawResult.getResultPoints();
|
||||
if(resultPoints.length >= 3){
|
||||
float distance1 = ResultPoint.distance(resultPoints[0],resultPoints[1]);
|
||||
float distance2 = ResultPoint.distance(resultPoints[1],resultPoints[2]);
|
||||
float distance3 = ResultPoint.distance(resultPoints[0],resultPoints[2]);
|
||||
int maxDistance = (int)Math.max(Math.max(distance1,distance2),distance3);
|
||||
if(handleAutoZoom(maxDistance,width)){
|
||||
Message message = Message.obtain();
|
||||
message.what = R.id.decode_succeeded;
|
||||
message.obj = rawResult;
|
||||
if(handler.isReturnBitmap()){
|
||||
Bundle bundle = new Bundle();
|
||||
bundleThumbnail(source, bundle);
|
||||
message.setData(bundle);
|
||||
}
|
||||
handler.sendMessageDelayed(message,300);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
if (handler != null) {
|
||||
Message message = Message.obtain(handler, R.id.decode_succeeded, rawResult);
|
||||
if(handler.isReturnBitmap()){
|
||||
Bundle bundle = new Bundle();
|
||||
bundleThumbnail(source, bundle);
|
||||
message.setData(bundle);
|
||||
}
|
||||
message.sendToTarget();
|
||||
}
|
||||
} else {
|
||||
if (handler != null) {
|
||||
Message message = Message.obtain(handler, R.id.decode_failed);
|
||||
message.sendToTarget();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private PlanarYUVLuminanceSource buildPlanarYUVLuminanceSource(byte[] data, int width, int height,boolean isRotate){
|
||||
PlanarYUVLuminanceSource source;
|
||||
if(isScreenPortrait){
|
||||
if(isRotate){
|
||||
byte[] rotatedData = new byte[data.length];
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int x = 0; x < width; x++)
|
||||
@@ -106,39 +184,7 @@ final class DecodeHandler extends Handler {
|
||||
}else{
|
||||
source = cameraManager.buildLuminanceSource(data, width, height);
|
||||
}
|
||||
if (source != null) {
|
||||
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
|
||||
try {
|
||||
rawResult = multiFormatReader.decodeWithState(bitmap);
|
||||
} catch (Exception e) {
|
||||
BinaryBitmap bitmap1 = new BinaryBitmap(new GlobalHistogramBinarizer(source));
|
||||
try {
|
||||
rawResult = multiFormatReader.decode(bitmap1);
|
||||
} catch (NotFoundException ne) {
|
||||
|
||||
}
|
||||
} finally {
|
||||
multiFormatReader.reset();
|
||||
}
|
||||
}
|
||||
|
||||
if (rawResult != null) {
|
||||
// Don't log the barcode contents for security.
|
||||
long end = System.currentTimeMillis();
|
||||
Log.d(TAG, "Found barcode in " + (end - start) + " ms");
|
||||
if (handler != null) {
|
||||
Message message = Message.obtain(handler, R.id.decode_succeeded, rawResult);
|
||||
Bundle bundle = new Bundle();
|
||||
bundleThumbnail(source, bundle);
|
||||
message.setData(bundle);
|
||||
message.sendToTarget();
|
||||
}
|
||||
} else {
|
||||
if (handler != null) {
|
||||
Message message = Message.obtain(handler, R.id.decode_failed);
|
||||
message.sendToTarget();
|
||||
}
|
||||
}
|
||||
return source;
|
||||
}
|
||||
|
||||
private static void bundleThumbnail(PlanarYUVLuminanceSource source, Bundle bundle) {
|
||||
@@ -152,4 +198,31 @@ final class DecodeHandler extends Handler {
|
||||
bundle.putFloat(DecodeThread.BARCODE_SCALED_FACTOR, (float) width / source.getWidth());
|
||||
}
|
||||
|
||||
private boolean handleAutoZoom(int length,int width){
|
||||
if(lastZoomTime > System.currentTimeMillis() - 1000){
|
||||
return true;
|
||||
}
|
||||
|
||||
if(length<width/5){
|
||||
|
||||
Camera camera = cameraManager.getOpenCamera().getCamera();
|
||||
if(camera!=null){
|
||||
Camera.Parameters params = camera.getParameters();
|
||||
if (params.isZoomSupported()) {
|
||||
int maxZoom = params.getMaxZoom();
|
||||
int zoom = params.getZoom();
|
||||
params.setZoom(Math.min(zoom + maxZoom/5,maxZoom));
|
||||
camera.setParameters(params);
|
||||
lastZoomTime = System.currentTimeMillis();
|
||||
return true;
|
||||
} else {
|
||||
Log.i(TAG, "zoom not supported");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,237 +0,0 @@
|
||||
package com.king.zxing;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2013 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.
|
||||
*/
|
||||
|
||||
|
||||
import java.util.EnumMap;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
|
||||
import com.google.zxing.DecodeHintType;
|
||||
|
||||
/**
|
||||
* @author Lachezar Dobrev
|
||||
*/
|
||||
public final class DecodeHintManager {
|
||||
|
||||
private static final String TAG = DecodeHintManager.class.getSimpleName();
|
||||
|
||||
// This pattern is used in decoding integer arrays.
|
||||
private static final Pattern COMMA = Pattern.compile(",");
|
||||
|
||||
private DecodeHintManager() {}
|
||||
|
||||
/**
|
||||
* <p>Split a query string into a list of name-value pairs.</p>
|
||||
*
|
||||
* <p>This is an alternative to the {@link Uri#getQueryParameterNames()} and
|
||||
* {@link Uri#getQueryParameters(String)}, which are quirky and not suitable
|
||||
* for exist-only Uri parameters.</p>
|
||||
*
|
||||
* <p>This method ignores multiple parameters with the same name and returns the
|
||||
* first one only. This is technically incorrect, but should be acceptable due
|
||||
* to the method of processing Hints: no multiple values for a hint.</p>
|
||||
*
|
||||
* @param query query to split
|
||||
* @return name-value pairs
|
||||
*/
|
||||
private static Map<String,String> splitQuery(String query) {
|
||||
Map<String,String> map = new HashMap<>();
|
||||
int pos = 0;
|
||||
while (pos < query.length()) {
|
||||
if (query.charAt(pos) == '&') {
|
||||
// Skip consecutive ampersand separators.
|
||||
pos ++;
|
||||
continue;
|
||||
}
|
||||
int amp = query.indexOf('&', pos);
|
||||
int equ = query.indexOf('=', pos);
|
||||
if (amp < 0) {
|
||||
// This is the last element in the query, no more ampersand elements.
|
||||
String name;
|
||||
String text;
|
||||
if (equ < 0) {
|
||||
// No equal sign
|
||||
name = query.substring(pos);
|
||||
name = name.replace('+', ' '); // Preemptively decode +
|
||||
name = Uri.decode(name);
|
||||
text = "";
|
||||
} else {
|
||||
// Split name and text.
|
||||
name = query.substring(pos, equ);
|
||||
name = name.replace('+', ' '); // Preemptively decode +
|
||||
name = Uri.decode(name);
|
||||
text = query.substring(equ + 1);
|
||||
text = text.replace('+', ' '); // Preemptively decode +
|
||||
text = Uri.decode(text);
|
||||
}
|
||||
if (!map.containsKey(name)) {
|
||||
map.put(name, text);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (equ < 0 || equ > amp) {
|
||||
// No equal sign until the &: this is a simple parameter with no value.
|
||||
String name = query.substring(pos, amp);
|
||||
name = name.replace('+', ' '); // Preemptively decode +
|
||||
name = Uri.decode(name);
|
||||
if (!map.containsKey(name)) {
|
||||
map.put(name, "");
|
||||
}
|
||||
pos = amp + 1;
|
||||
continue;
|
||||
}
|
||||
String name = query.substring(pos, equ);
|
||||
name = name.replace('+', ' '); // Preemptively decode +
|
||||
name = Uri.decode(name);
|
||||
String text = query.substring(equ + 1, amp);
|
||||
text = text.replace('+', ' '); // Preemptively decode +
|
||||
text = Uri.decode(text);
|
||||
if (!map.containsKey(name)) {
|
||||
map.put(name, text);
|
||||
}
|
||||
pos = amp + 1;
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
static Map<DecodeHintType,?> parseDecodeHints(Uri inputUri) {
|
||||
String query = inputUri.getEncodedQuery();
|
||||
if (query == null || query.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Extract parameters
|
||||
Map<String, String> parameters = splitQuery(query);
|
||||
|
||||
Map<DecodeHintType, Object> hints = new EnumMap<>(DecodeHintType.class);
|
||||
|
||||
for (DecodeHintType hintType: DecodeHintType.values()) {
|
||||
|
||||
if (hintType == DecodeHintType.CHARACTER_SET ||
|
||||
hintType == DecodeHintType.NEED_RESULT_POINT_CALLBACK ||
|
||||
hintType == DecodeHintType.POSSIBLE_FORMATS) {
|
||||
continue; // This hint is specified in another way
|
||||
}
|
||||
|
||||
String parameterName = hintType.name();
|
||||
String parameterText = parameters.get(parameterName);
|
||||
if (parameterText == null) {
|
||||
continue;
|
||||
}
|
||||
if (hintType.getValueType().equals(Object.class)) {
|
||||
// This is an unspecified type of hint content. Use the value as is.
|
||||
// TODO: Can we make a different assumption on this?
|
||||
hints.put(hintType, parameterText);
|
||||
continue;
|
||||
}
|
||||
if (hintType.getValueType().equals(Void.class)) {
|
||||
// Void hints are just flags: use the constant specified by DecodeHintType
|
||||
hints.put(hintType, Boolean.TRUE);
|
||||
continue;
|
||||
}
|
||||
if (hintType.getValueType().equals(String.class)) {
|
||||
// A string hint: use the decoded value.
|
||||
hints.put(hintType, parameterText);
|
||||
continue;
|
||||
}
|
||||
if (hintType.getValueType().equals(Boolean.class)) {
|
||||
// A boolean hint: a few values for false, everything else is true.
|
||||
// An empty parameter is simply a flag-style parameter, assuming true
|
||||
if (parameterText.isEmpty()) {
|
||||
hints.put(hintType, Boolean.TRUE);
|
||||
} else if ("0".equals(parameterText) ||
|
||||
"false".equalsIgnoreCase(parameterText) ||
|
||||
"no".equalsIgnoreCase(parameterText)) {
|
||||
hints.put(hintType, Boolean.FALSE);
|
||||
} else {
|
||||
hints.put(hintType, Boolean.TRUE);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
if (hintType.getValueType().equals(int[].class)) {
|
||||
// An integer array. Used to specify valid lengths.
|
||||
// Strip a trailing comma as in Java style array initialisers.
|
||||
if (!parameterText.isEmpty() && parameterText.charAt(parameterText.length() - 1) == ',') {
|
||||
parameterText = parameterText.substring(0, parameterText.length() - 1);
|
||||
}
|
||||
String[] values = COMMA.split(parameterText);
|
||||
int[] array = new int[values.length];
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
try {
|
||||
array[i] = Integer.parseInt(values[i]);
|
||||
} catch (NumberFormatException ignored) {
|
||||
Log.w(TAG, "Skipping array of integers hint " + hintType + " due to invalid numeric value: '" + values[i] + '\'');
|
||||
array = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (array != null) {
|
||||
hints.put(hintType, array);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
Log.w(TAG, "Unsupported hint type '" + hintType + "' of type " + hintType.getValueType());
|
||||
}
|
||||
|
||||
Log.i(TAG, "Hints from the URI: " + hints);
|
||||
return hints;
|
||||
}
|
||||
|
||||
static Map<DecodeHintType, Object> parseDecodeHints(Intent intent) {
|
||||
Bundle extras = intent.getExtras();
|
||||
if (extras == null || extras.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
Map<DecodeHintType,Object> hints = new EnumMap<>(DecodeHintType.class);
|
||||
|
||||
for (DecodeHintType hintType: DecodeHintType.values()) {
|
||||
|
||||
if (hintType == DecodeHintType.CHARACTER_SET ||
|
||||
hintType == DecodeHintType.NEED_RESULT_POINT_CALLBACK ||
|
||||
hintType == DecodeHintType.POSSIBLE_FORMATS) {
|
||||
continue; // This hint is specified in another way
|
||||
}
|
||||
|
||||
String hintName = hintType.name();
|
||||
if (extras.containsKey(hintName)) {
|
||||
if (hintType.getValueType().equals(Void.class)) {
|
||||
// Void hints are just flags: use the constant specified by the DecodeHintType
|
||||
hints.put(hintType, Boolean.TRUE);
|
||||
} else {
|
||||
Object hintData = extras.get(hintName);
|
||||
if (hintType.getValueType().isInstance(hintData)) {
|
||||
hints.put(hintType, hintData);
|
||||
} else {
|
||||
Log.w(TAG, "Ignoring hint " + hintType + " because it is not assignable from " + hintData);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Log.i(TAG, "Hints from the Intent: " + hints);
|
||||
return hints;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
package com.king.zxing;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2009 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.
|
||||
*/
|
||||
|
||||
|
||||
import com.google.zxing.ResultPoint;
|
||||
import com.google.zxing.ResultPointCallback;
|
||||
|
||||
final class ViewfinderResultPointCallback implements ResultPointCallback {
|
||||
|
||||
private final ViewfinderView viewfinderView;
|
||||
|
||||
ViewfinderResultPointCallback(ViewfinderView viewfinderView) {
|
||||
this.viewfinderView = viewfinderView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void foundPossibleResultPoint(ResultPoint point) {
|
||||
viewfinderView.addPossibleResultPoint(point);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -27,9 +27,11 @@ import android.graphics.LinearGradient;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.PointF;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.Shader;
|
||||
import android.support.annotation.ColorInt;
|
||||
import android.support.annotation.ColorRes;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
@@ -39,6 +41,7 @@ import android.text.TextPaint;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Log;
|
||||
import android.util.TypedValue;
|
||||
import android.view.View;
|
||||
|
||||
@@ -58,7 +61,7 @@ public final class ViewfinderView extends View {
|
||||
private static final long ANIMATION_DELAY = 15L;
|
||||
private static final int CURRENT_POINT_OPACITY = 0xA0;
|
||||
private static final int MAX_RESULT_POINTS = 20;
|
||||
private static final int POINT_SIZE = 8;
|
||||
private static final int POINT_SIZE = 20;
|
||||
|
||||
private static final int CORNER_RECT_WIDTH = 8; //扫描区边角的宽
|
||||
private static final int CORNER_RECT_HEIGHT = 40; //扫描区边角的高
|
||||
@@ -67,7 +70,6 @@ public final class ViewfinderView extends View {
|
||||
|
||||
private Paint paint;
|
||||
private TextPaint textPaint;
|
||||
private Bitmap resultBitmap;
|
||||
private int maskColor;
|
||||
//扫描区域边框颜色
|
||||
private int frameColor;
|
||||
@@ -217,7 +219,7 @@ public final class ViewfinderView extends View {
|
||||
this.labelText = labelText;
|
||||
}
|
||||
|
||||
public void setLabelTextColor(int color) {
|
||||
public void setLabelTextColor(@ColorInt int color) {
|
||||
this.labelTextColor = color;
|
||||
}
|
||||
|
||||
@@ -256,31 +258,23 @@ public final class ViewfinderView extends View {
|
||||
|
||||
// Draw the exterior (i.e. outside the framing rect) darkened
|
||||
drawExterior(canvas,frame,width,height);
|
||||
|
||||
if (resultBitmap != null) {
|
||||
// Draw the opaque result bitmap over the scanning rectangle
|
||||
paint.setAlpha(CURRENT_POINT_OPACITY);
|
||||
canvas.drawBitmap(resultBitmap, null, frame, paint);
|
||||
} else {
|
||||
|
||||
// Draw a red "laser scanner" line through the middle to show decoding is active
|
||||
drawLaserScanner(canvas,frame);
|
||||
// Draw a two pixel solid black border inside the framing rect
|
||||
drawFrame(canvas, frame);
|
||||
// 绘制边角
|
||||
drawCorner(canvas, frame);
|
||||
//绘制提示信息
|
||||
drawTextInfo(canvas, frame);
|
||||
//绘制扫码结果点
|
||||
drawResultPoint(canvas,frame);
|
||||
// Request another update at the animation interval, but only repaint the laser line,
|
||||
// not the entire viewfinder mask.
|
||||
postInvalidateDelayed(ANIMATION_DELAY,
|
||||
frame.left - POINT_SIZE,
|
||||
frame.top - POINT_SIZE,
|
||||
frame.right + POINT_SIZE,
|
||||
frame.bottom + POINT_SIZE);
|
||||
}
|
||||
// Draw a red "laser scanner" line through the middle to show decoding is active
|
||||
drawLaserScanner(canvas,frame);
|
||||
// Draw a two pixel solid black border inside the framing rect
|
||||
drawFrame(canvas, frame);
|
||||
// 绘制边角
|
||||
drawCorner(canvas, frame);
|
||||
//绘制提示信息
|
||||
drawTextInfo(canvas, frame);
|
||||
//绘制扫码结果点
|
||||
drawResultPoint(canvas,frame);
|
||||
// Request another update at the animation interval, but only repaint the laser line,
|
||||
// not the entire viewfinder mask.
|
||||
postInvalidateDelayed(ANIMATION_DELAY,
|
||||
frame.left - POINT_SIZE,
|
||||
frame.top - POINT_SIZE,
|
||||
frame.right + POINT_SIZE,
|
||||
frame.bottom + POINT_SIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -469,12 +463,9 @@ public final class ViewfinderView extends View {
|
||||
paint.setAlpha(CURRENT_POINT_OPACITY);
|
||||
paint.setColor(resultPointColor);
|
||||
synchronized (currentPossible) {
|
||||
float radius = POINT_SIZE / 2.0f;
|
||||
for (ResultPoint point : currentPossible) {
|
||||
if(point.getX()<frame.left || point.getX()>frame.right ||
|
||||
point.getY()<frame.top || point.getY()>frame.bottom){
|
||||
continue;
|
||||
}
|
||||
canvas.drawCircle( point.getX(),point.getY(), POINT_SIZE, paint);
|
||||
canvas.drawCircle( point.getX(),point.getY(), radius, paint);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -484,10 +475,6 @@ public final class ViewfinderView extends View {
|
||||
synchronized (currentLast) {
|
||||
float radius = POINT_SIZE / 2.0f;
|
||||
for (ResultPoint point : currentLast) {
|
||||
if(point.getX()<frame.left || point.getX()>frame.right ||
|
||||
point.getY()<frame.top || point.getY()>frame.bottom){
|
||||
continue;
|
||||
}
|
||||
canvas.drawCircle( point.getX(),point.getY(), radius, paint);
|
||||
}
|
||||
}
|
||||
@@ -495,11 +482,6 @@ public final class ViewfinderView extends View {
|
||||
}
|
||||
|
||||
public void drawViewfinder() {
|
||||
Bitmap resultBitmap = this.resultBitmap;
|
||||
this.resultBitmap = null;
|
||||
if (resultBitmap != null) {
|
||||
resultBitmap.recycle();
|
||||
}
|
||||
invalidate();
|
||||
}
|
||||
|
||||
@@ -519,15 +501,6 @@ public final class ViewfinderView extends View {
|
||||
isShowResultPoint = showResultPoint;
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Draw a bitmap with the result points highlighted instead of the live scanning display.
|
||||
// *
|
||||
// * @param barcode An image of the decoded barcode.
|
||||
// */
|
||||
// public void drawResultBitmap(Bitmap barcode) {
|
||||
// resultBitmap = barcode;
|
||||
// invalidate();
|
||||
// }
|
||||
|
||||
public void addPossibleResultPoint(ResultPoint point) {
|
||||
if(isShowResultPoint){
|
||||
@@ -544,4 +517,6 @@ public final class ViewfinderView extends View {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -21,6 +21,7 @@ import android.content.Context;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.hardware.Camera;
|
||||
import android.media.FaceDetector;
|
||||
import android.os.Handler;
|
||||
import android.util.Log;
|
||||
import android.view.SurfaceHolder;
|
||||
@@ -58,6 +59,7 @@ public final class CameraManager {
|
||||
private int requestedCameraId = OpenCameraInterface.NO_REQUESTED_CAMERA;
|
||||
private int requestedFramingRectWidth;
|
||||
private int requestedFramingRectHeight;
|
||||
private boolean isFullScreenScan;
|
||||
|
||||
/**
|
||||
* Preview frames are delivered here, which we pass on to the registered handler. Make sure to
|
||||
@@ -221,35 +223,29 @@ public final class CameraManager {
|
||||
if (camera == null) {
|
||||
return null;
|
||||
}
|
||||
Point screenResolution = configManager.getScreenResolution();
|
||||
if (screenResolution == null) {
|
||||
Point point = configManager.getCameraResolution();
|
||||
if (point == null) {
|
||||
// Called early, before init even finished
|
||||
return null;
|
||||
}
|
||||
|
||||
int width = findDesiredDimensionInRange(screenResolution.x, MIN_FRAME_WIDTH, MAX_FRAME_WIDTH);
|
||||
int height = findDesiredDimensionInRange(screenResolution.y, MIN_FRAME_HEIGHT, MAX_FRAME_HEIGHT);
|
||||
int width = point.x;
|
||||
int height = point.y;
|
||||
|
||||
int size = Math.min(width,height);
|
||||
if(isFullScreenScan){
|
||||
framingRect = new Rect(0,0,width,height);
|
||||
}else{
|
||||
int size = Math.min(width,height);
|
||||
|
||||
int leftOffset = (width - size) / 2;
|
||||
int topOffset = (height - size) / 2;
|
||||
framingRect = new Rect(leftOffset, topOffset, leftOffset + size, topOffset + size);
|
||||
}
|
||||
|
||||
int leftOffset = (screenResolution.x - size) / 2;
|
||||
int topOffset = (screenResolution.y - size) / 2;
|
||||
framingRect = new Rect(leftOffset, topOffset, leftOffset + size, topOffset + size);
|
||||
Log.d(TAG, "Calculated framing rect: " + framingRect);
|
||||
}
|
||||
return framingRect;
|
||||
}
|
||||
|
||||
private static int findDesiredDimensionInRange(int resolution, int hardMin, int hardMax) {
|
||||
int dim = 5 * resolution / 8; // Target 5/8 of each dimension
|
||||
if (dim < hardMin) {
|
||||
return hardMin;
|
||||
}
|
||||
if (dim > hardMax) {
|
||||
return hardMax;
|
||||
}
|
||||
return dim;
|
||||
}
|
||||
|
||||
/**
|
||||
* Like {@link #getFramingRect} but coordinates are in terms of the preview frame,
|
||||
@@ -270,6 +266,7 @@ public final class CameraManager {
|
||||
// Called early, before init even finished
|
||||
return null;
|
||||
}
|
||||
|
||||
// rect.left = rect.left * cameraResolution.x / screenResolution.x;
|
||||
// rect.right = rect.right * cameraResolution.x / screenResolution.x;
|
||||
// rect.top = rect.top * cameraResolution.y / screenResolution.y;
|
||||
@@ -280,11 +277,28 @@ public final class CameraManager {
|
||||
rect.top = rect.top * cameraResolution.x / screenResolution.y;
|
||||
rect.bottom = rect.bottom * cameraResolution.x / screenResolution.y;
|
||||
|
||||
|
||||
framingRectInPreview = rect;
|
||||
}
|
||||
|
||||
return framingRectInPreview;
|
||||
}
|
||||
|
||||
public boolean isFullScreenScan() {
|
||||
return isFullScreenScan;
|
||||
}
|
||||
|
||||
public void setFullScreenScan(boolean fullScreenScan) {
|
||||
isFullScreenScan = fullScreenScan;
|
||||
}
|
||||
|
||||
public Point getCameraResolution() {
|
||||
return configManager.getCameraResolution();
|
||||
}
|
||||
|
||||
public Point getScreenResolution() {
|
||||
return configManager.getScreenResolution();
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows third party apps to specify the camera ID, rather than determine
|
||||
@@ -337,12 +351,16 @@ public final class CameraManager {
|
||||
if (rect == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if(isFullScreenScan){
|
||||
return new PlanarYUVLuminanceSource(data,width,height,0,0,width,height,false);
|
||||
}
|
||||
int size = Math.min(width,height);
|
||||
int left = (width-size)/2;
|
||||
int top = (height-size)/2;
|
||||
// Go ahead and assume it's YUV rather than die.
|
||||
return new PlanarYUVLuminanceSource(data, width, height, left, top,
|
||||
left + size, top + size, false);
|
||||
size, size, false);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
//App
|
||||
def app_version = [:]
|
||||
app_version.versionCode = 9
|
||||
app_version.versionName = "1.1.0"
|
||||
app_version.versionCode = 10
|
||||
app_version.versionName = "1.1.1"
|
||||
ext.app_version = app_version
|
||||
|
||||
//build version
|
||||
|
||||
Reference in New Issue
Block a user