使用Camera和getOptimalPreviewSize扭曲图片

时间:2011-04-04 15:47:10

标签: android android-camera

我在相机应用程序上拍摄基本照片。当我获得最佳的最佳预览尺寸时,我遇到了问题。

事实上,使用第一个代码:

public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
    if (isPreviewRunning) {
        mCamera.stopPreview();
    }
    Camera.Parameters parameters = mCamera.getParameters();
    mCamera.setParameters(parameters);
    mCamera.startPreview();
    isPreviewRunning = true;
}

图片质量很好:

http://img689.imageshack.us/i/04042011172937.jpg/

但是,使用此代码:

private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
    final double ASPECT_TOLERANCE = 0.05;
    double targetRatio = (double) w / h;
    if (sizes == null) return null;

    Size optimalSize = null;
    double minDiff = Double.MAX_VALUE;

    int targetHeight = h;

    // Try to find an size match aspect ratio and size
    for (Size size : sizes) {
        double ratio = (double) size.width / size.height;
        if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
        if (Math.abs(size.height - targetHeight) < minDiff) {
            optimalSize = size;
            minDiff = Math.abs(size.height - targetHeight);
        }
    }

    // Cannot find the one match the aspect ratio, ignore the requirement
    if (optimalSize == null) {
        minDiff = Double.MAX_VALUE;
        for (Size size : sizes) {
            if (Math.abs(size.height - targetHeight) < minDiff) {
                optimalSize = size;
                minDiff = Math.abs(size.height - targetHeight);
            }
        }
    }
    return optimalSize;
}

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.
    if (isPreviewRunning) {
        mCamera.stopPreview();
    }
    Camera.Parameters parameters = mCamera.getParameters();

    List<Size> sizes = parameters.getSupportedPreviewSizes();
    Size optimalSize = getOptimalPreviewSize(sizes, w, h);
    parameters.setPreviewSize(optimalSize.width, optimalSize.height);

    mCamera.setParameters(parameters);
    mCamera.startPreview();
    isPreviewRunning =true;
}

图片完全失真:

http://img97.imageshack.us/i/04042011173220.jpg/

如何解决此问题?

我使用的是HTC Desire HD。

这可能也是我的保存方法? :

PictureCallback mPictureCallbackJpeg = new PictureCallback() {      
        public void onPictureTaken(byte[] imageData, Camera camera) {
    ....

    BitmapFactory.Options options=new BitmapFactory.Options();
                            options.inSampleSize = 5; 
                            Bitmap myImage = BitmapFactory.decodeByteArray(imageData, 0,imageData.length,options);
                            FileOutputStream fOut = new FileOutputStream(path + "/"+fl);
                            BufferedOutputStream bos = new BufferedOutputStream(fOut);


    myImage.compress(CompressFormat.JPEG, 100, bos);
    bos.flush();
    bos.close();
    ....
}

由于

2 个答案:

答案 0 :(得分:26)

我刚遇到同样的问题,并提出了类似但重量更轻的解决方案。我没看到你的保存方法有什么问题。

private Camera.Size getBestPreviewSize(int width, int height)
{
        Camera.Size result=null;    
        Camera.Parameters p = camera.getParameters();
        for (Camera.Size size : p.getSupportedPreviewSizes()) {
            if (size.width<=width && size.height<=height) {
                if (result==null) {
                    result=size;
                } else {
                    int resultArea=result.width*result.height;
                    int newArea=size.width*size.height;

                    if (newArea>resultArea) {
                        result=size;
                    }
                }
            }
        }
    return result;

}

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
    //This line helped me set the preview Display Orientation to Portrait
            //Only works API Level 8 and higher unfortunately.

    camera.setDisplayOrientation(90);

    Camera.Parameters parameters = camera.getParameters();
    Camera.Size size = getBestPreviewSize(width, height);
    parameters.setPreviewSize(size.width, size.height);
    camera.setParameters(parameters);
    camera.startPreview();

}

答案 1 :(得分:5)

最好的方法是使用最接近的宽高比获得预览尺寸:

Camera.Size getBestPreviewSize(int width, int height, Camera.Parameters parameters) {
        Camera.Size result=null;
        float dr = Float.MAX_VALUE;
        float ratio = (float)width/(float)height;

        for (Camera.Size size : parameters.getSupportedPreviewSizes()) {
            float r = (float)size.width/(float)size.height;
            if( Math.abs(r - ratio) < dr && size.width <= width && size.height <= height ) {
                dr = Math.abs(r - ratio);
                result = size;
            }
        }

        return result;
    }

宽度和高度参数是表面尺寸。