2

I cannot get camera preview in portrait orientation working correctly on my Droid 3. The preview is rotated 90 degrees counter-clockwise. For example, if I take a picture of a standing person, they appear lying down - their head appears at the left edge of the screen and the feet at the right edge.

Here is the code. I experimented with several settings which I have included as comments. Most weirdly, one bit of Google sample code turned the preview very dark in portrait. This code works correctly in landscape.

I'm using Android 2.3.3 on a Droid 3 phone.

I have used the Google Android sample code and tried every variation I can think of. I have read all the StackOverflow that I can find on this problem.

The default camera app that comes with the phone correctly previews portrait so I know that it is not a hardware problem.

Portrait is critical to my application so I would deeply appreciate any advice.

Thanks

Jeff

Activity's onCreate snippet:

    preview = new SimplePreview(this, defaultCameraId);

    setContentView(preview);

Preview class

package com.chex.camera;


/** Google's preview example */
public class SimplePreview extends ViewGroup implements SurfaceHolder.Callback {
private final String TAG = "Preview";

SurfaceView mSurfaceView;
SurfaceHolder mHolder;
Size mPreviewSize;
List<Size> mSupportedPreviewSizes;
Camera mCamera;
int cameraId;
Activity activity;

public SimplePreview(Activity context, int defaultCamera) {
    super(context);
    activity = context;
    cameraId = defaultCamera;
    mSurfaceView = new SurfaceView(context);
    addView(mSurfaceView);

    // Install a SurfaceHolder.Callback so we get notified when the
    // underlying surface is created and destroyed.
    mHolder = mSurfaceView.getHolder();
    mHolder.addCallback(this);
    mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}

public void setCamera(Camera camera) {
    mCamera = camera;
    if (mCamera != null) {
        mSupportedPreviewSizes = mCamera.getParameters()
                .getSupportedPreviewSizes();
        requestLayout();
    }
}

public void switchCamera(Camera camera) {
    setCamera(camera);
    try {
        camera.setPreviewDisplay(mHolder);
    } catch (IOException exception) {
        Log.e(TAG, "IOException caused by setPreviewDisplay()", exception);
    }
    Camera.Parameters parameters = camera.getParameters();
    parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
    requestLayout();

    camera.setParameters(parameters);
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    // We purposely disregard child measurements because act as a
    // wrapper to a SurfaceView that centers the camera preview instead
    // of stretching it.
    final int width = resolveSize(getSuggestedMinimumWidth(),
            widthMeasureSpec);
    final int height = resolveSize(getSuggestedMinimumHeight(),
            heightMeasureSpec);
    setMeasuredDimension(width, height);

    if (mSupportedPreviewSizes != null) {
        mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width,
                height);
    }
}

@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {

    if (changed && getChildCount() > 0) {
        final View child = getChildAt(0);

        final int width = r - l;
        final int height = b - t;

        int previewWidth = width;
        int previewHeight = height;
        if (mPreviewSize != null) {
            previewWidth = mPreviewSize.width;
            previewHeight = mPreviewSize.height;
        }

        // Center the child SurfaceView within the parent.
        if (width * previewHeight > height * previewWidth) {
            final int scaledChildWidth = previewWidth * height
                    / previewHeight;
            child.layout((width - scaledChildWidth) / 2, 0,
                    (width + scaledChildWidth) / 2, height);
        } else {
            final int scaledChildHeight = previewHeight * width
                    / previewWidth;
            child.layout(0, (height - scaledChildHeight) / 2, width,
                    (height + scaledChildHeight) / 2);
        }
    }
}

public void surfaceCreated(SurfaceHolder holder) {
    // The Surface has been created, acquire the camera and tell it where
    // to draw.
    try {
        if (mCamera != null) {
            // mCamera.setDisplayOrientation(90);
            mCamera.setPreviewDisplay(holder);

        }
    } catch (IOException exception) {
        Log.e(TAG, "IOException caused by setPreviewDisplay()", exception);
    }
}

public void surfaceDestroyed(SurfaceHolder holder) {
    // Surface will be destroyed when we return, so stop the preview.
    if (mCamera != null) {
        mCamera.stopPreview();
    }
}

private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
    final double ASPECT_TOLERANCE = 0.1;
    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) {
        Log.v(TAG, "  width: " + size.width + "  height: " + size.height);

        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;
}

/**
 * orientation and rotation work done here. Now that the size is known, set
 * up the camera parameters and begin the preview.
 */
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {

    if (mCamera != null) {

        mCamera.stopPreview();

        Camera.Parameters parameters = mCamera.getParameters();

        parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
        // requestLayout();

        // Following had no effect - I tried to force portrait
        parameters.set("orientation", "portrait");

        // Following had no effect - I tried to force portrait
        // parameters.set("rotation", 180);

        /*
         * Following turns my very dark. source: http://developer.android
         * .com/reference/android/hardware/Camera.html
         */

        android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();

        android.hardware.Camera.getCameraInfo(cameraId, info);

        int rotation = activity.getWindowManager().getDefaultDisplay()
                .getRotation();

        int degrees = 0;
        switch (rotation) {
        case Surface.ROTATION_0:
            degrees = 0;
            break;
        case Surface.ROTATION_90:
            degrees = 90;
            break;
        case Surface.ROTATION_180:
            degrees = 180;
            break;
        case Surface.ROTATION_270:
            degrees = 270;
            break;
        }

        int result;
        if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
            result = (info.orientation + degrees) % 360;
            result = (360 - result) % 360;
            // compensate the mirror
        } else {
            // back-facing
            result = (info.orientation - degrees + 360) % 360;
        }
        mCamera.setDisplayOrientation(result);

        mCamera.setParameters(parameters);

        mCamera.startPreview();
             }
           }
               }
4

0 回答 0