제임스딘딘의
Tech & Life

개발자의 기록 노트/Android

[안드로이드] 카메라 해상도 바꾸기

제임스-딘딘 2010. 12. 21. 08:14

안드로이드 카메라 해상도 바꾸기

카메라를 찍을때 촬영할 이미지의 해상도를 변경하는 방법을 보여주는 예제코드 입니다.
아래 코드는 APIDemo에 있던 Camera 소스를 약간 변경한 것입니다.
Preview Class는 카메라에서 1600 * 1200 (2MP)과 가장 가까운 해상도를 찾아서, 그 해상도로 촬영을 해 주는 역할을 합니다.
Activity에서 불러오는 방법은 APIDemo에 있는 Camera소스를 찾아 보시기 바랍니다.

 
class Preview extends SurfaceView implements SurfaceHolder.Callback {
    private static final int IMAGE_WIDTH = 1600; // 촬영할 가로 픽셀 수
    private static final int IMAGE_HEIGHT = 1200; // 촬영할 세로 픽셀 수
    SurfaceHolder mHolder;
    Camera mCamera;
    OnPictureTakenCallback mCallback;
    
    Preview(Context context) {
        super(context);
        initHolder();
    }

    // Install a SurfaceHolder.Callback so we get notified when the
    // underlying surface is created and destroyed.
    private void initHolder() {
        mHolder = getHolder();
        mHolder.addCallback(this);
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }
    public Preview(Context context, AttributeSet attrs) {
        super(context, attrs);
        initHolder();
    }

    public Preview(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        initHolder();
    }
    public void setMode(int mode) {
        mMode = mode;
    }
    public void surfaceCreated(SurfaceHolder holder) {
        // The Surface has been created, acquire the camera and tell it where
        // to draw.
       mCamera = Camera.open();
       try {
         mCamera.setPreviewDisplay(holder);

         Camera.Parameters parameters = mCamera.getParameters();
    // 카메라에서 찍을 수 있는 모든 사이즈를 가지고 와서 그중에 하나를 선택한다.
         List sizes = parameters.getSupportedPictureSizes();
         Size optimalSize;
         optimalSize = getOptimalPreviewSize(sizes, IMAGE_WIDTH, IMAGE_HEIGHT);
         parameters.setPictureSize(optimalSize.width, optimalSize.height); 
         mCamera.setParameters(parameters);
     } catch (IOException exception) {
        mCamera.release();
        mCamera = null;
            // TODO: add more exception handling logic here
    }
}

public void surfaceDestroyed(SurfaceHolder holder) {
        // Surface will be destroyed when we return, so stop the preview.
        // Because the CameraDevice object is not a shared resource, it's very
        // important to release it when the activity is paused.
    mCamera.stopPreview();
    mCamera.release();
    mCamera = null;
}

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 (mCamera != null) {
        Camera.Parameters parameters = mCamera.getParameters();
// get the optimal preview size
        List sizes = parameters.getSupportedPreviewSizes();
        Size optimalSize = getOptimalPreviewSize(sizes, w, h);
        parameters.setPreviewSize(optimalSize.width, optimalSize.height);
        mCamera.setParameters(parameters);
        mCamera.startPreview();
    }
} 

private Size getOptimalPreviewSize(List sizes, int width, int height) {
    final double ASPECT_TOLERANCE = 0.05;
    double targetRatio = (double) width / height;
    if (sizes == null) {
        return null;
    }

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

    int targetHeight = height;

// 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);
            }
        }
    }
    Log.i("optimal size", ""+optimalSize.width+" x "+optimalSize.height);
    return optimalSize;
}

private final Camera.PictureCallback jpeg = new Camera.PictureCallback() {
    @Override
    public void onPictureTaken(byte[] data, Camera camera) {
        if (mCallback != null) {
            mCallback.onPictureTaken(data);
        }
    }
};

public void takePicture() {
    camera.takePicture(null, null, jpeg);
}

public void restartPreview() {
    mCamera.startPreview();
}
public void setOnPictureTakenCallback(OnPictureTakenCallback callback) {
    this.mCallback = callback;
}

public interface OnPictureTakenCallback {
    public void onPictureTaken(byte[] data);
}