Valor de etiqueta de orientación EXIF ​​siempre 0 para imagen tomada con la aplicación de cámara de retrato de Android

Tengo una aplicación de cámara en modo retrato que toma imágenes de las cámaras frontales y posteriores. Estoy guardando la imagen en mi tarjeta sd e bash encontrar el valor exif correspondiente que siempre da 0. Pero obtengo la orientación exif esperada valor para las otras imágenes almacenadas en el dispositivo (como imágenes descargadas).

Cómo puedo arreglar esto ? Puede alguien ayudarme ?

Aquí está el código usado para guardar la imagen y encontrar la orientación

PictureCallback myPictureCallback_JPG = new PictureCallback() { @Override public void onPictureTaken(byte[] arg0, Camera arg1) { // TODO Auto-generated method stub try { File APP_FILE_PATH = new File(Environment.getExternalStorageDirectory() .getPath() + "/Myapp/"); if (!APP_FILE_PATH.exists()) { APP_FILE_PATH.mkdirs(); } File file = new File(APP_FILE_PATH, "image.jpg"); FileOutputStream fos = new FileOutputStream(file); fos.write(arg0); fos.close(); imageFileUri=Uri.fromfile(file); getApplicationContext().getContentResolver().notifyChange( imageFileUri, null); sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://" + Environment.getExternalStorageDirectory()))); ExifInterface exif = new ExifInterface(file.getAbsolutePath()); int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL); } catch (Exception e) { } } }; 

A continuación se muestra el código para las funciones creadas y cambiadas de surface

 @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { List sizes = parameters.getSupportedPreviewSizes(); Size optimalSize = getOptimalPreviewSize(sizes, width, height); parameters.setPreviewSize(optimalSize.width, optimalSize.height); camera.setParameters(parameters); camera.startPreview(); startPreview(); } @Override public void surfaceCreated(SurfaceHolder holder) { try { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) { Camera.CameraInfo info=new Camera.CameraInfo(); for (int i=0; i = 8) { 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; } else { // back-facing result = (info.orientation - degrees + 360) % 360; } camera.setDisplayOrientation(result); } else { parameters.set("orientation", "portrait"); } camera.setParameters(parameters); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } } private Size getOptimalPreviewSize(List sizes, int w, int h) { final double ASPECT_TOLERANCE = 0.1; double targetRatio = (double) w / h; if (sizes == null) return null; Size optimalSize = null; double minDiff = Double.MAX_VALUE; int targetHeight = h; for (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); } } 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; } 

También me enfrenté al mismo problema en los dispositivos de Samsung, luego implementé ExifInterface y lo resolví con éxito.

En cualquier modo en que se filmen las imágenes, siempre se almacenará en modo retrato solamente, y mientras se recupera también regresará en modo retrato. debajo del código que utilicé para lograr mi objective, lo implementé dentro de la cámara trasera, no estoy seguro acerca de la cámara.

Camera Intent @

 Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE); intent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri); startActivityForResult(intent, 1212); 

onActivityResult @

 @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == 1212) { sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://"+ Environment.getExternalStorageDirectory()))); Bitmap bitmap; //bitmap=GlobalMethods.decodeSampledBitmapFromResource(_path, 80, 80); bitmap=GlobalMethods.decodeFile(_path); if (bitmap == null) { imgMed.setImageBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.add_photo)); } else { imgMed.setImageBitmap(bitmap); imgMed.setScaleType(ScaleType.FIT_XY); } } } 

decodeFile @

  public static Bitmap decodeFile(String path) { int orientation; try { if(path==null){ return null; } // decode image size BitmapFactory.Options o = new BitmapFactory.Options(); o.inJustDecodeBounds = true; // Find the correct scale value. It should be the power of 2. final int REQUIRED_SIZE = 70; int width_tmp = o.outWidth, height_tmp = o.outHeight; int scale = 4; while (true) { if (width_tmp / 2 < REQUIRED_SIZE || height_tmp / 2 < REQUIRED_SIZE) break; width_tmp /= 2; height_tmp /= 2; scale++; } // decode with inSampleSize BitmapFactory.Options o2 = new BitmapFactory.Options(); o2.inSampleSize=scale; Bitmap bm = BitmapFactory.decodeFile(path,o2); Bitmap bitmap = bm; ExifInterface exif = new ExifInterface(path); orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1); Log.e("orientation",""+orientation); Matrix m=new Matrix(); if((orientation==3)){ m.postRotate(180); m.postScale((float)bm.getWidth(), (float)bm.getHeight()); // if(m.preRotate(90)){ Log.e("in orientation",""+orientation); bitmap = Bitmap.createBitmap(bm, 0, 0,bm.getWidth(),bm.getHeight(), m, true); return bitmap; } else if(orientation==6){ m.postRotate(90); Log.e("in orientation",""+orientation); bitmap = Bitmap.createBitmap(bm, 0, 0,bm.getWidth(),bm.getHeight(), m, true); return bitmap; } else if(orientation==8){ m.postRotate(270); Log.e("in orientation",""+orientation); bitmap = Bitmap.createBitmap(bm, 0, 0,bm.getWidth(),bm.getHeight(), m, true); return bitmap; } return bitmap; } catch (Exception e) { } return null; } 

El problema es que debe poner la información exif manualmente en su función onPictureTaken .

Después de guardar la imagen (jpg) debe crear una interfaz Exif y poner los parámetros usted mismo:

 .... exif = new ExifInterface(file.getAbsolutePath()); exif.setAttribute(ExifInterface.TAG_ORIENTATION, orientation_detected_by_you_application); exif.saveAttributes(); 

Las otras imágenes que tiene en su teléfono están hechas con una aplicación que coloca la información exif en las imágenes que toma.

Para detectar orientación:

 public void enableOrientationListener(){ if (mOrientationEventListener == null) { mOrientationEventListener = new OrientationEventListener(getContext(), SensorManager.SENSOR_DELAY_NORMAL) { @Override public void onOrientationChanged(int orientation) { // determine our orientation based on sensor response int lastOrientation = mOrientation; Display display = null; if(parentActivity == null){ display = ((WindowManager)getContext().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); }else{ display = parentActivity.getWindowManager().getDefaultDisplay(); } if (display.getOrientation() == Surface.ROTATION_0) { // landscape oriented devices if (orientation >= 315 || orientation < 45) { if (mOrientation != ORIENTATION_LANDSCAPE_NORMAL) { mOrientation = ORIENTATION_LANDSCAPE_NORMAL; } } else if (orientation < 315 && orientation >= 225) { if (mOrientation != ORIENTATION_PORTRAIT_INVERTED) { mOrientation = ORIENTATION_PORTRAIT_INVERTED; } } else if (orientation < 225 && orientation >= 135) { if (mOrientation != ORIENTATION_LANDSCAPE_INVERTED) { mOrientation = ORIENTATION_LANDSCAPE_INVERTED; } } else if (orientation <135 && orientation > 45) { if (mOrientation != ORIENTATION_PORTRAIT_NORMAL) { mOrientation = ORIENTATION_PORTRAIT_NORMAL; } } } else { // portrait oriented devices if (orientation >= 315 || orientation < 45) { if (mOrientation != ORIENTATION_PORTRAIT_NORMAL) { mOrientation = ORIENTATION_PORTRAIT_NORMAL; } } else if (orientation < 315 && orientation >= 225) { if (mOrientation != ORIENTATION_LANDSCAPE_NORMAL) { mOrientation = ORIENTATION_LANDSCAPE_NORMAL; } } else if (orientation < 225 && orientation >= 135) { if (mOrientation != ORIENTATION_PORTRAIT_INVERTED) { mOrientation = ORIENTATION_PORTRAIT_INVERTED; } } else if (orientation <135 && orientation > 45) { if (mOrientation != ORIENTATION_LANDSCAPE_INVERTED) { mOrientation = ORIENTATION_LANDSCAPE_INVERTED; } } } } }; } if (mOrientationEventListener.canDetectOrientation()) { mOrientationEventListener.enable(); } } private static final int ORIENTATION_PORTRAIT_NORMAL = 1; private static final int ORIENTATION_PORTRAIT_INVERTED = 2; private static final int ORIENTATION_LANDSCAPE_NORMAL = 3; private static final int ORIENTATION_LANDSCAPE_INVERTED = 4; public void disableOrientationListener(){ if(mOrientationEventListener != null){ mOrientationEventListener.disable(); } } 

Y debe establecer mOrientation como atributo de orientación para su imagen.

Este problema fue resuelto hace mucho tiempo, pero encontré algunas dificultades para que la cámara funcione correctamente, así que esta es mi solución final, sin usar exif. 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 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()); } }