安卓:从相机保存的Jpeg看起来有损坏

3
我正在编写一款Android应用程序,当用户点击按钮时,它会保存来自相机的JPEG快照。不幸的是,我发现我的代码保存的JPEG文件看起来损坏了。这似乎是由于我的参数调用setPreviewSize(见下面的代码片段)引起的-如果我删除它,那么图像就可以正常保存;但是如果没有它,我就无法设置预览大小,并且setDisplayOrientation似乎也没有效果。
我的应用程序针对API级别8(Android 2.2),我在HTC Desire HD上进行调试。我不太确定我做错了什么...任何帮助都将非常感激!
谢谢, Scottie
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
    // Now that the size is known, set up the camera parameters and begin
    // the preview.
    Camera.Parameters parameters = mCamera.getParameters();        
    Camera.Size size = getBestPreviewSize(w,h);

    // This next call is required in order for preview size to be set and
    // setDisplayOrientation to take effect...
    // Unfortunately it's also causing JPEG to be created wrong
    parameters.setPreviewSize(size.width, size.height);

    parameters.setPictureFormat(ImageFormat.JPEG);
    mCamera.setParameters(parameters);
    mCamera.setDisplayOrientation(90);

    mCamera.startPreview();

}

// This is the snapshot button event handler
public void onSnapshotButtonClick(View target) {
    //void android.hardware.Camera.takePicture(ShutterCallback shutter, 
    //                              PictureCallback raw, PictureCallback jpeg)
    mPreview.mCamera.takePicture(null, null, mPictureCallback);
}


// This saves the camera snapshot as a JPEG file on the SD card
Camera.PictureCallback mPictureCallback = new Camera.PictureCallback() {
    public void onPictureTaken(byte[] imageData, Camera c) {

        if (imageData != null) {
            FileOutputStream outStream = null;
            try {
                String myJpgPath = String.format(
                        "/sdcard/%d.jpg", System.currentTimeMillis());

                outStream = new FileOutputStream(myJpgPath);
                outStream.write(imageData);
                outStream.close();
                Log.d("TestApp", "onPictureTaken - wrote bytes: "
                        + imageData.length);

                c.startPreview();
                Toast.makeText(getApplicationContext(), String.format("%s written", myJpgPath), Toast.LENGTH_SHORT).show();

            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
            }
        }
    }
};

1
我也遇到了同样的问题,但只在HTC Desire HD上出现。JPEG在三星Galaxy S和模拟器上保存正常。 - jA_cOp
@jA_cOp - 谢谢你,至少我知道不是我的问题!Android源代码中的相机应用程序运行良好,所以我将研究一下并找出差异。 - Scottie
你解决了这个问题吗?我遇到了同样的问题,只是在HTC Desire HD上。 - Ikky
@Ikky - 我还没有机会回到这个项目,等我有了更新会在这里通知你。 - Scottie
如果setPreviewSize不是必要的,尝试移除parameters.setPreviewSize参数,这对我有用。 - Ikky
2个回答

4

另一个解决方法是匹配预览和图片尺寸的宽高比(即使用setPreviewSize(w1,h1); setPictureSize(w2,h2),其中w1/h1 与 w2/h2 相近(稍微有些差异似乎也没问题))。例如,对于Desire HD S,w1=800,h1=480,w2=2592,h2=1552与w1=960,h1=720,h2=2592,h2=1952一样有效(如果您不介意图像失真的话;-))


我可以在我的HTC Desire S设备上确认这一点。顺便说一下,在此设备上的本机相机应用程序中,您可以在设置中定义纵横比(4:3或5:3)和分辨率。可用分辨率列表取决于纵横比,因为它们似乎需要匹配。 - guillaume-tgl

2
我假设你正在使用广泛流传的getBestPreviewSize(w,h)方法的常见实现,该方法通过循环不同的getSupportedPreviewSizes()来找到最佳匹配。虽然我不确定为什么会导致图像失真,但我发现使用getBestPreviewSize方法的输出调用parameters.setPreviewSize(size.width, size.height)方法会导致HTC Desire上出现问题。我还验证了,注释掉这个方法后,扭曲的图像问题就消失了。

我有一个类似的应用程序问题,已经删除了setPreviewSize,但仍有一些用户(Desire S)出现问题。因此,这不仅与代码的这部分相关。我看到很多帖子都围绕着这个问题,希望有人能够详细解释为什么图片会出现这样的情况。 - plus-
太好了!我已经苦苦挣扎于从onFramePreview转换为YUV时得到的扭曲图像几个小时了,而你提供的正是我一直在寻找的。非常感谢! - Muzikant

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接