Android如何修复相机方向
Posted
技术标签:
【中文标题】Android如何修复相机方向【英文标题】:Android how to fix camera orientation 【发布时间】:2013-12-02 14:34:12 【问题描述】:注意相机的视图(不是捕获的图像)是如何向左翻转的(上图),Activity
的方向是正确的,但是相机视图是混乱的,请帮助我 :) 谢谢你。
这是 XML 布局文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_
android:layout_
android:orientation="vertical" >
<LinearLayout
android:layout_
android:layout_
android:orientation="vertical" >
<LinearLayout
android:layout_
android:layout_
android:gravity="center|top"
android:orientation="vertical" >
<SurfaceView
android:id="@+id/camerapreview"
android:layout_margin="10dp"
android:layout_
android:layout_ />
</LinearLayout>
</LinearLayout>
</LinearLayout>
这里是活动的代码:
public class CustomCameraActivity extends Activity implements SurfaceHolder.Callback
Camera camera;
SurfaceView surfaceView;
SurfaceHolder surfaceHolder;
boolean previewing = false;
@Override
public void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.camera);
surfaceView = (SurfaceView)findViewById(R.id.camerapreview);
surfaceHolder = surfaceView.getHolder();
surfaceHolder.addCallback(this);
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
if(previewing)
camera.stopPreview();
previewing = false;
if (camera != null)
try
camera.setPreviewDisplay(surfaceHolder);
camera.startPreview();
previewing = true;
catch (IOException e)
e.printStackTrace();
@Override
public void surfaceCreated(SurfaceHolder holder)
camera = Camera.open();
@Override
public void surfaceDestroyed(SurfaceHolder holder)
camera.stopPreview();
camera.release();
camera = null;
previewing = false;
【问题讨论】:
Check it out, it will guide you 我的意思是相机的视图而不是捕获的图像。 In your case, it will be help you tnx @RobinHood 生病检查一下 【参考方案1】:我找到了解决方案here。 @Ed Jellard 的回答。
我只需在surfaceCreated(SurfaceHolder holder)
方法上添加camera.setDisplayOrientation(90);
,现在显示在正确的角度。
看看快乐的 T-REX :)
【讨论】:
我不认为这只 T-REX 很高兴 :P 无论如何,它帮助了我。谢谢。 @AmitGupta 在我看来很开心。 :D 这仅在设备的相机以横向方式定向时才有效。虽然这适用于大多数人,但不适用于 Nexus 5X 等摄像头为反向横向的设备(您需要将方向设置为 180) 这仅适用于此设备,并且您已在其他设备上旋转图像。这可能是正确的解决方案:captechconsulting.com/blogs/…【参考方案2】:这个问题很久以前就解决了,但是我遇到了一些困难,所以这是我的最终解决方案,希望这对其他人有帮助:
public void startPreview()
try
Log.i(TAG, "starting preview: " + started);
// ....
Camera.CameraInfo camInfo = new Camera.CameraInfo();
Camera.getCameraInfo(cameraIndex, camInfo);
int cameraRotationOffset = camInfo.orientation;
// ...
Camera.Parameters parameters = camera.getParameters();
List<Camera.Size> previewSizes = parameters.getSupportedPreviewSizes();
Camera.Size previewSize = null;
float closestRatio = Float.MAX_VALUE;
int targetPreviewWidth = isLandscape() ? getWidth() : getHeight();
int targetPreviewHeight = isLandscape() ? getHeight() : getWidth();
float targetRatio = targetPreviewWidth / (float) targetPreviewHeight;
Log.v(TAG, "target size: " + targetPreviewWidth + " / " + targetPreviewHeight + " ratio:" + targetRatio);
for (Camera.Size candidateSize : previewSizes)
float whRatio = candidateSize.width / (float) candidateSize.height;
if (previewSize == null || Math.abs(targetRatio - whRatio) < Math.abs(targetRatio - closestRatio))
closestRatio = whRatio;
previewSize = candidateSize;
int rotation = getWindowManager().getDefaultDisplay().getRotation();
int degrees = 0;
switch (rotation)
case Surface.ROTATION_0:
degrees = 0;
break; // Natural orientation
case Surface.ROTATION_90:
degrees = 90;
break; // Landscape left
case Surface.ROTATION_180:
degrees = 180;
break;// Upside down
case Surface.ROTATION_270:
degrees = 270;
break;// Landscape right
int displayRotation;
if (isFrontFacingCam)
displayRotation = (cameraRotationOffset + degrees) % 360;
displayRotation = (360 - displayRotation) % 360; // compensate
// the
// mirror
else // back-facing
displayRotation = (cameraRotationOffset - degrees + 360) % 360;
Log.v(TAG, "rotation cam / phone = displayRotation: " + cameraRotationOffset + " / " + degrees + " = "
+ displayRotation);
this.camera.setDisplayOrientation(displayRotation);
int rotate;
if (isFrontFacingCam)
rotate = (360 + cameraRotationOffset + degrees) % 360;
else
rotate = (360 + cameraRotationOffset - degrees) % 360;
Log.v(TAG, "screenshot rotation: " + cameraRotationOffset + " / " + degrees + " = " + rotate);
Log.v(TAG, "preview size: " + previewSize.width + " / " + previewSize.height);
parameters.setPreviewSize(previewSize.width, previewSize.height);
parameters.setRotation(rotate);
camera.setParameters(parameters);
camera.setPreviewDisplay(mHolder);
camera.startPreview();
Log.d(TAG, "preview started");
started = true;
catch (IOException e)
Log.d(TAG, "Error setting camera preview: " + e.getMessage());
【讨论】:
我不知道如何处理变量。如果您添加有关其余部分的更多信息,那就太好了。代码中有很多红色变量。【参考方案3】:Camera.CameraInfo
类中有一个属性,名为orientation
。它返回整数。您可以获取当前方向,然后进行相应的更改。
请参阅此 answer 处理方向和 CameraInfo 类。
我相信这会对你有所帮助。
【讨论】:
【参考方案4】:当您旋转手机时,相机会自动旋转,但是如果您希望相机或图库中的图像处于正确的方向,请使用:-
public void rotate(String filePath)
Bitmap cameraBitmap = null;
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inJustDecodeBounds = false;
bmOptions.inPurgeable = true;
bmOptions.inBitmap = cameraBitmap;
bmOptions.inMutable = true;
cameraBitmap = BitmapFactory.decodeFile(filePath,bmOptions);
// Your image file path
ByteArrayOutputStream bos = new ByteArrayOutputStream();
cameraBitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);
ExifInterface exif = new ExifInterface(filePath);
float rotation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
System.out.println(rotation);
float rotationInDegrees = exifToDegrees(rotation);
System.out.println(rotationInDegrees);
Matrix matrix = new Matrix();
matrix.postRotate(rotationInDegrees);
Bitmap rotatedBitmap = Bitmap.createBitmap(cameraBitmap , 0, 0, cameraBitmap.getWidth(), cameraBitmap.getHeight(), matrix, true);
FileOutputStream fos=new FileOutputStream(filePath);
rotatedBitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
fos.write(bos.toByteArray());
cameraBitmap.recycle();
System.gc();
fos.flush();
fos.close();
private static float exifToDegrees(float exifOrientation)
if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_90) return 90;
else if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_180) return 180;
else if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_270) return 270;
return 0;
【讨论】:
这不是一个实际的答案,阅读OP comment以上是关于Android如何修复相机方向的主要内容,如果未能解决你的问题,请参考以下文章
如何在Android中修复相机预览(surfaceview)的正确纵横比?