|
|
@@ -18,6 +18,7 @@ import com.miekir.ocr.tool.DateTool;
|
|
|
import com.miekir.ocr.tool.ImageUtil;
|
|
|
|
|
|
import java.io.File;
|
|
|
+import java.math.BigDecimal;
|
|
|
import java.util.HashMap;
|
|
|
import java.util.Map;
|
|
|
|
|
|
@@ -28,7 +29,6 @@ import io.reactivex.android.schedulers.AndroidSchedulers;
|
|
|
import io.reactivex.schedulers.Schedulers;
|
|
|
|
|
|
/**
|
|
|
- *
|
|
|
* @author 詹子聪
|
|
|
* @date 2020/7/27 15:53
|
|
|
* Description: 操作的事务
|
|
|
@@ -36,10 +36,9 @@ import io.reactivex.schedulers.Schedulers;
|
|
|
public class OperationPresenter extends BasePresenter<IOperationView> {
|
|
|
|
|
|
/**
|
|
|
- *
|
|
|
* @param context
|
|
|
- * @param uri 图片
|
|
|
- * @param scene 识别场景类型
|
|
|
+ * @param uri 图片
|
|
|
+ * @param scene 识别场景类型
|
|
|
*/
|
|
|
public void startOcrFromUri(Context context, Uri uri, String scene) {
|
|
|
getView().showLoading(context.getResources().getString(R.string.loading));
|
|
|
@@ -53,52 +52,135 @@ public class OperationPresenter extends BasePresenter<IOperationView> {
|
|
|
} else {
|
|
|
emitter.onNext(photoBase64);
|
|
|
}
|
|
|
- }})
|
|
|
- /*.filter(base64String -> {
|
|
|
- // 图片base64不为空才继续,否则直接忽略,没有任何回调会被调用
|
|
|
- return !TextUtils.isEmpty(base64String);
|
|
|
- })*/
|
|
|
- .flatMap(photoBase64 -> {
|
|
|
- Map<String, Object> requestParams = new HashMap<>();
|
|
|
- requestParams.put("request_id", "035992000119071904311742_"+ DateTool.getRequestId());
|
|
|
- requestParams.put("appid", "10233937");
|
|
|
- requestParams.put("image", photoBase64);
|
|
|
- Map<String, Object> options = new HashMap<>();
|
|
|
- options.put("scene", scene);
|
|
|
- requestParams.put("options", options);
|
|
|
-
|
|
|
- // 发送识别请求
|
|
|
- return RetrofitHelper.getInstance()
|
|
|
- .getRequestApi(ApiService.class)
|
|
|
- .getOcrResult(requestParams);
|
|
|
- })
|
|
|
- .subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
|
|
|
- .subscribe(new BaseObserver<OcrResult>() {
|
|
|
- @Override
|
|
|
- public void onSuccess(OcrResult result) {
|
|
|
- if (getView() != null) {
|
|
|
- getView().dismissLoading();
|
|
|
- getView().onOcrResult(result);
|
|
|
+ }
|
|
|
+ })
|
|
|
+ /*.filter(base64String -> {
|
|
|
+ // 图片base64不为空才继续,否则直接忽略,没有任何回调会被调用
|
|
|
+ return !TextUtils.isEmpty(base64String);
|
|
|
+ })*/
|
|
|
+ .flatMap(photoBase64 -> {
|
|
|
+ Map<String, Object> requestParams = new HashMap<>();
|
|
|
+ requestParams.put("request_id", "035992000119071904311742_" + DateTool.getRequestId());
|
|
|
+ requestParams.put("appid", "10233937");
|
|
|
+ requestParams.put("image", photoBase64);
|
|
|
+ Map<String, Object> options = new HashMap<>();
|
|
|
+ options.put("scene", scene);
|
|
|
+ requestParams.put("options", options);
|
|
|
+
|
|
|
+ // 发送识别请求
|
|
|
+ return RetrofitHelper.getInstance()
|
|
|
+ .getRequestApi(ApiService.class)
|
|
|
+ .getOcrResult(requestParams);
|
|
|
+ })
|
|
|
+ .subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
|
|
|
+ .subscribe(new BaseObserver<OcrResult>() {
|
|
|
+ @Override
|
|
|
+ public void onSuccess(OcrResult result) {
|
|
|
+ if (getView() != null) {
|
|
|
+ getView().dismissLoading();
|
|
|
+ getView().onOcrResult(result);
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- @Override
|
|
|
- public void onFailure(Throwable e, String errMsg) {
|
|
|
- // 装饰器模式
|
|
|
- if (getView() != null) {
|
|
|
- getView().dismissLoading();
|
|
|
- getView().onOcrResult(null);
|
|
|
+ @Override
|
|
|
+ public void onFailure(Throwable e, String errMsg) {
|
|
|
+ // 装饰器模式
|
|
|
+ if (getView() != null) {
|
|
|
+ getView().dismissLoading();
|
|
|
+ getView().onOcrResult(null);
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
- });
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- *
|
|
|
* @param context
|
|
|
* @param rawPhotoBytes 原图
|
|
|
- * @param scene 识别场景类型
|
|
|
+ * @param scene 识别场景类型
|
|
|
*/
|
|
|
+// public void startOcrFromFile(Context context, byte[] rawPhotoBytes, int[] rectData, File file, String scene, boolean isLandscape) {
|
|
|
+// getView().showLoading(context.getResources().getString(R.string.loading));
|
|
|
+// int mLeft = rectData[0];
|
|
|
+// int mTop = rectData[1];
|
|
|
+// int mRight = rectData[2];
|
|
|
+// int mBottom = rectData[3];
|
|
|
+// Observable.create(new ObservableOnSubscribe<String>() {
|
|
|
+// @Override
|
|
|
+// public void subscribe(ObservableEmitter<String> emitter) throws Exception {
|
|
|
+// Bitmap originalBmp = BitmapFactory.decodeByteArray(rawPhotoBytes , 0, rawPhotoBytes.length);
|
|
|
+// // 这里由于要快速拍照,使用的格式是ImageFormat.YUV_420_888,导致拍出来的照片自动逆时针90度,所以要转换裁剪位置
|
|
|
+// int newLeft = mTop*originalBmp.getHeight()/ SizeTool.SCREEN_WIDTH;
|
|
|
+// int newTop = (SizeTool.SCREEN_WIDTH-mRight)*originalBmp.getHeight()/ SizeTool.SCREEN_WIDTH;
|
|
|
+// int newWidth = (mBottom-mTop)*originalBmp.getHeight()/ SizeTool.SCREEN_WIDTH;
|
|
|
+// int newHeight = (mRight-mLeft)*originalBmp.getHeight()/ SizeTool.SCREEN_WIDTH;
|
|
|
+// Bitmap croppedBmp = Bitmap.createBitmap(originalBmp, newLeft, newTop, newWidth, newHeight);
|
|
|
+// // 旋转90度,让OCR可以识别
|
|
|
+// Bitmap rotatedBitmap;
|
|
|
+// if (isLandscape) {
|
|
|
+// rotatedBitmap = croppedBmp;
|
|
|
+// } else {
|
|
|
+// rotatedBitmap = ImageUtil.rotateBitmap90(croppedBmp);
|
|
|
+// }
|
|
|
+//
|
|
|
+// if (!file.getParentFile().exists()) {
|
|
|
+// file.mkdirs();
|
|
|
+// }
|
|
|
+// // todo 压缩图片
|
|
|
+// boolean saveCropSuccess = ImageUtil.saveBitmapFile(rotatedBitmap, file);
|
|
|
+// originalBmp.recycle();
|
|
|
+// croppedBmp.recycle();
|
|
|
+// rotatedBitmap.recycle();
|
|
|
+// if (saveCropSuccess) {
|
|
|
+// // 保存最终截图成功
|
|
|
+// // 根据URI获取图片的base64字符串
|
|
|
+// String photoBase64 = Base64Tool.getBase64FromFilePath(file.getAbsolutePath());
|
|
|
+// if (TextUtils.isEmpty(photoBase64)) {
|
|
|
+// emitter.onError(new Exception("Empty image"));
|
|
|
+// } else {
|
|
|
+// emitter.onNext(photoBase64);
|
|
|
+// }
|
|
|
+// } else {
|
|
|
+// emitter.onNext("Crop photo error");
|
|
|
+// }
|
|
|
+// }})
|
|
|
+// /*.filter(base64String -> {
|
|
|
+// // 图片base64不为空才继续,否则直接忽略,没有任何回调会被调用
|
|
|
+// return !TextUtils.isEmpty(base64String);
|
|
|
+// })*/
|
|
|
+// .flatMap(photoBase64 -> {
|
|
|
+// Map<String, Object> requestParams = new HashMap<>();
|
|
|
+// requestParams.put("request_id", "035992000119071904311742_"+ DateTool.getRequestId());
|
|
|
+// requestParams.put("appid", "10233937");
|
|
|
+// requestParams.put("image", photoBase64);
|
|
|
+// Map<String, Object> options = new HashMap<>();
|
|
|
+// options.put("scene", scene);
|
|
|
+// requestParams.put("options", options);
|
|
|
+//
|
|
|
+// // 发送识别请求
|
|
|
+// return RetrofitHelper.getInstance()
|
|
|
+// .getRequestApi(ApiService.class)
|
|
|
+// .getOcrResult(requestParams);
|
|
|
+// })
|
|
|
+// .subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
|
|
|
+// .subscribe(new BaseObserver<OcrResult>() {
|
|
|
+// @Override
|
|
|
+// public void onSuccess(OcrResult result) {
|
|
|
+// if (getView() != null) {
|
|
|
+// getView().dismissLoading();
|
|
|
+// getView().onOcrResult(result);
|
|
|
+// }
|
|
|
+// }
|
|
|
+//
|
|
|
+// @Override
|
|
|
+// public void onFailure(Throwable e, String errMsg) {
|
|
|
+// // 装饰器模式
|
|
|
+// if (getView() != null) {
|
|
|
+// getView().dismissLoading();
|
|
|
+// getView().onOcrResult(null);
|
|
|
+// }
|
|
|
+// }
|
|
|
+// });
|
|
|
+// }
|
|
|
public void startOcrFromFile(Context context, byte[] rawPhotoBytes, int[] rectData, File file, String scene, boolean isLandscape) {
|
|
|
getView().showLoading(context.getResources().getString(R.string.loading));
|
|
|
int mLeft = rectData[0];
|
|
|
@@ -108,19 +190,69 @@ public class OperationPresenter extends BasePresenter<IOperationView> {
|
|
|
Observable.create(new ObservableOnSubscribe<String>() {
|
|
|
@Override
|
|
|
public void subscribe(ObservableEmitter<String> emitter) throws Exception {
|
|
|
- Bitmap originalBmp = BitmapFactory.decodeByteArray(rawPhotoBytes , 0, rawPhotoBytes.length);
|
|
|
- // 这里由于要快速拍照,使用的格式是ImageFormat.YUV_420_888,导致拍出来的照片自动逆时针90度,所以要转换裁剪位置
|
|
|
- int newLeft = mTop*originalBmp.getHeight()/ SizeTool.SCREEN_WIDTH;
|
|
|
- int newTop = (SizeTool.SCREEN_WIDTH-mRight)*originalBmp.getHeight()/ SizeTool.SCREEN_WIDTH;
|
|
|
- int newWidth = (mBottom-mTop)*originalBmp.getHeight()/ SizeTool.SCREEN_WIDTH;
|
|
|
- int newHeight = (mRight-mLeft)*originalBmp.getHeight()/ SizeTool.SCREEN_WIDTH;
|
|
|
- Bitmap croppedBmp = Bitmap.createBitmap(originalBmp, newLeft, newTop, newWidth, newHeight);
|
|
|
+ Bitmap originalBmp = BitmapFactory.decodeByteArray(rawPhotoBytes, 0, rawPhotoBytes.length);
|
|
|
+ // 这里由于要快速拍照,使用的格式是ImageFormat.YUV_420_888,导致拍出来的照片自动逆时针90度,
|
|
|
+ // 所以要先恢复原来的图片再裁剪
|
|
|
+ Bitmap normalBitmap = ImageUtil.rotateBitmap90(originalBmp);
|
|
|
+ int normalWidth = normalBitmap.getWidth();
|
|
|
+ int normalHeight = normalBitmap.getHeight();
|
|
|
+
|
|
|
+ // 图片不旋转,以屏幕为参考系进行缩小或者放大,直到图片一条边等于屏幕的一条边,图片的另一条边大于等于屏幕的另一条边
|
|
|
+ int realLeft;
|
|
|
+ int realTop;
|
|
|
+ int realWidth;
|
|
|
+ int realHeight;
|
|
|
+
|
|
|
+ // 图片宽度与屏幕宽度的比
|
|
|
+ float widthD = 1.0f * normalWidth / SizeTool.SCREEN_WIDTH;
|
|
|
+ // 图片高度与屏幕高度的比
|
|
|
+ float heightD = 1.0f * normalHeight / mHeight;
|
|
|
+ boolean isPortraitPhoto = BigDecimal.valueOf(heightD).compareTo(BigDecimal.valueOf(widthD)) > 0;
|
|
|
+ if (isPortraitPhoto) {
|
|
|
+ // 高的倍距大,以宽为基准
|
|
|
+ if (widthD > 0) {
|
|
|
+ // 图片宽要缩小到屏幕宽
|
|
|
+ float pivot = 1.0f * normalWidth / SizeTool.SCREEN_WIDTH;
|
|
|
+ realLeft = (int) (mLeft * pivot);
|
|
|
+ realTop = (int) (mTop * pivot);
|
|
|
+ realWidth = (int) ((mRight - mLeft) * pivot);
|
|
|
+ realHeight = (int) ((mBottom - mTop) * pivot);
|
|
|
+ } else {
|
|
|
+ // 屏幕宽要缩小到图片宽
|
|
|
+ float pivot = 1.0f * normalWidth / SizeTool.SCREEN_WIDTH;
|
|
|
+ realLeft = (int) (mLeft * pivot);
|
|
|
+ realTop = (int) (mTop * pivot);
|
|
|
+ realWidth = (int) ((mRight - mLeft) * pivot);
|
|
|
+ realHeight = (int) ((mBottom - mTop) * pivot);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 宽的倍距大,以高为基准
|
|
|
+ if (heightD > 0) {
|
|
|
+ // 图片高要缩小到屏幕高
|
|
|
+ float pivot = 1.0f * normalHeight / mHeight;
|
|
|
+ realLeft = (int) (mLeft * pivot);
|
|
|
+ realTop = (int) (mTop * pivot);
|
|
|
+ realWidth = (int) ((mRight - mLeft) * pivot);
|
|
|
+ realHeight = (int) ((mBottom - mTop) * pivot);
|
|
|
+ } else {
|
|
|
+ // 屏幕高要缩小到图片高,其实一样
|
|
|
+ float pivot = 1.0f * normalHeight / mHeight;
|
|
|
+ realLeft = (int) (mLeft * pivot);
|
|
|
+ realTop = (int) (mTop * pivot);
|
|
|
+ realWidth = (int) ((mRight - mLeft) * pivot);
|
|
|
+ realHeight = (int) ((mBottom - mTop) * pivot);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ Bitmap croppedBmp = Bitmap.createBitmap(normalBitmap, realLeft, realTop, realWidth, realHeight);
|
|
|
+
|
|
|
// 旋转90度,让OCR可以识别
|
|
|
Bitmap rotatedBitmap;
|
|
|
if (isLandscape) {
|
|
|
- rotatedBitmap = croppedBmp;
|
|
|
+ rotatedBitmap = ImageUtil.rotateBitmap(croppedBmp, -90);
|
|
|
} else {
|
|
|
- rotatedBitmap = ImageUtil.rotateBitmap90(croppedBmp);
|
|
|
+ rotatedBitmap = croppedBmp;
|
|
|
}
|
|
|
|
|
|
if (!file.getParentFile().exists()) {
|
|
|
@@ -143,14 +275,15 @@ public class OperationPresenter extends BasePresenter<IOperationView> {
|
|
|
} else {
|
|
|
emitter.onNext("Crop photo error");
|
|
|
}
|
|
|
- }})
|
|
|
+ }
|
|
|
+ })
|
|
|
/*.filter(base64String -> {
|
|
|
// 图片base64不为空才继续,否则直接忽略,没有任何回调会被调用
|
|
|
return !TextUtils.isEmpty(base64String);
|
|
|
})*/
|
|
|
.flatMap(photoBase64 -> {
|
|
|
Map<String, Object> requestParams = new HashMap<>();
|
|
|
- requestParams.put("request_id", "035992000119071904311742_"+ DateTool.getRequestId());
|
|
|
+ requestParams.put("request_id", "035992000119071904311742_" + DateTool.getRequestId());
|
|
|
requestParams.put("appid", "10233937");
|
|
|
requestParams.put("image", photoBase64);
|
|
|
Map<String, Object> options = new HashMap<>();
|
|
|
@@ -182,4 +315,12 @@ public class OperationPresenter extends BasePresenter<IOperationView> {
|
|
|
}
|
|
|
});
|
|
|
}
|
|
|
+
|
|
|
+ private int mWidth = SizeTool.SCREEN_WIDTH;
|
|
|
+ private int mHeight = SizeTool.SCREEN_HEIGHT;
|
|
|
+
|
|
|
+ protected void setWidthHeight(int width, int height) {
|
|
|
+ mWidth = width;
|
|
|
+ mHeight = height;
|
|
|
+ }
|
|
|
}
|