Quiero configurar la orientación de la cámara de acuerdo con la orientación del dispositivo en Android, pero parece que nada funciona. Traté de rotar Surface y los parámetros de la cámara, pero la vista previa de la cámara en modo retrato siempre se da vuelta. Necesitaría rotarlo 90 grados en el sentido de las agujas del reloj para que sea correcto. Aquí está el código que estoy usando en este momento que funciona solo en modo horizontal.
SurfaceHolder.Callback surfaceCallback = new SurfaceHolder.Callback() {
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
camera.stopPreview();
camera.release();
camera = null;
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
initCamera();
}
private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
final double ASPECT_TOLERANCE = 0.2;
double targetRatio = (double) w / h;
if (sizes == null)
return null;
Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
int targetHeight = h;
// Try to find an size match aspect ratio and size
for (Size size : sizes) {
Log.d(TAG, "Checking size " + size.width + "w " + size.height
+ "h");
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);
}
}
}
return optimalSize;
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
Camera.Parameters parameters = camera.getParameters();
List<Size> sizes = parameters.getSupportedPreviewSizes();
Size optimalSize = getOptimalPreviewSize(sizes, width, height);
Log.d(TAG, "Surface size is " + width + "w " + height + "h");
Log.d(TAG, "Optimal size is " + optimalSize.width + "w " + optimalSize.height + "h");
parameters.setPreviewSize(optimalSize.width, optimalSize.height);
// parameters.setPreviewSize(width, height);
camera.setParameters(parameters);
camera.startPreview();
}
};
android
camera
orientation
surfaceview
Abhinav
fuente
fuente
Respuestas:
De otro miembro y mi problema:
El problema de rotación de la cámara depende de diferentes dispositivos y de una versión determinada.
Versión 1.6: para solucionar el problema de rotación, y es bueno para la mayoría de dispositivos
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) { p.set("orientation", "portrait"); p.set("rotation",90); } if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) { p.set("orientation", "landscape"); p.set("rotation", 90); }
Versión 2.1: depende del tipo de dispositivo, por ejemplo, no se puede solucionar el problema con XPeria X10, pero es bueno para X8 y Mini
Camera.Parameters parameters = camera.getParameters(); parameters.set("orientation", "portrait"); camera.setParameters(parameters);
Versión 2.2: no para todos los dispositivos
camera.setDisplayOrientation(90);
http://code.google.com/p/android/issues/detail?id=1193#c42
fuente
De los Javadocs para
setDisplayOrientation(int)
(Requiere API nivel 9):public static void setCameraDisplayOrientation(Activity activity, int cameraId, android.hardware.Camera camera) { android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo(); android.hardware.Camera.getCameraInfo(cameraId, info); int rotation = activity.getWindowManager().getDefaultDisplay() .getRotation(); int degrees = 0; switch (rotation) { case Surface.ROTATION_0: degrees = 0; break; case Surface.ROTATION_90: degrees = 90; break; case Surface.ROTATION_180: degrees = 180; break; case Surface.ROTATION_270: degrees = 270; break; } int result; if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { result = (info.orientation + degrees) % 360; result = (360 - result) % 360; // compensate the mirror } else { // back-facing result = (info.orientation - degrees + 360) % 360; } camera.setDisplayOrientation(result); }
fuente
CameraInfo
no se introdujo hasta el nivel de API 9, por lo que el método que publiqué requiere el nivel de API 9.result = (360 - result) % 360; // compensate the mirror
deben eliminarse , las imágenes de la cámara frontal se rotan incorrectamente de loEsta solución funcionará para todas las versiones de Android. Puede utilizar la reflexión en Java para que funcione en todos los dispositivos Android:
Básicamente, debe crear un contenedor de reflexión para llamar al setDisplayOrientation de Android 2.2, en lugar de llamar al método específico.
El método:
protected void setDisplayOrientation(Camera camera, int angle){ Method downPolymorphic; try { downPolymorphic = camera.getClass().getMethod("setDisplayOrientation", new Class[] { int.class }); if (downPolymorphic != null) downPolymorphic.invoke(camera, new Object[] { angle }); } catch (Exception e1) { } }
Y en lugar de usar camera.setDisplayOrientation (x) use setDisplayOrientation (camera, x) :
if (Integer.parseInt(Build.VERSION.SDK) >= 8) setDisplayOrientation(mCamera, 90); else { if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) { p.set("orientation", "portrait"); p.set("rotation", 90); } if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) { p.set("orientation", "landscape"); p.set("rotation", 90); } }
fuente
Camera.Parameters
. Intente agregar la siguiente línea:Camera.Parameters p = camera.getParameters();
Enfrenté el problema cuando estaba usando ZBar para escanear pestañas. Problema de orientación de la cámara. Usando el siguiente código, pude resolver el problema. Este no es el fragmento de código completo. Por favor, tome solo la ayuda de esto.
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { if (isPreviewRunning) { mCamera.stopPreview(); } setCameraDisplayOrientation(mCamera); previewCamera(); } public void previewCamera() { try { // Hard code camera surface rotation 90 degs to match Activity view // in portrait mCamera.setPreviewDisplay(mHolder); mCamera.setPreviewCallback(previewCallback); mCamera.startPreview(); mCamera.autoFocus(autoFocusCallback); isPreviewRunning = true; } catch (Exception e) { Log.d("DBG", "Error starting camera preview: " + e.getMessage()); } } public void setCameraDisplayOrientation(android.hardware.Camera camera) { Camera.Parameters parameters = camera.getParameters(); android.hardware.Camera.CameraInfo camInfo = new android.hardware.Camera.CameraInfo(); android.hardware.Camera.getCameraInfo(getBackFacingCameraId(), camInfo); Display display = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); int rotation = display.getRotation(); int degrees = 0; switch (rotation) { case Surface.ROTATION_0: degrees = 0; break; case Surface.ROTATION_90: degrees = 90; break; case Surface.ROTATION_180: degrees = 180; break; case Surface.ROTATION_270: degrees = 270; break; } int result; if (camInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { result = (camInfo.orientation + degrees) % 360; result = (360 - result) % 360; // compensate the mirror } else { // back-facing result = (camInfo.orientation - degrees + 360) % 360; } camera.setDisplayOrientation(result); } private int getBackFacingCameraId() { int cameraId = -1; // Search for the front facing camera int numberOfCameras = Camera.getNumberOfCameras(); for (int i = 0; i < numberOfCameras; i++) { Camera.CameraInfo info = new Camera.CameraInfo(); Camera.getCameraInfo(i, info); if (info.facing == Camera.CameraInfo.CAMERA_FACING_BACK) { cameraId = i; break; } } return cameraId; }
fuente
Finalmente arreglé esto usando la aplicación de cámara de Google. Obtiene la orientación del teléfono mediante el uso de un sensor y luego establece la etiqueta EXIF de manera adecuada. El JPEG que sale de la cámara no se orienta automáticamente.
Además, la vista previa de la cámara funciona correctamente solo en el modo horizontal. Si necesita que el diseño de su actividad esté orientado en vertical, tendrá que hacerlo manualmente utilizando el valor del sensor de orientación.
fuente
mira esta solución
public static void setCameraDisplayOrientation(Activity activity, int cameraId, android.hardware.Camera camera) { android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo(); android.hardware.Camera.getCameraInfo(cameraId, info); int rotation = activity.getWindowManager().getDefaultDisplay() .getRotation(); int degrees = 0; switch (rotation) { case Surface.ROTATION_0: degrees = 0; break; case Surface.ROTATION_90: degrees = 90; break; case Surface.ROTATION_180: degrees = 180; break; case Surface.ROTATION_270: degrees = 270; break; } int result; if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { result = (info.orientation + degrees) % 360; result = (360 - result) % 360; // compensate the mirror } else { // back-facing result = (info.orientation - degrees + 360) % 360; } camera.setDisplayOrientation(result); }
fuente
Este problema se resolvió hace mucho tiempo, pero encontré algunas dificultades para unir todas las piezas, así que aquí está mi solución final, espero que esto ayude a otros:
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()); } }
fuente