Android 自定义相机以错误方向显示预览和缩放图像
我使用的是一款简单的定制相机,只需点击按钮即可拍照 相机会以错误的方向(横向)显示预览,即使手机处于纵向,图像也会显示一些缩放的图像 我在谷歌上搜索了一下,找到了很多解决这个问题的方法,我尝试了所有的方法,但是没有人能解决我的问题 我想我遗漏了一些主要的概念,我想不出来 CameraActivity.javaAndroid 自定义相机以错误方向显示预览和缩放图像,android,android-camera,Android,Android Camera,我使用的是一款简单的定制相机,只需点击按钮即可拍照 相机会以错误的方向(横向)显示预览,即使手机处于纵向,图像也会显示一些缩放的图像 我在谷歌上搜索了一下,找到了很多解决这个问题的方法,我尝试了所有的方法,但是没有人能解决我的问题 我想我遗漏了一些主要的概念,我想不出来 CameraActivity.java public class CameraActivity extends AppCompatActivity { private static final String TAG =
public class CameraActivity extends AppCompatActivity {
private static final String TAG = "CameraActivity";
private Camera mCamera;
private CameraPreview mPreview;
private PictureCallback mPictureCallback;
private Context myContext;
private FrameLayout cameraPreview;
private boolean frontCamera = false, backCamera = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_camera);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
initialize();
}
private void findViews() {
cameraPreview = (FrameLayout) findViewById(R.id.camera_preview);
}
public void initialize() {
findViews();
myContext = this;
mCamera = Camera.open(findBackFacingCamera());
mPreview = new CameraPreview(myContext, mCamera);
cameraPreview.addView(mPreview);
}
private int findFrontFacingCamera() {
int cameraId = -1; // initialized with empty
int numberOfCameras = Camera.getNumberOfCameras();
CameraInfo cameraInfo = new CameraInfo();
for (int i = 0; i < numberOfCameras; i++) {
Camera.getCameraInfo(i, cameraInfo);
if (cameraInfo.facing == CameraInfo.CAMERA_FACING_FRONT) {
cameraId = i;
frontCamera = true;
break;
}
}
return cameraId;
}
private int findBackFacingCamera() {
int cameraId = -1; // initialized with empty
int numberOfCameras = Camera.getNumberOfCameras();
CameraInfo cameraInfo = new CameraInfo();
for (int i = 0; i < numberOfCameras; i++) {
Camera.getCameraInfo(i, cameraInfo);
if (cameraInfo.facing == CameraInfo.CAMERA_FACING_BACK) {
cameraId = i;
backCamera = true;
break;
}
}
return cameraId;
}
@Override
protected void onResume() {
super.onResume();
//mPictureCallback=getPi
if (!hasCamera(myContext)) {
Log.e(TAG, "Sorry, your phone does not have a camera!");
}
if (mCamera == null) {
if (findFrontFacingCamera() == 1) {
releaseCamera();
chooseCamera();
}
}
}
private void chooseCamera() {
// If currently front camera is opened,then switch to back camera
if (frontCamera) {
int cameraId = findBackFacingCamera();
if (cameraId > 0) {
// Open backfacing camera
// Set picture callback
// refresh the preview
mCamera = Camera.open(cameraId);
mPictureCallback = getPictureCallBack();
mPreview.refreshCamera(mCamera);
}
} else {
int cameraId = findFrontFacingCamera();
if (cameraId > 0) {
mCamera = Camera.open(cameraId);
mPictureCallback = getPictureCallBack();
mPreview.refreshCamera(mCamera);
}
}
}
private PictureCallback getPictureCallBack() {
PictureCallback pictureCallback = new PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
File pictureFile = getOutputMediaFile();
if (pictureFile == null) {
return;
}
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
Log.e(TAG, " picture saved at " + pictureFile.getName());
} catch (Exception e) {
Log.e(TAG, " getPictureCallBack " + e);
}
mPreview.refreshCamera(mCamera);
}
};
return pictureCallback;
}
private File getOutputMediaFile() {
// make a new storage directory inside sd card
File mediaStorage = new File("/sdcard/", "Tootle Camera");
// if Tootle Camera directory doesn't exist
if (!mediaStorage.exists()) {
if (!mediaStorage.mkdirs()) {
return null;
} else {
mediaStorage.mkdirs();
}
}
String timeStamp = new SimpleDateFormat("dd/MM/yyy_hh:mm:ss a").format(new Date());
// make media file
File mediaFile = new File(mediaStorage.getPath() + File.separator + "IMG_" + timeStamp + ".jpg");
return mediaFile;
}
private void releaseCamera() {
if (mCamera != null) {
mCamera.release();
mCamera = null;
}
}
public boolean hasCamera(Context context) {
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
return true;
} else {
return false;
}
}
@Override
protected void onPause() {
super.onPause();
releaseCamera();
}
}
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private static final String TAG = "CameraPreview";
private SurfaceHolder mHolder;
private Camera mCamera;
private boolean isPreviewRunning = false;
public CameraPreview(Context context, Camera camera) {
super(context);
mCamera = camera;
mHolder = getHolder();
mHolder.addCallback(this);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
try {
// create the surface and start camera previre
if (mCamera == null) {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
}
} catch (Exception e) {
Log.e(TAG, " surfaceCreated " + e);
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
// If your preview can change or rotate, take care of those events here.
// Make sure to stop the preview before resizing or reformatting it.
//refreshCamera(mCamera);
if (isPreviewRunning) {
mCamera.stopPreview();
}
Camera.Parameters parameters = mCamera.getParameters();
Display display = ((WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
if (display.getRotation() == Surface.ROTATION_0) {
parameters.setPreviewSize(height, width);
mCamera.setDisplayOrientation(90);
}
if (display.getRotation() == Surface.ROTATION_90) {
parameters.setPreviewSize(width, height);
}
if (display.getRotation() == Surface.ROTATION_180) {
parameters.setPreviewSize(height, width);
}
if (display.getRotation() == Surface.ROTATION_270) {
parameters.setPreviewSize(width, height);
mCamera.setDisplayOrientation(180);
}
mCamera.setParameters(parameters);
previewCamera();
}
public void refreshCamera(Camera camera) {
if (mHolder == null) {
// preview surface does not exist
return;
}
try {
mCamera.stopPreview();
} catch (Exception e) {
Log.e(TAG, " refreshCamera " + e);
}
setCamera(camera);
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e) {
Log.e(TAG, " refreshCamera " + e);
}
}
private void setCamera(Camera camera) {
//method to set a camera instance
mCamera = camera;
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
mCamera.release();
}
public void previewCamera() {
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
isPreviewRunning = true;
} catch (Exception e) {
Log.d(TAG, "Cannot start preview " + e);
}
}
}
如果您有文件路径和位图,请使用以下方法检查旋转并修复它:
public Bitmap checkRotation(String filePath, Bitmap scaledBitmap) {
ExifInterface exif;
try {
exif = new ExifInterface(filePath);
int orientation = exif.getAttributeInt(
ExifInterface.TAG_ORIENTATION, 0);
Log.d("EXIF", "Exif: " + orientation);
Matrix matrix = new Matrix();
if (orientation == 6) {
matrix.postRotate(90);
Log.d("EXIF", "Exif: " + orientation);
} else if (orientation == 3) {
matrix.postRotate(180);
Log.d("EXIF", "Exif: " + orientation);
} else if (orientation == 8) {
matrix.postRotate(270);
Log.d("EXIF", "Exif: " + orientation);
}
scaledBitmap = Bitmap.createBitmap(scaledBitmap, 0, 0,
scaledBitmap.getWidth(), scaledBitmap.getHeight(), matrix,
true);
} catch (IOException e) {
e.printStackTrace();
}
return scaledBitmap;
}
在您的CameraPreview.java中
public class CameraActivity extends AppCompatActivity {
private static final String TAG = "CameraActivity";
private Camera mCamera;
private CameraPreview mPreview;
private PictureCallback mPictureCallback;
private Context myContext;
private FrameLayout cameraPreview;
private boolean frontCamera = false, backCamera = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_camera);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
initialize();
}
private void findViews() {
cameraPreview = (FrameLayout) findViewById(R.id.camera_preview);
}
public void initialize() {
findViews();
myContext = this;
mCamera = Camera.open(findBackFacingCamera());
mPreview = new CameraPreview(myContext, mCamera);
cameraPreview.addView(mPreview);
}
private int findFrontFacingCamera() {
int cameraId = -1; // initialized with empty
int numberOfCameras = Camera.getNumberOfCameras();
CameraInfo cameraInfo = new CameraInfo();
for (int i = 0; i < numberOfCameras; i++) {
Camera.getCameraInfo(i, cameraInfo);
if (cameraInfo.facing == CameraInfo.CAMERA_FACING_FRONT) {
cameraId = i;
frontCamera = true;
break;
}
}
return cameraId;
}
private int findBackFacingCamera() {
int cameraId = -1; // initialized with empty
int numberOfCameras = Camera.getNumberOfCameras();
CameraInfo cameraInfo = new CameraInfo();
for (int i = 0; i < numberOfCameras; i++) {
Camera.getCameraInfo(i, cameraInfo);
if (cameraInfo.facing == CameraInfo.CAMERA_FACING_BACK) {
cameraId = i;
backCamera = true;
break;
}
}
return cameraId;
}
@Override
protected void onResume() {
super.onResume();
//mPictureCallback=getPi
if (!hasCamera(myContext)) {
Log.e(TAG, "Sorry, your phone does not have a camera!");
}
if (mCamera == null) {
if (findFrontFacingCamera() == 1) {
releaseCamera();
chooseCamera();
}
}
}
private void chooseCamera() {
// If currently front camera is opened,then switch to back camera
if (frontCamera) {
int cameraId = findBackFacingCamera();
if (cameraId > 0) {
// Open backfacing camera
// Set picture callback
// refresh the preview
mCamera = Camera.open(cameraId);
mPictureCallback = getPictureCallBack();
mPreview.refreshCamera(mCamera);
}
} else {
int cameraId = findFrontFacingCamera();
if (cameraId > 0) {
mCamera = Camera.open(cameraId);
mPictureCallback = getPictureCallBack();
mPreview.refreshCamera(mCamera);
}
}
}
private PictureCallback getPictureCallBack() {
PictureCallback pictureCallback = new PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
File pictureFile = getOutputMediaFile();
if (pictureFile == null) {
return;
}
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
Log.e(TAG, " picture saved at " + pictureFile.getName());
} catch (Exception e) {
Log.e(TAG, " getPictureCallBack " + e);
}
mPreview.refreshCamera(mCamera);
}
};
return pictureCallback;
}
private File getOutputMediaFile() {
// make a new storage directory inside sd card
File mediaStorage = new File("/sdcard/", "Tootle Camera");
// if Tootle Camera directory doesn't exist
if (!mediaStorage.exists()) {
if (!mediaStorage.mkdirs()) {
return null;
} else {
mediaStorage.mkdirs();
}
}
String timeStamp = new SimpleDateFormat("dd/MM/yyy_hh:mm:ss a").format(new Date());
// make media file
File mediaFile = new File(mediaStorage.getPath() + File.separator + "IMG_" + timeStamp + ".jpg");
return mediaFile;
}
private void releaseCamera() {
if (mCamera != null) {
mCamera.release();
mCamera = null;
}
}
public boolean hasCamera(Context context) {
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
return true;
} else {
return false;
}
}
@Override
protected void onPause() {
super.onPause();
releaseCamera();
}
}
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private static final String TAG = "CameraPreview";
private SurfaceHolder mHolder;
private Camera mCamera;
private boolean isPreviewRunning = false;
public CameraPreview(Context context, Camera camera) {
super(context);
mCamera = camera;
mHolder = getHolder();
mHolder.addCallback(this);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
try {
// create the surface and start camera previre
if (mCamera == null) {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
}
} catch (Exception e) {
Log.e(TAG, " surfaceCreated " + e);
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
// If your preview can change or rotate, take care of those events here.
// Make sure to stop the preview before resizing or reformatting it.
//refreshCamera(mCamera);
if (isPreviewRunning) {
mCamera.stopPreview();
}
Camera.Parameters parameters = mCamera.getParameters();
Display display = ((WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
if (display.getRotation() == Surface.ROTATION_0) {
parameters.setPreviewSize(height, width);
mCamera.setDisplayOrientation(90);
}
if (display.getRotation() == Surface.ROTATION_90) {
parameters.setPreviewSize(width, height);
}
if (display.getRotation() == Surface.ROTATION_180) {
parameters.setPreviewSize(height, width);
}
if (display.getRotation() == Surface.ROTATION_270) {
parameters.setPreviewSize(width, height);
mCamera.setDisplayOrientation(180);
}
mCamera.setParameters(parameters);
previewCamera();
}
public void refreshCamera(Camera camera) {
if (mHolder == null) {
// preview surface does not exist
return;
}
try {
mCamera.stopPreview();
} catch (Exception e) {
Log.e(TAG, " refreshCamera " + e);
}
setCamera(camera);
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
} catch (Exception e) {
Log.e(TAG, " refreshCamera " + e);
}
}
private void setCamera(Camera camera) {
//method to set a camera instance
mCamera = camera;
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
mCamera.release();
}
public void previewCamera() {
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
isPreviewRunning = true;
} catch (Exception e) {
Log.d(TAG, "Cannot start preview " + e);
}
}
}
之后
写下:
mCamera.setDisplayOrientation(90);
mCamera.startPreview();
屏幕快照不是捕获的图像,而是实时相机预览。您不应使用预览曲面的大小来设置相机的预览大小。您应该迭代getSupportedPreviewSizes以获得最佳匹配。要选择摄像机实时预览的纵向方向,请使用camera.setDisplayOrientation()。