Parcourir la source

截图规范化

詹子聪 il y a 5 ans
Parent
commit
6d051ac573

+ 11 - 0
app/src/main/java/com/miekir/ocr/tool/ImageUtil.java

@@ -84,4 +84,15 @@ public final class ImageUtil {
         Bitmap scaledBitmap = Bitmap.createScaledBitmap(rawBitmap, rawBitmap.getWidth(), rawBitmap.getHeight(), true);
         return Bitmap.createBitmap(scaledBitmap, 0, 0, scaledBitmap.getWidth(), scaledBitmap.getHeight(), matrix, true);
     }
+
+    /**
+     * 旋转
+     * @return
+     */
+    public static Bitmap rotateBitmap(Bitmap rawBitmap, int degree) {
+        Matrix matrix = new Matrix();
+        matrix.postRotate(degree);
+        Bitmap scaledBitmap = Bitmap.createScaledBitmap(rawBitmap, rawBitmap.getWidth(), rawBitmap.getHeight(), true);
+        return Bitmap.createBitmap(scaledBitmap, 0, 0, scaledBitmap.getWidth(), scaledBitmap.getHeight(), matrix, true);
+    }
 }

+ 11 - 0
app/src/main/java/com/miekir/ocr/ui/CameraActivity.java

@@ -163,6 +163,17 @@ public class CameraActivity extends BaseCameraActivity {
                iv_flash.setImageResource(R.mipmap.flash_close);
            }
         });
+
+        textureView.post(new Runnable() {
+            @Override
+            public void run() {
+                setWidthHeight(textureView.getWidth(), textureView.getHeight());
+            }
+        });
+    }
+
+    protected void setWidthHeight(int width, int height) {
+
     }
 
 

+ 5 - 0
app/src/main/java/com/miekir/ocr/ui/OperationActivity.java

@@ -278,4 +278,9 @@ public class OperationActivity extends CameraActivity implements CropView.onLoca
             tv_name.setText(String.format(ConstantString.RESULT_FORMAT, getString(R.string.name), result.name.getText()));
         }
     }
+
+    @Override
+    protected void setWidthHeight(int width, int height) {
+        mOperationPresenter.setWidthHeight(width, height);
+    }
 }

+ 193 - 52
app/src/main/java/com/miekir/ocr/ui/OperationPresenter.java

@@ -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;
+    }
 }

+ 0 - 1
mvp/src/main/java/com/miekir/mvp/base/BaseActivity.java

@@ -49,7 +49,6 @@ public abstract class BaseActivity extends AppCompatActivity {
         getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
         //mBinder = ButterKnife.bind(this);
         mLoadingDialog = new LoadingDialog(this);
-        initViews(savedInstanceState);
     }
 
     protected void hideInputMethod() {

+ 2 - 2
mvp/src/main/java/com/miekir/mvp/view/BaseMVPActivity.java

@@ -2,11 +2,9 @@ package com.miekir.mvp.view;
 
 import android.os.Bundle;
 
-import com.miekir.common.utils.ToastTool;
 import com.miekir.mvp.base.BaseActivity;
 import com.miekir.mvp.presenter.BasePresenter;
 import com.miekir.mvp.presenter.InjectPresenter;
-import com.miekir.mvp.view.IView;
 
 import java.lang.reflect.Field;
 import java.util.ArrayList;
@@ -55,6 +53,8 @@ public abstract class BaseMVPActivity extends BaseActivity implements IView {
                 }
             }
         }
+
+        initViews(savedInstanceState);
     }
 
     @Override