自定义相机实现的奇怪预览

时间:2014-02-19 21:51:24

标签: android android-camera photo

我在我的应用中实现了自定义相机活动。相机在我的nexus 5上工作得很好。但是在阿尔卡特One Touch Star上,当我停止预览以显示快照时,我得到了这个预览

enter image description here

此外,PictureCallback的字节数组是正确的。事实上,如果我将数组解码为Bitmap,我可以正确看到它。

以下是SurfaceView作为相机预览的实现。

public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
private int mPhotoRotation;

public CameraPreview(Context context) {
    super(context);
}

@SuppressLint("InlinedApi")
@SuppressWarnings("deprecation")
public CameraPreview(Context context, Camera camera) {
    super(context);
    mCamera = camera;

    Camera.Parameters parameters = camera.getParameters();
    List<String> focusModes = parameters.getSupportedFocusModes();

    if (focusModes != null && focusModes.contains(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE))
        parameters.setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
    else if (focusModes != null && focusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO))
        parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
    if (parameters.getSupportedFlashModes() != null && parameters.getSupportedFlashModes().contains(Parameters.FLASH_MODE_AUTO))
        parameters.setFlashMode(Parameters.FLASH_MODE_AUTO);
    camera.setParameters(parameters);

    mHolder = getHolder();
    mHolder.addCallback(this);

    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB)
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}

@Override
public void surfaceCreated(SurfaceHolder holder) {
    try {
        mCamera.setPreviewDisplay(holder);
        mCamera.startPreview();
    } catch (IOException e) {
    }
}

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
    if (mCamera != null) {
        mCamera.stopPreview();
        Parameters parameters = mCamera.getParameters();
        List<Camera.Size> previewSizes = parameters.getSupportedPreviewSizes();
        Camera.Size size = getOptimalPreviewSize(previewSizes, width, height);

        parameters.setPreviewSize(size.width, size.height);
        mCamera.setParameters(parameters);

        Display display = ((WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
        mPhotoRotation = 0;
        if (display.getRotation() == Surface.ROTATION_0) {
            mPhotoRotation = 90;
        } else if (display.getRotation() == Surface.ROTATION_270) {
            mPhotoRotation = 180;
        }
        mCamera.setDisplayOrientation(mPhotoRotation);
        mCamera.startPreview();
    }
}

private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {
    final double ASPECT_TOLERANCE = 0.1;
    double targetRatio = (double) h / w;

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

    int targetHeight = h;

    for (Camera.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);
        }
    }

    if (optimalSize == null) {
        minDiff = Double.MAX_VALUE;
        for (Camera.Size size : sizes) {
            if (Math.abs(size.height - targetHeight) < minDiff) {
                optimalSize = size;
                minDiff = Math.abs(size.height - targetHeight);
            }
        }
    }
    return optimalSize;
}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}

public int getPhotoRotation() {
    return mPhotoRotation;
}

}

当用户拍摄照片时,执行此代码

mCamera.takePicture(null, null, mPictureCallback);

并且回调只是保留字节数组的备份并停止预览。

mPictureCallback = new PictureCallback() {
        public void onPictureTaken(byte[] data, Camera camera) {
            mPhotoJpeg = data;
            mCamera.stopPreview();
        }
    };

那么这种行为的原因是什么?为什么只在阿尔卡特而不是在nexus 5上?

0 个答案:

没有答案