【问题标题】:ANDROID: Saving PreviewCallback image as a .jpg from a byte array results in a corrupt fileANDROID:将 PreviewCallback 图像保存为字节数组中的 .jpg 会导致文件损坏
【发布时间】:2026-02-03 06:55:01
【问题描述】:

我一直在扩充 QR 扫描库 Zxing,以便在扫描后立即保存照片。我被建议在 PreviewCallback.java 中的 onPreviewFrame 方法中这样做:

 public void onPreviewFrame(byte[] data, Camera camera) {
Point cameraResolution = configManager.getCameraResolution();
Handler thePreviewHandler = previewHandler;

YuvImage im = new YuvImage(data, ImageFormat.NV21, 1200,
        800, null);
        Rect r = new Rect(0, 0, 1200, 800);
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        im.compressToJpeg(r, 50, baos);

        try {
            FileOutputStream output = new FileOutputStream("/sdcard/test_jpg.jpg");
            output.write(baos.toByteArray());
            output.flush();
            output.close();

            System.out.println("Attempting to save file");
            System.out.println(data);
        } catch (FileNotFoundException e) {
            System.out.println("Saving to file failed");
        } catch (IOException e) {
            System.out.println("Saving to file failed");
        }

if (cameraResolution != null && thePreviewHandler != null) {
  Message message = thePreviewHandler.obtainMessage(previewMessage, cameraResolution.x,
      cameraResolution.y, data);
  message.sendToTarget();
  previewHandler = null;

} else {
  Log.d(TAG, "Got preview callback, but no handler or resolution available");
}}

运行此代码的结果是设置文件目录中的图像损坏。我相信这是由于每帧都运行代码。如果允许保存完整图像,有没有办法将其限制为每秒左右,或者有没有一种方法可以让图像仅在完成扫描时保存。

我有一个不太有利的工作选择,因为我可以成功保存扫描时显示的黑白图像;颜色当然是首选。


更新:代码更改为(理论上)适应任何设备上的相机分辨率。图像仍然损坏。

public void onPreviewFrame(byte[] data, Camera camera) {
Point cameraResolution = configManager.getCameraResolution();
Handler thePreviewHandler = previewHandler;

android.hardware.Camera.Parameters parameters = camera.getParameters();
android.hardware.Camera.Size size = parameters.getPictureSize();

int height = size.height;
int width = size.width;

YuvImage im = new YuvImage(data, ImageFormat.NV21, width,
        height, null);
        Rect r = new Rect(0, 0, width, height);
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        im.compressToJpeg(r, 50, baos);

        try {
            FileOutputStream output = new FileOutputStream("/sdcard/test_jpg.jpg");
            output.write(baos.toByteArray());
            output.flush();
            output.close();

            System.out.println("Attempting to save file");
            System.out.println(data);

        } catch (FileNotFoundException e) {             
            System.out.println("Saving to file failed");                
        } catch (IOException e) {               
            System.out.println("Saving to file failed");                
        }    
if (cameraResolution != null && thePreviewHandler != null) {
  Message message = thePreviewHandler.obtainMessage(previewMessage, cameraResolution.x,
      cameraResolution.y, data);
  message.sendToTarget();
  previewHandler = null;

} else {
  Log.d(TAG, "Got preview callback, but no handler or resolution available");
}}

检查 width 和 height 变量是否正确设置为 Nexus 7 的相机宽度和高度 1280x960。我相信问题来自于尝试保存每一帧图像,因为“尝试保存到文件”在 logcat 中出现的速度有点快;每秒几次。还可能值得注意的是,保存的损坏图像是方形的(ish)。

提前致谢。

【问题讨论】:

    标签: java android save photo zxing


    【解决方案1】:

    1200 x 800?你确定这是你的预览尺寸吗?检查你的参数。可能是 1280 x 720

    【讨论】:

    • 是的,它是相机,检查您的相机预览尺寸
    • 如何找到任何设备的相机高度和宽度?我已经通过 Camera.getParamters 看到了它,但我找不到合适的示例代码。
    • OP 更新为适合任何相机尺寸的内容,图像仍然损坏。
    • 你应该使用getPreviewSize()而不是getPictureSize(),我认为它们是不同的。试一试
    • 谢谢,现在可以成功了,但是我没有办法在扫描时只保存一张照片。我将提出一个新问题来解决这个问题。再次感谢。