我们正在使用Surface实现Android相机。当我用此相机拍摄照片时,它会浮肿且模糊。当我在代码中放入自动对焦时,也会发生同样的事情。下面是用我的相机拍摄的照片。请让我知道如何更清楚地保存图片?
相机
public class Cameramain extends AppCompatActivity {
private static final String TAG = "Cameramain";
com.example.ss.myapplication.Preview preview;
Camera camera;
Context ctx;
private final static int PERMISSIONS_REQUEST_CODE = 100;
// Camera.CameraInfo.CAMERA_FACING_FRONT or Camera.CameraInfo.CAMERA_FACING_BACK
private final static int CAMERA_FACING = Camera.CameraInfo.CAMERA_FACING_BACK;
private AppCompatActivity mActivity;
private int n = 1;
public void startCamera() {
if ( preview == null ) {
preview = new Preview(this, (SurfaceView) findViewById(R.id.surfaceView));
preview.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT));
((FrameLayout) findViewById(R.id.layout)).addView(preview);
preview.setKeepScreenOn(true);
//프리뷰 화면 눌렀을 때 사진을 찍음
preview.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
camera.takePicture(shutterCallback, rawCallback, jpegCallback);
}
});
}
preview.setCamera(null);
if (camera != null) {
camera.release();
camera = null;
}
int numCams = Camera.getNumberOfCameras();
if (numCams > 0) {
try {
camera = Camera.open(CAMERA_FACING);
// camera orientation
camera.setDisplayOrientation(setCameraDisplayOrientation(this, CAMERA_FACING,
camera));
// get Camera parameters
Camera.Parameters params = camera.getParameters();
// picture image orientation
params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
camera.setParameters(params);
params.setRotation(setCameraDisplayOrientation(this, CAMERA_FACING, camera));
// camera.getParameters(params);
camera.startPreview();
} catch (RuntimeException ex) {
Toast.makeText(ctx, "camera_not_found " + ex.getMessage().toString(),
Toast.LENGTH_LONG).show();
Log.d(TAG, "camera_not_found " + ex.getMessage().toString());
}
}
preview.setCamera(camera);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ctx = this;
mActivity = this;
//상태바 없애기
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON,
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setContentView(R.layout.activity_main);
}
@Override
protected void onResume() {
super.onResume();
startCamera();
}
@Override
protected void onPause() {
super.onPause();
// Surface will be destroyed when we return, so stop the preview.
if(camera != null) {
// Call stopPreview() to stop updating the preview surface
camera.stopPreview();
preview.setCamera(null);
camera.release();
camera = null;
}
((FrameLayout) findViewById(R.id.layout)).removeView(preview);
preview = null;
}
private void resetCam() {
startCamera();
}
private void refreshGallery(File file) {
Intent mediaScanIntent = new Intent( Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
mediaScanIntent.setData(Uri.fromFile(file));
sendBroadcast(mediaScanIntent);
}
Camera.ShutterCallback shutterCallback = new Camera.ShutterCallback() {
public void onShutter() {
Log.d(TAG, "onShutter'd");
}
};
Camera.PictureCallback rawCallback = new Camera.PictureCallback() {
public void onPictureTaken(byte[] data, Camera camera) {
Log.d(TAG, "onPictureTaken - raw");
}
};
//참고 : http://stackoverflow.com/q/37135675
Camera.PictureCallback jpegCallback = new Camera.PictureCallback() {
public void onPictureTaken(byte[] data, Camera camera) {
//이미지의 너비와 높이 결정
int w = camera.getParameters().getPictureSize().width;
int h = camera.getParameters().getPictureSize().height;
int orientation = setCameraDisplayOrientation(Cameramain.this,
CAMERA_FACING, camera);
//byte array를 bitmap으로 변환
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
Bitmap bitmap = BitmapFactory.decodeByteArray( data, 0, data.length, options);
//int w = bitmap.getWidth();
//int h = bitmap.getHeight();
//이미지를 디바이스 방향으로 회전
Matrix matrix = new Matrix();
matrix.postRotate(orientation);
bitmap = Bitmap.createBitmap(bitmap, 0, 0, w, h, matrix, true);
//bitmap을 byte array로 변환
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
byte[] currentData = stream.toByteArray();
//파일로 저장
new SaveImageTask().execute(currentData);
resetCam();
Log.d(TAG, "onPictureTaken - jpeg");
}
};
private class SaveImageTask extends AsyncTask<byte[], Void, Void> {
@Override
protected Void doInBackground(byte[]... data) {
FileOutputStream outStream = null;
// Write to SD Card
try {
File sdCard = Environment.getExternalStorageDirectory();
File dir = new File (sdCard.getAbsolutePath() + "/picture");
dir.mkdirs();
String fileName = String.format("01.jpg");
File outFile = new File(dir, fileName);
outStream = new FileOutputStream(outFile);
outStream.write(data[0]);
outStream.flush();
outStream.close();
Log.d(TAG, "onPictureTaken - wrote bytes: " + data.length + " to "
+ outFile.getAbsolutePath());
refreshGallery(outFile);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
}
return null;
}
}
}
预览
class Preview extends ViewGroup implements SurfaceHolder.Callback {
private final String TAG = "Preview";
SurfaceView mSurfaceView;
SurfaceHolder mHolder;
Camera.Size mPreviewSize;
List<Camera.Size> mSupportedPreviewSizes;
Camera mCamera;
Preview(Context context, SurfaceView sv ) {
super(context);
mSurfaceView = sv;
// addView(mSurfaceView);
mHolder = mSurfaceView.getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void setCamera(Camera camera) {
if (mCamera != null) {
// Call stopPreview() to stop updating the preview surface.
mCamera.stopPreview();
// Important: Call release() to release the camera for use by other
// applications. Applications should release the camera immediately
// during onPause() and re-open() it during onResume()).
mCamera.release();
mCamera = null;
}
mCamera = camera;
if (mCamera != null) {
List<Camera.Size> localSizes = mCamera.getParameters().getSupportedPreviewSizes();
mSupportedPreviewSizes = localSizes;
requestLayout();
// get Camera parameters
Camera.Parameters params = mCamera.getParameters();
List<String> focusModes = params.getSupportedFocusModes();
if (focusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
// set the focus mode
params.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
// set Camera parameters
mCamera.setParameters(params);
}
try {
mCamera.setPreviewDisplay(mHolder);
} catch (IOException e) {
e.printStackTrace();
}
// Important: Call startPreview() to start updating the preview
// surface. Preview must be started before you can take a picture.
mCamera.startPreview();
}
}
@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) {
//Toast.makeText(getContext(), "surfaceCreated", Toast.LENGTH_LONG).show();
Log.d( "@@@", "surfaceCreated" );
// The Surface has been created, acquire the camera and tell it where
// to draw.
try {
if (mCamera != null) {
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 Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {
final double ASPECT_TOLERANCE = 0.1;
double targetRatio = (double) w / h;
if (sizes == null) return null;
Camera.Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
int targetHeight = h;
// Try to find an size match aspect ratio and size
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);
}
}
// Cannot find the one match the aspect ratio, ignore the requirement
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;
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
if ( mCamera != null) {
Camera.Parameters parameters = mCamera.getParameters();
List<Camera.Size> allSizes = parameters.getSupportedPreviewSizes();
Camera.Size size = allSizes.get(0); // get top size
for (int i = 0; i < allSizes.size(); i++) {
if (allSizes.get(i).width > size.width)
size = allSizes.get(i);
}
//set max Preview Size
parameters.setPreviewSize(size.width, size.height);
// Important: Call startPreview() to start updating the preview surface.
// Preview must be started before you can take a picture.
mCamera.startPreview();
}
}
}