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<Size> 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<Size> sizes = parameters.getSupportedPreviewSizes();
Size optimalSize = getOptimalPreviewSize(sizes, w, h);
parameters.setPreviewSize(optimalSize.width, optimalSize.height);
mCamera.setParameters(parameters);
mCamera.startPreview();
}
}
private Size getOptimalPreviewSize(List<Size> 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);
}
}