Bladeren bron

优化从相册选择

詹子聪 5 jaren geleden
bovenliggende
commit
ae86e3c968

+ 180 - 0
app/src/main/java/com/miekir/ocr/tool/ImageOrientation.java

@@ -0,0 +1,180 @@
+package com.miekir.ocr.tool;
+
+import android.content.ContentUris;
+import android.content.Context;
+import android.database.Cursor;
+import android.graphics.Bitmap;
+import android.graphics.Matrix;
+import android.media.ExifInterface;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Environment;
+import android.provider.DocumentsContract;
+import android.provider.MediaStore;
+
+import java.io.IOException;
+
+public class ImageOrientation {
+
+
+    public static Bitmap modifyOrientation(String filePath, Bitmap bitmap) throws IOException {
+        ExifInterface ei = new ExifInterface(filePath);
+        int orientation = ei.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
+
+        switch (orientation) {
+            case ExifInterface.ORIENTATION_ROTATE_90:
+                return rotate(bitmap, 90);
+
+            case ExifInterface.ORIENTATION_ROTATE_180:
+                return rotate(bitmap, 180);
+
+            case ExifInterface.ORIENTATION_ROTATE_270:
+                return rotate(bitmap, 270);
+
+            case ExifInterface.ORIENTATION_FLIP_HORIZONTAL:
+                return flip(bitmap, true, false);
+
+            case ExifInterface.ORIENTATION_FLIP_VERTICAL:
+                return flip(bitmap, false, true);
+
+            default:
+                return bitmap;
+        }
+    }
+
+    public static String getPath(final Context context, final Uri uri) {
+
+        final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
+
+        // DocumentProvider
+        if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
+            // ExternalStorageProvider
+            if (isExternalStorageDocument(uri)) {
+                final String docId = DocumentsContract.getDocumentId(uri);
+                final String[] split = docId.split(":");
+                final String type = split[0];
+
+                if ("primary".equalsIgnoreCase(type)) {
+                    return Environment.getExternalStorageDirectory() + "/" + split[1];
+                }
+
+                // TODO handle non-primary volumes
+            }
+            // DownloadsProvider
+            else if (isDownloadsDocument(uri)) {
+
+                final String id = DocumentsContract.getDocumentId(uri);
+                final Uri contentUri = ContentUris.withAppendedId(
+                        Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
+
+                return getDataColumn(context, contentUri, null, null);
+            }
+            // MediaProvider
+            else if (isMediaDocument(uri)) {
+                final String docId = DocumentsContract.getDocumentId(uri);
+                final String[] split = docId.split(":");
+                final String type = split[0];
+
+                Uri contentUri = null;
+                if ("image".equals(type)) {
+                    contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
+                } else if ("video".equals(type)) {
+                    contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
+                } else if ("audio".equals(type)) {
+                    contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
+                }
+
+                final String selection = "_id=?";
+                final String[] selectionArgs = new String[]{
+                        split[1]
+                };
+
+                return getDataColumn(context, contentUri, selection, selectionArgs);
+            }
+        }
+        // MediaStore (and general)
+        else if ("content".equalsIgnoreCase(uri.getScheme())) {
+            return getDataColumn(context, uri, null, null);
+        }
+        // File
+        else if ("file".equalsIgnoreCase(uri.getScheme())) {
+            return uri.getPath();
+        }
+
+        return null;
+    }
+
+    /**
+     * Get the value of the data column for this Uri. This is useful for
+     * MediaStore Uris, and other file-based ContentProviders.
+     *
+     * @param context       The context.
+     * @param uri           The Uri to query.
+     * @param selection     (Optional) Filter used in the query.
+     * @param selectionArgs (Optional) Selection arguments used in the query.
+     * @return The value of the _data column, which is typically a file path.
+     */
+    private static String getDataColumn(Context context, Uri uri, String selection,
+                                        String[] selectionArgs) {
+
+        Cursor cursor = null;
+        final String column = "_data";
+        final String[] projection = {
+                column
+        };
+
+        try {
+            cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
+                    null);
+            if (cursor != null && cursor.moveToFirst()) {
+                final int column_index = cursor.getColumnIndexOrThrow(column);
+                return cursor.getString(column_index);
+            }
+        } finally {
+            if (cursor != null) {
+                cursor.close();
+            }
+        }
+        return null;
+    }
+
+
+    /**
+     * @param uri The Uri to check.
+     * @return Whether the Uri authority is ExternalStorageProvider.
+     */
+    private static boolean isExternalStorageDocument(Uri uri) {
+        return "com.android.externalstorage.documents".equals(uri.getAuthority());
+    }
+
+    /**
+     * @param uri The Uri to check.
+     * @return Whether the Uri authority is DownloadsProvider.
+     */
+    private static boolean isDownloadsDocument(Uri uri) {
+        return "com.android.providers.downloads.documents".equals(uri.getAuthority());
+    }
+
+    /**
+     * @param uri The Uri to check.
+     * @return Whether the Uri authority is MediaProvider.
+     */
+    private static boolean isMediaDocument(Uri uri) {
+        return "com.android.providers.media.documents".equals(uri.getAuthority());
+    }
+
+
+    private static Bitmap rotate(Bitmap bitmap, float degrees) {
+        Matrix matrix = new Matrix();
+        matrix.postRotate(degrees);
+        return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
+    }
+
+    private static Bitmap flip(Bitmap bitmap, boolean horizontal, boolean vertical) {
+        Matrix matrix = new Matrix();
+        matrix.preScale(horizontal ? -1 : 1, vertical ? -1 : 1);
+        return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
+    }
+
+
+}

