使用 Android 相机 API 时,低质量图片和覆盖 surfaceChanged 的​​用途是什么

Low quality picture and what's the usage of overriding surfaceChanged when using Android Camera API

我的应用程序有问题,具体来说,当我想拍照(从 android 相机 API)并将其发送到我的服务器时,我得到了一些奇怪的图片,如下所示示例:

其中包含很多噪声点,实际上 size/resolution 非常小(176*144 像素)。这是我的 surfaceChanged 原始代码:

public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
    // start preview with new settings
    try {
        Camera.Parameters parameters = mCamera.getParameters();
        parameters.set("orientation", "portrait");
        mCamera.setDisplayOrientation(90);
        mCamera.setPreviewDisplay(mHolder);
        mCamera.startPreview();
    } catch (Exception e){
        Log.e(LOG_TAG, "Error starting camera preview: " + e.getMessage());
    }
    mCamera.startPreview();
}

然后我试着问了一些同学这个问题,他们不知道但是其中一位给出了以下代码:

@Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
    try {
        // camera.stopPreview();
        // Camera.Parameters mParameters = camera.getParameters();
        Camera.Parameters parameters = mCamera.getParameters();
        Camera.Size optiSize = getBestPreviewSize(720, 720);
        if (optiSize != null) {
            parameters.setPreviewSize(optiSize.width, optiSize.height);
            parameters.setPictureSize(optiSize.width, optiSize.height);
        }
        parameters.set("orientation", "portrait");
        mCamera.setDisplayOrientation(90);
        List<String> focusModes = parameters.getSupportedFocusModes();

        if (focusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
            parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
        }
        mCamera.setParameters(parameters);
        // mParameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
        // camera.setParameters(mParameters); // apply the changes
    } catch (Exception e) {
        // older phone - doesn't support these calls
    }
    mCamera.startPreview();
}


private Camera.Size getBestPreviewSize(int width, int height) {
    List<Camera.Size> sizes = mCamera.getParameters()
            .getSupportedPreviewSizes();
    if (sizes == null)
        return null;
    Camera.Size optimalSize = null;
    int tmpSize;

    int minWidthDiff = 1000;
    for (Camera.Size size : sizes) {
        if (size.width > size.height)
            tmpSize = size.height;
        else
            tmpSize = size.width;
        if (Math.abs(tmpSize - width) < minWidthDiff) {
            minWidthDiff = Math.abs(tmpSize - width);
            optimalSize = size;
        }
    }
    return optimalSize;
}

而且这个效果很好,它可以存储全分辨率的原始图片。尽管我修改了一些其他代码以使新代码与我的系统兼容(例如添加自动对焦)。但我认为问题的发生是因为方法 surfaceChanged 因为如果我只使用自动对焦拍摄图像,它仍然不起作用。

所以我的问题是:为什么这种方法会影响我的图像质量。我以为只有当我们 "change" 表面时才会调用此方法,例如旋转屏幕。但显然它的作用不止于此?

有人可以帮我吗?或者一些帖子来解释这个事实?非常感谢您。

当表面改变时调用此方法,例如它被调整大小。调整相机的一些参数以更好地适应新配置(例如设置合适的预览尺寸)是很常见的。

你在第一个代码中所做的是获取相机的 Camera.Parameters,设置一个键值对(顺便说一下,the documentation 没有提到任何带有键的参数"orientation" - 它可能没有任何意义)。您忘记做的是使用 Camera.setParameters() 将新参数应用于相机。话又说回来,如果没有实际设置任何有效参数,这将不起作用。

这会导致图片质量低下的问题。您应该使用 Camera.Parameters 对象来设置所需的预览和图片大小。在第二个代码块中,这是在 getBestPreviewSize() 内完成的。获取可用预览尺寸列表,并根据预览尺寸选择最合适的尺寸。设置一个满意的图片尺寸也可能会有所帮助。

事实是,不同的设备具有不同的参数支持值集。如果您想提供一致的功能,您应该使用 Camera.Parameters.getSupported* 方法检查支持的值并相应地设置它们。