El control de la cámara para tomar fotografías en vertical no hace girar las imágenes finales

Estoy tratando de controlar la cámara Android para tomar fotos en una aplicación de retrato, pero cuando guardo la imagen, está en el paisaje. He setCameraDisplayOrientation() la imagen de 90 grados con el método setCameraDisplayOrientation() , pero no funciona.

Entonces he encontrado esta publicación, pero la TAG_ORIENTATION es 0 (undefined). Si captura este valor y aplico un valor de rotación, tampoco funciona.

¿Cómo puedo tomar una foto en el retrato y guardarla con una buena orientación?

  /** Initializes the back/front camera */ private boolean initPhotoCamera() { try { camera = getCameraInstance(selected_camera); Camera.Parameters parameters = camera.getParameters(); // parameters.setPreviewSize(width_video, height_video); // parameters.set("orientation", "portrait"); // parameters.set("rotation", 1); // camera.setParameters(parameters); checkCameraFlash(parameters); // camera.setDisplayOrientation( 0); setCameraDisplayOrientation(selected_camera, camera); surface_view.getHolder().setFixedSize(width_video, height_video); LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(width_video, height_video); surface_view.setLayoutParams(lp); camera.lock(); surface_holder = surface_view.getHolder(); surface_holder.addCallback(this); surface_holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); setPreviewCamera(); } catch (Exception e) { Log.v("RecordVideo", "Could not initialize the Camera"); return false; } return true; } public void setCameraDisplayOrientation(int cameraId, Camera camera) { Camera.CameraInfo info = new Camera.CameraInfo(); Camera.getCameraInfo(cameraId, info); int rotation = 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); } public static Bitmap rotate(Bitmap bitmap, int degree) { int w = bitmap.getWidth(); int h = bitmap.getHeight(); Matrix mtx = new Matrix(); // mtx.postRotate(degree); mtx.setRotate(degree); return Bitmap.createBitmap(bitmap, 0, 0, w, h, mtx, true); } @Override public void onPictureTaken(byte[] data, Camera camera) { String timeStamp = Calendar.getInstance().getTime().toString(); output_file_name = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM) + File.separator + timeStamp + ".jpeg"; File pictureFile = new File(output_file_name); if (pictureFile.exists()) { pictureFile.delete(); } try { FileOutputStream fos = new FileOutputStream(pictureFile); fos.write(data); Bitmap realImage = BitmapFactory.decodeFile(output_file_name); ExifInterface exif=new ExifInterface(pictureFile.toString()); Log.d("EXIF value", exif.getAttribute(ExifInterface.TAG_ORIENTATION)); if(exif.getAttribute(ExifInterface.TAG_ORIENTATION).equalsIgnoreCase("6")){ realImage= rotate(realImage, 90); } else if(exif.getAttribute(ExifInterface.TAG_ORIENTATION).equalsIgnoreCase("8")){ realImage= rotate(realImage, 270); } else if(exif.getAttribute(ExifInterface.TAG_ORIENTATION).equalsIgnoreCase("3")){ realImage= rotate(realImage, 180); } else if(exif.getAttribute(ExifInterface.TAG_ORIENTATION).equalsIgnoreCase("0")){ realImage= rotate(realImage, 45); } boolean bo = realImage.compress(Bitmap.CompressFormat.JPEG, 100, fos); fos.close(); Log.d("Info", bo + ""); } catch (FileNotFoundException e) { Log.d("Info", "File not found: " + e.getMessage()); } catch (IOException e) { Log.d("TAG", "Error accessing file: " + e.getMessage()); } } 

8 Solutions collect form web for “El control de la cámara para tomar fotografías en vertical no hace girar las imágenes finales”

El método setCameraDisplayOrientation () le permite cambiar la visualización de la vista previa sin afectar la forma en que se graba la imagen ( fuente ).

Con el fin de cambiar la imagen grabada real que necesita para establecer el parámetro de rotación de la cámara . Lo haces así:

 //STEP #1: Get rotation degrees Camera.CameraInfo info = new Camera.CameraInfo(); Camera.getCameraInfo(Camera.CameraInfo.CAMERA_FACING_BACK, info); int rotation = mActivity.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 rotate = (info.orientation - degrees + 360) % 360; //STEP #2: Set the 'rotation' parameter Camera.Parameters params = mCamera.getParameters(); params.setRotation(rotate); mCamera.setParameters(params); 

Su solución es una especie de solución ya que modifica la imagen DESPUÉS de que ya estaba grabada. Esta solución es más limpia y no requiere todas estas instrucciones 'if' antes de guardar la imagen.

El problema es cuando guardé la imagen que no hice bien.

 @Override public void onPictureTaken(byte[] data, Camera camera) { String timeStamp = new SimpleDateFormat( "yyyyMMdd_HHmmss").format( new Date( )); output_file_name = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM) + File.separator + timeStamp + ".jpeg"; File pictureFile = new File(output_file_name); if (pictureFile.exists()) { pictureFile.delete(); } try { FileOutputStream fos = new FileOutputStream(pictureFile); Bitmap realImage = BitmapFactory.decodeByteArray(data, 0, data.length); ExifInterface exif=new ExifInterface(pictureFile.toString()); Log.d("EXIF value", exif.getAttribute(ExifInterface.TAG_ORIENTATION)); if(exif.getAttribute(ExifInterface.TAG_ORIENTATION).equalsIgnoreCase("6")){ realImage= rotate(realImage, 90); } else if(exif.getAttribute(ExifInterface.TAG_ORIENTATION).equalsIgnoreCase("8")){ realImage= rotate(realImage, 270); } else if(exif.getAttribute(ExifInterface.TAG_ORIENTATION).equalsIgnoreCase("3")){ realImage= rotate(realImage, 180); } else if(exif.getAttribute(ExifInterface.TAG_ORIENTATION).equalsIgnoreCase("0")){ realImage= rotate(realImage, 90); } boolean bo = realImage.compress(Bitmap.CompressFormat.JPEG, 100, fos); fos.close(); ((ImageView) findViewById(R.id.imageview)).setImageBitmap(realImage); Log.d("Info", bo + ""); } catch (FileNotFoundException e) { Log.d("Info", "File not found: " + e.getMessage()); } catch (IOException e) { Log.d("TAG", "Error accessing file: " + e.getMessage()); } } public static Bitmap rotate(Bitmap bitmap, int degree) { int w = bitmap.getWidth(); int h = bitmap.getHeight(); Matrix mtx = new Matrix(); // mtx.postRotate(degree); mtx.setRotate(degree); return Bitmap.createBitmap(bitmap, 0, 0, w, h, mtx, true); } 

Puede utilizar el método siguiente para generar la vista previa correctamente cuando utilice la cámara frontal.

Este código entra en el método surfaceChanged de la vista previa de tu cámara

 @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { int angleToRotate=CommonMethods.getRoatationAngle(mActivity, Camera.CameraInfo.CAMERA_FACING_FRONT); mCamera.setDisplayOrientation(angleToRotate); } 

Este código puede ser puesto en una clase estática

  /** * Get Rotation Angle * * @param mContext * @param cameraId * probably front cam * @return angel to rotate */ public static int getRoatationAngle(Activity mContext, int cameraId) { android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo(); android.hardware.Camera.getCameraInfo(cameraId, info); int rotation = mContext.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; } return result; } 

Puede girar la imagen de esta manera. Esto se utiliza sólo cuando se toma la imagen y estamos a punto de guardar la imagen

 public static Bitmap rotate(Bitmap bitmap, int degree) { int w = bitmap.getWidth(); int h = bitmap.getHeight(); Matrix mtx = new Matrix(); mtx.postRotate(degree); return Bitmap.createBitmap(bitmap, 0, 0, w, h, mtx, true); } 

El método que se utilizará para tomar la foto

  @Override public void onPictureTaken(byte[] data, Camera camera) { int angleToRotate = getRoatationAngle(MainActivity.this, Camera.CameraInfo.CAMERA_FACING_FRONT); // Solve image inverting problem angleToRotate = angleToRotate + 180; Bitmap orignalImage = BitmapFactory.decodeByteArray(data, 0, data.length); Bitmap bitmapImage = rotate(orignalImage, angleToRotate); } 

El bitmapImage contiene la imagen correcta.

Éste debe funcionar, ExifInterface no trabaja con todos los fabricantes así que utilice CameraInfo en lugar de otro, apenas deje la cámara capturar la imagen con su rotación del defecto y después rote los datos del resultado en PictureCallback

 private PictureCallback mPicture = new PictureCallback() { @Override public void onPictureTaken(byte[] data, Camera camera) { File dir = new File(Constant.SDCARD_CACHE_PREFIX); if (!dir.exists()) { dir.mkdirs(); } File pictureFile = new File(Constant.SDCARD_TAKE_PHOTO_CACHE_PREFIX); try { Bitmap realImage = BitmapFactory.decodeByteArray(data, 0, data.length); android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo(); android.hardware.Camera.getCameraInfo(mCurrentCameraId, info); Bitmap bitmap = rotate(realImage, info.orientation); FileOutputStream fos = new FileOutputStream(pictureFile); bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos); fos.close(); } catch (FileNotFoundException e) { Log.d(TAG, "File not found: " + e.getMessage()); } catch (IOException e) { Log.d(TAG, "Error accessing file: " + e.getMessage()); } resultFileUri = Uri.fromFile(pictureFile); startEffectFragment(); } }; public static Bitmap rotate(Bitmap bitmap, int degree) { int w = bitmap.getWidth(); int h = bitmap.getHeight(); Matrix mtx = new Matrix(); mtx.postRotate(degree); return Bitmap.createBitmap(bitmap, 0, 0, w, h, mtx, true); } 

Encontré la respuesta de gran alcance para usted, apenas encuentro el mismo problema y lo resuelvo sin guardar la solución del archivo. La solución es registrar un OrientationEventListener para conseguir la orientación siempre que cambie. http://www.androidzeitgeist.com/2013/01/fixing-rotation-camera-picture.html aquí dan los detalles. Mi código es como abajo:

 private CameraOrientationListener myOrientationListener; private int rotation; protected void onCreate(Bundle savedInstanceState) { setListeners(); rotation = setCameraDisplayOrientation(CameraActivity.this, Camera.getNumberOfCameras()-1, mCamera); } public void setListeners(){ myOrientationListener = new CameraOrientationListener(this); if(myOrientationListener.canDetectOrientation()) myOrientationListener.enable(); } public static int setCameraDisplayOrientation(Activity activity, int cameraId, Camera camera) { CameraInfo info = new CameraInfo(); 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 == 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); return result; } /* * record the rotation when take photo */ public void takePhoto(){ myOrientationListener.rememberOrientation(); rotation += myOrientationListener.getRememberedOrientation(); rotation = rotation % 360; mCamera.takePicture(null, null, mPicture); } class CameraOrientationListener extends OrientationEventListener { private int currentNormalizedOrientation; private int rememberedNormalizedOrientation; public CameraOrientationListener(Context context) { super(context, SensorManager.SENSOR_DELAY_NORMAL); } @Override public void onOrientationChanged(int orientation) { // TODO Auto-generated method stub if (orientation != ORIENTATION_UNKNOWN) { currentNormalizedOrientation = normalize(orientation); } } private int normalize(int degrees) { if (degrees > 315 || degrees <= 45) { return 0; } if (degrees > 45 && degrees <= 135) { return 90; } if (degrees > 135 && degrees <= 225) { return 180; } if (degrees > 225 && degrees <= 315) { return 270; } throw new RuntimeException("The physics as we know them are no more. Watch out for anomalies."); } public void rememberOrientation() { rememberedNormalizedOrientation = currentNormalizedOrientation; } public int getRememberedOrientation() { return rememberedNormalizedOrientation; } } 

Espero eso ayude:)

Este es el mejor método para usar (Mencionado a continuación) cuando el diseño se fija en modo vertical.

 @Override protected void onResume() { super.onResume(); if (!openCamera(CameraInfo.CAMERA_FACING_BACK)) { alertCameraDialog(); } if (cOrientationEventListener == null) { cOrientationEventListener = new OrientationEventListener(this, SensorManager.SENSOR_DELAY_NORMAL) { public void onOrientationChanged(int orientation) { // determine our orientation based on sensor response int lastOrientation = mOrientation; if (orientation == ORIENTATION_UNKNOWN) return; Camera.CameraInfo info = new android.hardware.Camera.CameraInfo(); android.hardware.Camera.getCameraInfo(cameraId, info); orientation = (orientation + 45) / 90 * 90; int rotation = 0; if (info.facing == CameraInfo.CAMERA_FACING_FRONT) { rotation = (info.orientation - orientation + 360) % 360; } else { // back-facing camera rotation = (info.orientation + orientation) % 360; } Parameters params = camera.getParameters(); params.setRotation(rotation); camera.setParameters(params); } }; } if (cOrientationEventListener.canDetectOrientation()) { cOrientationEventListener.enable(); } } 

Usted utilizará OrientEventListener e implementará este método de devolución de llamada. OnOrientationChanged se llama siempre que hay un cambio en la orientación, por lo tanto, su rotación de la cámara se establecerá y la imagen se girará cuando se guarda.

  private PictureCallback myPictureCallback_JPG = new PictureCallback() { @Override public void onPictureTaken(byte[] arg0, Camera arg1) { try { File pictureFile = getOutputMediaFile(); if (pictureFile == null) { return; } FileOutputStream fos = new FileOutputStream(pictureFile); fos.write(arg0); fos.close(); camera.startPreview(); } catch (Exception e) { e.printStackTrace(); } } }; 

GetOutputMediaFile

  private static File getOutputMediaFile() { File mediaStorageDir = new File( Environment .getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "MyCameraApp"); if (!mediaStorageDir.exists()) { if (!mediaStorageDir.mkdirs()) { Log.d("MyCameraApp", "failed to create directory"); return null; } } // Create a media file name String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss") .format(new Date()); File mediaFile; mediaFile = new File(mediaStorageDir.getPath() + File.separator + "IMG_" + timeStamp + ".jpg"); return mediaFile; } 

Fuente Aquí

No tengo el representante para dejar un comentario, así que tengo que dejar otra respuesta en su lugar, aunque Nvhausid respuesta es impresionante y merece el crédito. Simple, elegante y funciona tanto para cámaras frontales como traseras en un dispositivo Samsung donde Exif y Media Cursor no lo hacen.

La única cosa que la respuesta faltaba para mí era el manejo de la imagen en espejo de la cámara frente al usuario.

Aquí está el cambio de código para eso:

 Bitmap bitmap = rotate(realImage, info.orientation, info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT); 

Y el nuevo método de rotación:

 public static Bitmap rotate(Bitmap bitmap, int degree, boolean mirror) { int w = bitmap.getWidth(); int h = bitmap.getHeight(); Matrix mtx = new Matrix(); if(mirror)mtx.setScale(1,-1); mtx.postRotate(degree); return Bitmap.createBitmap(bitmap, 0, 0, w, h, mtx, true); } 

Utilicé la nueva cámara2 api para obtener la orientación del sensor y luego girarlo en consecuencia:

  private void detectSensorOrientation() { CameraManager manager = (CameraManager) getSystemService(CAMERA_SERVICE); try { for (String cameraId : manager.getCameraIdList()) { CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId); // We don't use a front facing camera in this sample. Integer facing = characteristics.get(CameraCharacteristics.LENS_FACING); if (facing != null && facing == CameraCharacteristics.LENS_FACING_FRONT) { continue; } cameraOrientaion = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION); } } catch (CameraAccessException e) { e.printStackTrace(); } } 

Entonces con la ayuda del parámetro de cameraOrientation, giré mi cameraPhoto:

  private void generateRotatedBitmap() { if (cameraOrientaion != 0) { Matrix matrix = new Matrix(); matrix.postRotate(cameraOrientaion); rotatedPhoto = Bitmap.createBitmap(cameraPhoto, 0, 0, cameraPhoto.getWidth(), cameraPhoto.getHeight(), matrix, true); cameraPhoto.recycle(); } } 
FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.