+ 2 - 1
app/src/main/java/com/miekir/ocr/tool/ImageUtil.java

@@ -82,7 +82,7 @@ public final class ImageUtil {
             }
 
             BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
-            compressedBitmap.compress(Bitmap.CompressFormat.JPEG, 98, bos);
+            compressedBitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);
             bos.flush();
             bos.close();
             return true;
@@ -164,4 +164,5 @@ public final class ImageUtil {
 
         return BitmapFactory.decodeStream(imageStream);
     }
+
 }

+ 8 - 90
app/src/main/java/com/miekir/ocr/ui/OperationPresenter.java

@@ -16,6 +16,7 @@ import com.miekir.ocr.api.ApiService;
 import com.miekir.ocr.bean.OcrResult;
 import com.miekir.ocr.tool.Base64Tool;
 import com.miekir.ocr.tool.DateTool;
+import com.miekir.ocr.tool.ImageOrientation;
 import com.miekir.ocr.tool.ImageUtil;
 
 import java.io.File;
@@ -51,8 +52,13 @@ public class OperationPresenter extends BasePresenter<IOperationView> {
             public void subscribe(ObservableEmitter<String> emitter) throws Exception {
                 // 根据URI获取图片的base64字符串
                 String photoBase64 = null;
-                // 这个需要顺时针旋转90度才正常
-                Bitmap rotatedBitmap = ImageUtil.rotateBitmap90(ImageUtil.getBitmapFromUri(context, uri));
+                // 这个如果是竖屏拍的照片,需要顺时针旋转90度才正常
+                Bitmap rawBitmap = ImageUtil.getBitmapFromUri(context, uri);
+                String filePath = ImageOrientation.getPath(context, uri);
+                Bitmap rotatedBitmap = null;
+                if (!TextUtils.isEmpty(filePath)) {
+                    rotatedBitmap = ImageOrientation.modifyOrientation(filePath, rawBitmap);
+                }
 
                 if (rotatedBitmap == null) {
                     photoBase64 = Base64Tool.getBase64FromUri(context, uri);
@@ -148,94 +154,6 @@ public class OperationPresenter extends BasePresenter<IOperationView> {
                 });
     }
 
-    /**
-     * @param context
-     * @param rawPhotoBytes 原图
-     * @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 isScreenLandscape) {
         getView().showLoading(context.getResources().getString(R.string.loading));
         int mLeft = rectData[0];