Kaynağa Gözat

解决了拍照慢,但是有旋转

詹子聪 5 yıl önce
ebeveyn
işleme
ad4fc6ee9e

+ 19 - 0
app/src/main/java/com/miekir/ocr/tool/FileManager.java

@@ -0,0 +1,19 @@
+package com.miekir.ocr.tool;
+
+import java.io.BufferedOutputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+public final class FileManager {
+    public static void writeFrame(String fileName, byte[] data) {
+        try {
+            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(fileName));
+            bos.write(data);
+            bos.flush();
+            bos.close();
+//            Log.e(TAG, "" + data.length + " bytes have been written to " + filesDir + fileName + ".jpg");
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+}

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

@@ -0,0 +1,128 @@
+package com.miekir.ocr.tool;
+
+import android.graphics.ImageFormat;
+import android.graphics.Rect;
+import android.graphics.YuvImage;
+import android.media.Image;
+
+import java.io.ByteArrayOutputStream;
+import java.nio.ByteBuffer;
+import java.nio.ReadOnlyBufferException;
+
+public final class ImageUtil {
+
+    public static byte[] imageToByteArray(Image image) {
+        byte[] data = null;
+        if (image.getFormat() == ImageFormat.JPEG) {
+            Image.Plane[] planes = image.getPlanes();
+            ByteBuffer buffer = planes[0].getBuffer();
+            data = new byte[buffer.capacity()];
+            buffer.get(data);
+            return data;
+        } else if (image.getFormat() == ImageFormat.YUV_420_888) {
+            data = NV21toJPEG(
+                    YUV_420_888toNV21(image),
+                    image.getWidth(), image.getHeight());
+        }
+        return data;
+    }
+
+    private static byte[] YUV_420_888toNV21(Image image) {
+        byte[] nv21;
+        ByteBuffer yBuffer = image.getPlanes()[0].getBuffer();
+        ByteBuffer uBuffer = image.getPlanes()[1].getBuffer();
+        ByteBuffer vBuffer = image.getPlanes()[2].getBuffer();
+
+        int ySize = yBuffer.remaining();
+        int uSize = uBuffer.remaining();
+        int vSize = vBuffer.remaining();
+
+        nv21 = new byte[ySize + uSize + vSize];
+
+        //U and V are swapped
+        yBuffer.get(nv21, 0, ySize);
+        vBuffer.get(nv21, ySize, vSize);
+        uBuffer.get(nv21, ySize + vSize, uSize);
+
+        return nv21;
+    }
+
+
+    private static byte[] NV21toJPEG(byte[] nv21, int width, int height) {
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        YuvImage yuv = new YuvImage(nv21, ImageFormat.NV21, width, height, null);
+        yuv.compressToJpeg(new Rect(0, 0, width, height), 100, out);
+        return out.toByteArray();
+    }
+
+
+    private static byte[] YUV_420_888toNV21Accept(Image image) {
+        int width = image.getWidth();
+        int height = image.getHeight();
+        int ySize = width * height;
+        int uvSize = width * height / 4;
+
+        byte[] nv21 = new byte[ySize + uvSize * 2];
+
+        ByteBuffer yBuffer = image.getPlanes()[0].getBuffer(); // Y
+        ByteBuffer uBuffer = image.getPlanes()[1].getBuffer(); // U
+        ByteBuffer vBuffer = image.getPlanes()[2].getBuffer(); // V
+
+        int rowStride = image.getPlanes()[0].getRowStride();
+        assert (image.getPlanes()[0].getPixelStride() == 1);
+
+        int pos = 0;
+
+        if (rowStride == width) { // likely
+            yBuffer.get(nv21, 0, ySize);
+            pos += ySize;
+        } else {
+            int yBufferPos = width - rowStride; // not an actual position
+            for (; pos < ySize; pos += width) {
+                yBufferPos += rowStride - width;
+                yBuffer.position(yBufferPos);
+                yBuffer.get(nv21, pos, width);
+            }
+        }
+
+        rowStride = image.getPlanes()[2].getRowStride();
+        int pixelStride = image.getPlanes()[2].getPixelStride();
+
+        assert (rowStride == image.getPlanes()[1].getRowStride());
+        assert (pixelStride == image.getPlanes()[1].getPixelStride());
+
+        if (pixelStride == 2 && rowStride == width && uBuffer.get(0) == vBuffer.get(1)) {
+            // maybe V an U planes overlap as per NV21, which means vBuffer[1] is alias of uBuffer[0]
+            byte savePixel = vBuffer.get(1);
+            try {
+                vBuffer.put(1, (byte) ~savePixel);
+                if (uBuffer.get(0) == (byte) ~savePixel) {
+                    vBuffer.put(1, savePixel);
+                    vBuffer.get(nv21, ySize, uvSize);
+
+                    return nv21; // shortcut
+                }
+
+
+                // unfortunately, the check failed. We must save U and V pixel by pixel
+                vBuffer.put(1, savePixel);
+            } catch (ReadOnlyBufferException ex) {
+                // unfortunately, we cannot check if vBuffer and uBuffer overlap
+            }
+
+            // other optimizations could check if (pixelStride == 1) or (pixelStride == 2),
+            // but performance gain would be less significant
+
+            for (int row = 0; row < height / 2; row++) {
+                for (int col = 0; col < width / 2; col++) {
+                    int vuPos = col * pixelStride + row * rowStride;
+                    nv21[pos++] = vBuffer.get(vuPos);
+                    nv21[pos++] = uBuffer.get(vuPos);
+                }
+            }
+        }
+        return nv21;
+    }
+
+
+}

+ 17 - 9
app/src/main/java/com/miekir/ocr/ui/CameraActivity.java

@@ -37,14 +37,14 @@ import androidx.annotation.NonNull;
 import com.miekir.ocr.R;
 import com.miekir.ocr.base.BaseCameraActivity;
 import com.miekir.ocr.tool.CameraPreviewTool;
+import com.miekir.ocr.tool.FileManager;
+import com.miekir.ocr.tool.ImageUtil;
 import com.miekir.ocr.widget.AutoFitTextureView;
 
 import java.io.File;
-import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.OutputStream;
-import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -387,7 +387,9 @@ public class CameraActivity extends BaseCameraActivity {
                 width = jpegSizes[0].getWidth();
                 height = jpegSizes[0].getHeight();
             }
-            ImageReader reader = ImageReader.newInstance(width, height, ImageFormat.JPEG, 1);
+            //ImageReader reader = ImageReader.newInstance(width, height, ImageFormat.JPEG, 1);
+            // 解决拍照慢的问题
+            ImageReader reader = ImageReader.newInstance(width, height, ImageFormat.YUV_420_888, 1);
             List<Surface> outputSurfaces = new ArrayList<Surface>(2);
             outputSurfaces.add(reader.getSurface());
             outputSurfaces.add(new Surface(textureView.getSurfaceTexture()));
@@ -436,7 +438,17 @@ public class CameraActivity extends BaseCameraActivity {
         @Override
         public void onImageAvailable(ImageReader reader) {
 
-            Image image = null;
+            // YUV_420_888转换成jpg
+            Image image = reader.acquireLatestImage();
+            if (image != null) {
+                //converting to JPEG
+                byte[] jpegData = ImageUtil.imageToByteArray(image);
+                //write to file (for example ..some_path/frame.jpg)
+                FileManager.writeFrame(file.getAbsolutePath(), jpegData);
+                image.close();
+            }
+
+            /*Image image = null;
             try {
                 image = reader.acquireLatestImage();
                 ByteBuffer buffer = image.getPlanes()[0].getBuffer();
@@ -451,7 +463,7 @@ public class CameraActivity extends BaseCameraActivity {
                 if (image != null) {
                     image.close();
                 }
-            }
+            }*/
         }
 
         private void save(byte[] bytes) throws IOException {
@@ -468,8 +480,4 @@ public class CameraActivity extends BaseCameraActivity {
     };
 
 
-
-
-
-
 }

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

@@ -54,7 +54,7 @@ public class OperationActivity extends CameraActivity implements CropView.onLoca
         // 裁剪View
         pcv_scan = findViewById(R.id.pcv_scan);
         pcv_scan.setLocationListener(this);
-        showResultDialog(null);
+        //showResultDialog(null);
     }
 
     @Override