Je capture une image et la place en vue image.
public void captureImage() { Intent intentCamera = new Intent("android.media.action.IMAGE_CAPTURE"); File filePhoto = new File(Environment.getExternalStorageDirectory(), "Pic.jpg"); imageUri = Uri.fromFile(filePhoto); MyApplicationGlobal.imageUri = imageUri.getPath(); intentCamera.putExtra(MediaStore.EXTRA_OUTPUT, imageUri); startActivityForResult(intentCamera, TAKE_PICTURE); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent intentFromCamera) { super.onActivityResult(requestCode, resultCode, intentFromCamera); if (resultCode == RESULT_OK && requestCode == TAKE_PICTURE) { if (intentFromCamera != null) { Bundle extras = intentFromCamera.getExtras(); if (extras.containsKey("data")) { bitmap = (Bitmap) extras.get("data"); } else { bitmap = getBitmapFromUri(); } } else { bitmap = getBitmapFromUri(); } // imageView.setImageBitmap(bitmap); imageView.setImageURI(imageUri); } else { } } public Bitmap getBitmapFromUri() { getContentResolver().notifyChange(imageUri, null); ContentResolver cr = getContentResolver(); Bitmap bitmap; try { bitmap = android.provider.MediaStore.Images.Media.getBitmap(cr, imageUri); return bitmap; } catch (Exception e) { e.printStackTrace(); return null; } }
Mais le problème est l’image sur certains appareils à chaque rotation. Par exemple, sur un appareil Samsung, cela fonctionne bien, mais sur un Sony Xperia, l’image est pivotée de 90 degrés et sur Toshiba Thrive (tablette) de 180 degrés.
La plupart des caméras téléphoniques sont en mode paysage, ce qui signifie que si vous prenez la photo en portrait, les photos qui en résultent seront pivotées de 90 degrés. Dans ce cas, le logiciel de la caméra doit renseigner les données Exif avec l’orientation dans laquelle la photo doit être affichée.
Notez que la solution ci-dessous dépend du fabricant du logiciel / périphérique de la caméra qui alimente les données Exif, de sorte qu’il fonctionnera dans la plupart des cas, mais il ne s’agit pas d’une solution fiable à 100%.
ExifInterface ei = new ExifInterface(photoPath); int orientation = ei.getAtsortingbuteInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED); Bitmap rotatedBitmap = null; switch(orientation) { case ExifInterface.ORIENTATION_ROTATE_90: rotatedBitmap = rotateImage(bitmap, 90); break; case ExifInterface.ORIENTATION_ROTATE_180: rotatedBitmap = rotateImage(bitmap, 180); break; case ExifInterface.ORIENTATION_ROTATE_270: rotatedBitmap = rotateImage(bitmap, 270); break; case ExifInterface.ORIENTATION_NORMAL: default: rotatedBitmap = bitmap; }
Voici la méthode rotateImage
:
public static Bitmap rotateImage(Bitmap source, float angle) { Masortingx masortingx = new Masortingx(); masortingx.postRotate(angle); return Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(), masortingx, true); }
En combinant la réponse de Jason Robinson à la réponse de Felix et en remplissant les parties manquantes, voici la solution complète finale pour ce problème qui fera les choses suivantes après l’avoir testée sur Android Android 4.1 ( Jelly Bean ), Android 4.4 ( KitKat ) et Android 5.0 ( Lollipop ).
Pas
Réduisez l’image si elle était supérieure à 1024×1024.
Faites pivoter l’image vers la bonne orientation uniquement si elle a pivoté de 90, 180 ou 270 degrés.
Recyclez l’image pivotée à des fins de mémoire.
Voici la partie code:
Appelez la méthode suivante avec le Context
actuel et l’ URI
l’image à corriger
/** * This method is responsible for solving the rotation issue if exist. Also scale the images to * 1024x1024 resolution * * @param context The current context * @param selectedImage The Image URI * @return Bitmap image results * @throws IOException */ public static Bitmap handleSamplingAndRotationBitmap(Context context, Uri selectedImage) throws IOException { int MAX_HEIGHT = 1024; int MAX_WIDTH = 1024; // First decode with inJustDecodeBounds=true to check dimensions final BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; InputStream imageStream = context.getContentResolver().openInputStream(selectedImage); BitmapFactory.decodeStream(imageStream, null, options); imageStream.close(); // Calculate inSampleSize options.inSampleSize = calculateInSampleSize(options, MAX_WIDTH, MAX_HEIGHT); // Decode bitmap with inSampleSize set options.inJustDecodeBounds = false; imageStream = context.getContentResolver().openInputStream(selectedImage); Bitmap img = BitmapFactory.decodeStream(imageStream, null, options); img = rotateImageIfRequired(context, img, selectedImage); return img; }
Voici la méthode CalculateInSampleSize
de la source précitée:
/** * Calculate an inSampleSize for use in a {@link BitmapFactory.Options} object when decoding * bitmaps using the decode* methods from {@link BitmapFactory}. This implementation calculates * the closest inSampleSize that will result in the final decoded bitmap having a width and * height equal to or larger than the requested width and height. This implementation does not * ensure a power of 2 is returned for inSampleSize which can be faster when decoding but * results in a larger bitmap which isn't as useful for caching purposes. * * @param options An options object with out* params already populated (run through a decode* * method with inJustDecodeBounds==true * @param reqWidth The requested width of the resulting bitmap * @param reqHeight The requested height of the resulting bitmap * @return The value to be used for inSampleSize */ private static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) { // Raw height and width of image final int height = options.outHeight; final int width = options.outWidth; int inSampleSize = 1; if (height > reqHeight || width > reqWidth) { // Calculate ratios of height and width to requested height and width final int heightRatio = Math.round((float) height / (float) reqHeight); final int widthRatio = Math.round((float) width / (float) reqWidth); // Choose the smallest ratio as inSampleSize value, this will guarantee a final image // with both dimensions larger than or equal to the requested height and width. inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio; // This offers some additional logic in case the image has a strange // aspect ratio. For example, a panorama may have a much larger // width than height. In these cases the total pixels might still // end up being too large to fit comfortably in memory, so we should // be more aggressive with sample down the image (=larger inSampleSize). final float totalPixels = width * height; // Anything more than 2x the requested pixels we'll sample down further final float totalReqPixelsCap = reqWidth * reqHeight * 2; while (totalPixels / (inSampleSize * inSampleSize) > totalReqPixelsCap) { inSampleSize++; } } return inSampleSize; }
Vient ensuite la méthode qui vérifiera l’orientation actuelle de l’image pour décider de l’angle de rotation
/** * Rotate an image if required. * * @param img The image bitmap * @param selectedImage Image URI * @return The resulted Bitmap after manipulation */ private static Bitmap rotateImageIfRequired(Context context, Bitmap img, Uri selectedImage) throws IOException { InputStream input = context.getContentResolver().openInputStream(selectedImage); ExifInterface ei; if (Build.VERSION.SDK_INT > 23) ei = new ExifInterface(input); else ei = new ExifInterface(selectedImage.getPath()); int orientation = ei.getAtsortingbuteInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL); switch (orientation) { case ExifInterface.ORIENTATION_ROTATE_90: return rotateImage(img, 90); case ExifInterface.ORIENTATION_ROTATE_180: return rotateImage(img, 180); case ExifInterface.ORIENTATION_ROTATE_270: return rotateImage(img, 270); default: return img; } }
Enfin la méthode de rotation elle-même
private static Bitmap rotateImage(Bitmap img, int degree) { Masortingx masortingx = new Masortingx(); masortingx.postRotate(degree); Bitmap rotatedImg = Bitmap.createBitmap(img, 0, 0, img.getWidth(), img.getHeight(), masortingx, true); img.recycle(); return rotatedImg; }
-Ne pas oublier de voter pour ces réponses des gars pour leurs efforts et Shirish Herwade qui a posé cette question utile.
Il est facile de détecter l’orientation de l’image et de remplacer le bitmap par:
/** * Rotate an image if required. * @param img * @param selectedImage * @return */ private static Bitmap rotateImageIfRequired(Context context,Bitmap img, Uri selectedImage) { // Detect rotation int rotation = getRotation(context, selectedImage); if (rotation != 0) { Masortingx masortingx = new Masortingx(); masortingx.postRotate(rotation); Bitmap rotatedImg = Bitmap.createBitmap(img, 0, 0, img.getWidth(), img.getHeight(), masortingx, true); img.recycle(); return rotatedImg; } else{ return img; } } /** * Get the rotation of the last image added. * @param context * @param selectedImage * @return */ private static int getRotation(Context context,Uri selectedImage) { int rotation = 0; ContentResolver content = context.getContentResolver(); Cursor mediaCursor = content.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, new Ssortingng[] { "orientation", "date_added" }, null, null, "date_added desc"); if (mediaCursor != null && mediaCursor.getCount() != 0) { while(mediaCursor.moveToNext()){ rotation = mediaCursor.getInt(0); break; } } mediaCursor.close(); return rotation; }
Pour éviter les souvenirs avec de grandes images, je vous recommande de redimensionner l’image en utilisant:
private static final int MAX_HEIGHT = 1024; private static final int MAX_WIDTH = 1024; public static Bitmap decodeSampledBitmap(Context context, Uri selectedImage) throws IOException { // First decode with inJustDecodeBounds=true to check dimensions final BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; InputStream imageStream = context.getContentResolver().openInputStream(selectedImage); BitmapFactory.decodeStream(imageStream, null, options); imageStream.close(); // Calculate inSampleSize options.inSampleSize = calculateInSampleSize(options, MAX_WIDTH, MAX_HEIGHT); // Decode bitmap with inSampleSize set options.inJustDecodeBounds = false; imageStream = context.getContentResolver().openInputStream(selectedImage); Bitmap img = BitmapFactory.decodeStream(imageStream, null, options); img = rotateImageIfRequired(img, selectedImage); return img; }
Il est impossible d’utiliser ExifInterface pour obtenir l’orientation, car un problème de système d’exploitation Android: https://code.google.com/p/android/issues/detail?id=19268
Et voici calculateInSampleSize
/** * Calculate an inSampleSize for use in a {@link BitmapFactory.Options} object when decoding * bitmaps using the decode* methods from {@link BitmapFactory}. This implementation calculates * the closest inSampleSize that will result in the final decoded bitmap having a width and * height equal to or larger than the requested width and height. This implementation does not * ensure a power of 2 is returned for inSampleSize which can be faster when decoding but * results in a larger bitmap which isn't as useful for caching purposes. * * @param options An options object with out* params already populated (run through a decode* * method with inJustDecodeBounds==true * @param reqWidth The requested width of the resulting bitmap * @param reqHeight The requested height of the resulting bitmap * @return The value to be used for inSampleSize */ public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) { // Raw height and width of image final int height = options.outHeight; final int width = options.outWidth; int inSampleSize = 1; if (height > reqHeight || width > reqWidth) { // Calculate ratios of height and width to requested height and width final int heightRatio = Math.round((float) height / (float) reqHeight); final int widthRatio = Math.round((float) width / (float) reqWidth); // Choose the smallest ratio as inSampleSize value, this will guarantee a final image // with both dimensions larger than or equal to the requested height and width. inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio; // This offers some additional logic in case the image has a strange // aspect ratio. For example, a panorama may have a much larger // width than height. In these cases the total pixels might still // end up being too large to fit comfortably in memory, so we should // be more aggressive with sample down the image (=larger inSampleSize). final float totalPixels = width * height; // Anything more than 2x the requested pixels we'll sample down further final float totalReqPixelsCap = reqWidth * reqHeight * 2; while (totalPixels / (inSampleSize * inSampleSize) > totalReqPixelsCap) { inSampleSize++; } } return inSampleSize; }
Une solution en ligne:
Picasso.with(context).load("http://soffr.miximages.com/android/DvpvklR.jpg").into(imageView);
Ou
Picasso.with(context).load("file:" + photoPath).into(imageView);
Cela détectera automatiquement la rotation et placera l’image dans l’orientation correcte
Picasso est une bibliothèque très puissante pour la gestion des images dans votre application, notamment: Transformations d’images complexes avec une utilisation minimale de la mémoire.
// Try this way,hope this will help you to solve your problem...
activity_main.xml
MainActivity.java
public class MainActivity extends Activity { private ImageView imgFromCameraOrGallery; private Button btnCamera; private Button btnGallery; private Ssortingng imgPath; final private int PICK_IMAGE = 1; final private int CAPTURE_IMAGE = 2; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); imgFromCameraOrGallery = (ImageView) findViewById(R.id.imgFromCameraOrGallery); btnCamera = (Button) findViewById(R.id.btnCamera); btnGallery = (Button) findViewById(R.id.btnGallery); btnCamera.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { final Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); intent.putExtra(MediaStore.EXTRA_OUTPUT, setImageUri()); startActivityForResult(intent, CAPTURE_IMAGE); } }); btnGallery.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(); intent.setType("image/*"); intent.setAction(Intent.ACTION_GET_CONTENT); startActivityForResult(Intent.createChooser(intent, ""), PICK_IMAGE); } }); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (resultCode == Activity.RESULT_OK) { if (requestCode == CAPTURE_IMAGE) { setCapturedImage(getImagePath()); } else if (requestCode == PICK_IMAGE) { imgFromCameraOrGallery.setImageBitmap(BitmapFactory.decodeFile(getAbsolutePath(data.getData()))); } } } private Ssortingng getRightAngleImage(Ssortingng photoPath) { try { ExifInterface ei = new ExifInterface(photoPath); int orientation = ei.getAtsortingbuteInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL); int degree = 0; switch (orientation) { case ExifInterface.ORIENTATION_NORMAL: degree = 0; break; case ExifInterface.ORIENTATION_ROTATE_90: degree = 90; break; case ExifInterface.ORIENTATION_ROTATE_180: degree = 180; break; case ExifInterface.ORIENTATION_ROTATE_270: degree = 270; break; case ExifInterface.ORIENTATION_UNDEFINED: degree = 0; break; default: degree = 90; } return rotateImage(degree,photoPath); } catch (Exception e) { e.printStackTrace(); } return photoPath; } private Ssortingng rotateImage(int degree, Ssortingng imagePath){ if(degree<=0){ return imagePath; } try{ Bitmap b= BitmapFactory.decodeFile(imagePath); Matrix matrix = new Matrix(); if(b.getWidth()>b.getHeight()){ masortingx.setRotate(degree); b = Bitmap.createBitmap(b, 0, 0, b.getWidth(), b.getHeight(), masortingx, true); } FileOutputStream fOut = new FileOutputStream(imagePath); Ssortingng imageName = imagePath.subssortingng(imagePath.lastIndexOf("/") + 1); Ssortingng imageType = imageName.subssortingng(imageName.lastIndexOf(".") + 1); FileOutputStream out = new FileOutputStream(imagePath); if (imageType.equalsIgnoreCase("png")) { b.compress(Bitmap.CompressFormat.PNG, 100, out); }else if (imageType.equalsIgnoreCase("jpeg")|| imageType.equalsIgnoreCase("jpg")) { b.compress(Bitmap.CompressFormat.JPEG, 100, out); } fOut.flush(); fOut.close(); b.recycle(); }catch (Exception e){ e.printStackTrace(); } return imagePath; } private void setCapturedImage(final Ssortingng imagePath){ new AsyncTask(){ @Override protected Ssortingng doInBackground(Void... params) { try { return getRightAngleImage(imagePath); }catch (Throwable e){ e.printStackTrace(); } return imagePath; } @Override protected void onPostExecute(Ssortingng imagePath) { super.onPostExecute(imagePath); imgFromCameraOrGallery.setImageBitmap(decodeFile(imagePath)); } }.execute(); } public Bitmap decodeFile(Ssortingng path) { try { // Decode deal_image size BitmapFactory.Options o = new BitmapFactory.Options(); o.inJustDecodeBounds = true; BitmapFactory.decodeFile(path, o); // The new size we want to scale to final int REQUIRED_SIZE = 1024; // Find the correct scale value. It should be the power of 2. int scale = 1; while (o.outWidth / scale / 2 >= REQUIRED_SIZE && o.outHeight / scale / 2 >= REQUIRED_SIZE) scale *= 2; // Decode with inSampleSize BitmapFactory.Options o2 = new BitmapFactory.Options(); o2.inSampleSize = scale; return BitmapFactory.decodeFile(path, o2); } catch (Throwable e) { e.printStackTrace(); } return null; } public Ssortingng getAbsolutePath(Uri uri) { if(Build.VERSION.SDK_INT >= 19){ Ssortingng id = ""; if(uri.getLastPathSegment().split(":").length > 1) id = uri.getLastPathSegment().split(":")[1]; else if(uri.getLastPathSegment().split(":").length > 0) id = uri.getLastPathSegment().split(":")[0]; if(id.length() > 0){ final Ssortingng[] imageColumns = {MediaStore.Images.Media.DATA }; final Ssortingng imageOrderBy = null; Uri tempUri = getUri(); Cursor imageCursor = getContentResolver().query(tempUri, imageColumns, MediaStore.Images.Media._ID + "=" + id, null, imageOrderBy); if (imageCursor.moveToFirst()) { return imageCursor.getSsortingng(imageCursor.getColumnIndex(MediaStore.Images.Media.DATA)); }else{ return null; } }else{ return null; } }else{ Ssortingng[] projection = { MediaStore.MediaColumns.DATA }; Cursor cursor = getContentResolver().query(uri, projection, null, null, null); if (cursor != null) { int column_index = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA); cursor.moveToFirst(); return cursor.getSsortingng(column_index); } else return null; } } private Uri getUri() { Ssortingng state = Environment.getExternalStorageState(); if(!state.equalsIgnoreCase(Environment.MEDIA_MOUNTED)) return MediaStore.Images.Media.INTERNAL_CONTENT_URI; return MediaStore.Images.Media.EXTERNAL_CONTENT_URI; } public Uri setImageUri() { Uri imgUri; Ssortingng state = Environment.getExternalStorageState(); if (Environment.MEDIA_MOUNTED.equals(state)) { File file = new File(Environment.getExternalStorageDirectory() + "/DCIM/",getSsortingng(R.ssortingng.app_name) + Calendar.getInstance().getTimeInMillis() + ".png"); imgUri = Uri.fromFile(file); imgPath = file.getAbsolutePath(); }else { File file = new File(getFilesDir() ,getSsortingng(R.ssortingng.app_name) + Calendar.getInstance().getTimeInMillis()+ ".png"); imgUri = Uri.fromFile(file); this.imgPath = file.getAbsolutePath(); } return imgUri; } public Ssortingng getImagePath() { return imgPath; } }
Vous pouvez simplement lire l’orientation du capteur de la caméra comme indiqué par Google dans la documentation: https://developer.android.com/reference/android/hardware/camera2/CameraCharacteristics.html
SENSOR_ORIENTATION Added in API level 21 Key SENSOR_ORIENTATION Clockwise angle through which the output image needs to be rotated to be upright on the device screen in its native orientation. Also defines the direction of rolling shutter readout, which is from top to bottom in the sensor's coordinate system. Units: Degrees of clockwise rotation; always a multiple of 90 Range of valid values: 0, 90, 180, 270 This key is available on all devices.
Exemple de code:
CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE); int orientation = 0; try { Ssortingng cameraId = manager.getCameraIdList()[0]; CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId); orientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION); } catch (Exception e) { }
Normalement, il est recommandé de résoudre le problème avec l’ interface ExifInter , comme l’a suggéré @Jason Robinson. Si cette approche ne fonctionne pas, vous pouvez chercher l’ orientation de la dernière image prise …
private int getImageOrientation(){ final Ssortingng[] imageColumns = { MediaStore.Images.Media._ID, MediaStore.Images.ImageColumns.ORIENTATION }; final Ssortingng imageOrderBy = MediaStore.Images.Media._ID+" DESC"; Cursor cursor = getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, imageColumns, null, null, imageOrderBy); if(cursor.moveToFirst()){ int orientation = cursor.getInt(cursor.getColumnIndex(MediaStore.Images.ImageColumns.ORIENTATION)); cursor.close(); return orientation; } else { return 0; } }
J’ai passé beaucoup de temps à chercher une solution pour cela. Et finalement réussi à faire cela. N’oubliez pas de voter @Jason Robinson pour répondre car mon est basé sur le sien.
En premier lieu, vous devez savoir que, depuis Android 7.0, nous devons utiliser FileProvider
et quelque chose appelé ContentUri
, sinon vous obtiendrez une erreur agaçante en essayant d’invoquer votre Intent
. Ceci est un exemple de code:
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); intent.putExtra(MediaStore.EXTRA_OUTPUT, getUriFromPath(context, "[Your path to save image]")); startActivityForResult(intent, CAPTURE_IMAGE_RESULT);
Méthode getUriFromPath(Context, Ssortingng)
base sur la version utilisateur d’Android crée FileUri (file://...)
ou ContentUri (content://...)
et la ContentUri (content://...)
:
public Uri getUriFromPath(Context context, Ssortingng destination) { File file = new File(destination); if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) { return FileProvider.getUriForFile(context, context.getPackageName() + ".provider", file); } else { return Uri.fromFile(file); } }
Après onActivityResult
vous pouvez capturer l’ onActivityResult
où l’image est enregistrée par la caméra, mais maintenant vous devez détecter la rotation de la caméra, nous allons utiliser la réponse @Jason Robinson modifiée:
Nous devons d’abord créer ExifInterface
basé sur Uri
@Nullable public ExifInterface getExifInterface(Context context, Uri uri) { try { Ssortingng path = uri.toSsortingng(); if (path.startsWith("file://")) { return new ExifInterface(path); } if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { if (path.startsWith("content://")) { InputStream inputStream = context.getContentResolver().openInputStream(uri); return new ExifInterface(inputStream); } } } catch (IOException e) { e.printStackTrace(); } return null; }
Le code ci-dessus peut être simplifié, mais je veux tout montrer. Donc, à partir de FileUri
nous pouvons créer ExifInterface
basé sur le Ssortingng path
, mais à partir de ContentUri
nous ne pouvons pas, Android ne le supporte pas.
Dans ce cas, nous devons utiliser un autre constructeur basé sur InputStream
. Rappelez-vous que ce constructeur n’est pas disponible par défaut, vous devez append une bibliothèque supplémentaire:
comstack "com.android.support:exifinterface:XX.XX"
Maintenant, nous pouvons utiliser la méthode getExifInterface
pour obtenir notre angle:
public float getExifAngle(Context context, Uri uri) { try { ExifInterface exifInterface = getExifInterface(context, uri); if(exifInterface == null) { return -1f; } int orientation = exifInterface.getAtsortingbuteInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED); switch (orientation) { case ExifInterface.ORIENTATION_ROTATE_90: return 90f; case ExifInterface.ORIENTATION_ROTATE_180: return 180f; case ExifInterface.ORIENTATION_ROTATE_270: return 270f; case ExifInterface.ORIENTATION_NORMAL: return 0f; case ExifInterface.ORIENTATION_UNDEFINED: return -1f; default: return -1f; } } catch (Exception e) { e.printStackTrace(); return -1f; } }
Maintenant vous avez Angle pour bien faire pivoter votre image :).
Malheureusement, la réponse de @ jason-robinson ci-dessus n’a pas fonctionné pour moi.
Bien que la fonction de rotation fonctionne parfaitement:
public static Bitmap rotateImage(Bitmap source, float angle) { Masortingx masortingx = new Masortingx(); masortingx.postRotate(angle); return Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(), masortingx, true); }
J’ai dû faire ce qui suit pour obtenir l’orientation car l’orientation Exif était toujours 0
protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode,resultCode,data); if (requestCode == RESULT_LOAD_IMAGE && resultCode == RESULT_OK && data != null) { Uri selectedImage = data.getData(); Ssortingng[] orientationColumn = {MediaStore.Images.Media.ORIENTATION}; Cursor cur = managedQuery(imageUri, orientationColumn, null, null, null); int orientation = -1; if (cur != null && cur.moveToFirst()) { orientation = cur.getInt(cur.getColumnIndex(orientationColumn[0])); } InputStream imageStream = getContentResolver().openInputStream(selectedImage); Bitmap bitmap = BitmapFactory.decodeStream(imageStream); switch(orientation) { case 90: bitmap = rotateImage(chosen_image_bitmap, 90); break; case 180: bitmap = rotateImage(chosen_image_bitmap, 180); break; case 270: bitmap = rotateImage(chosen_image_bitmap, 270); break; default: break; } imageView.setImageBitmap(bitmap );
Si quelqu’un rencontre des problèmes avec ExifInterface
sur Android 4.4 (KitKat) pour obtenir l’orientation, cela peut être dû à un chemin erroné provenant de l’URI. Voir une solution pour obtenir un meilleur getPath
dans la question Stack Overflow Obtenir un vrai chemin depuis l’URI, le nouveau framework d’access au stockage Android KitKat
La réponse sélectionnée utilise la méthode la plus courante pour répondre à cette question et à des questions similaires. Cependant, il ne fonctionne pas avec les caméras avant et arrière sur Samsung. Pour ceux qui recherchent une solution compatible avec les caméras avant et arrière pour Samsung et les autres grands fabricants, cette réponse de nvhausid est géniale:
https://stackoverflow.com/a/18915443/6080472
Pour ceux qui ne veulent pas cliquer, la magie appropriée consiste à utiliser CameraInfo plutôt que d’utiliser EXIF.
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);
Code complet dans le lien.
Mieux vaut essayer de prendre la photo dans une orientation spécifique.
android:screenOrientation="landscape" android:configChanges="orientation|keyboardHidden"
Pour de meilleurs résultats, donnez une orientation paysage dans l’activité de visualisation de cameraview.
Cela va sans dire, mais rappelez-vous toujours que vous pouvez gérer certains de ces problèmes de traitement des images sur votre serveur. J’ai utilisé des réponses comme celles contenues dans ce fil pour gérer l’affichage immédiat de l’image. Cependant, mon application nécessite que les images soient stockées sur le serveur (ceci est probablement une exigence courante si vous souhaitez que l’image persiste lorsque les utilisateurs changent de téléphone).
Les solutions contenues dans la plupart des threads concernant ce sujet n’évoquent pas le manque de persistance des données EXIF qui ne survivent pas à la compression de l’image Bitmap, ce qui signifie que vous devrez faire pivoter l’image à chaque chargement de votre serveur. Vous pouvez également envoyer les données d’orientation EXIF à votre serveur, puis faire pivoter l’image si nécessaire.
Il était plus facile pour moi de créer une solution permanente sur un serveur car je n’avais pas à me soucier des chemins de fichiers clandestins d’Android.
Il existe une commande plus simple pour corriger cette erreur.
Il suffit d’append simplement votre imageImageView.setBitmap (bitmap); this yourImageView.setRotation (90);
Cette mine fixe. J’espère que cela aide !
La réponse de Jason Robinson et la réponse de Sami Eltamawy sont excellentes.
Juste une amélioration pour compléter l’approche, vous devez utiliser compat ExifInterface.
com.android.support:exifinterface:${lastLibVersion}
Vous serez en mesure d’instancier l’ExifInterface (API pior <24) avec InputStream
(à partir de ContentResolver
) au lieu des chemins uri en évitant “Fichier non trouvé exceptions”
https://android-developers.googleblog.com/2016/12/introducing-the-exifinterface-support-library.html
Essayez ce qui suit si vous rencontrez un problème avec S4.
android:configChanges="locale|touchscreen|orientation|screenLayout|screenSize|keyboardHidden|uiMode"
La solution la plus simple à ce problème:
captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION));
Je sauvegarde l’image au format jpg.