¿Por qué una imagen capturada con la intención de la cámara se gira en algunos dispositivos con Android?
Frecuentes
Visto 278,177 equipos
452
Estoy capturando una imagen y poniéndola en vista de imagen.
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;
}
}
Pero el problema es que la imagen en algunos dispositivos cada vez que se gira. Por ejemplo, en un dispositivo Samsung funciona bien, pero en un Sony Xperia la imagen se gira 90 grados y sigue Toshiba prospera (tableta) en 180 grados.
26 Respuestas
525
La mayoría de las cámaras de los teléfonos son horizontales, lo que significa que si toma la foto en posición vertical, las fotos resultantes girarán 90 grados. En este caso, el software de la cámara debe llenar el Exif datos con la orientación en la que se debe ver la foto.
Tenga en cuenta que la solución a continuación depende del software de la cámara/fabricante del dispositivo que completa los datos Exif, por lo que funcionará en la mayoría de los casos, pero no es una solución 100% confiable.
ExifInterface ei = new ExifInterface(photoPath);
int orientation = ei.getAttributeInt(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;
}
Aquí está la rotateImage
método:
public static Bitmap rotateImage(Bitmap source, float angle) {
Matrix matrix = new Matrix();
matrix.postRotate(angle);
return Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(),
matrix, true);
}
Respondido 04 ago 17, 02:08
De los códigos de @JasonRobinson, aprendo cómo obtener la orientación real y combinándolos con estos codigos Estoy manejando con éxito la orientación. - Raditya Kurnianto
Este código es para una imagen que ya se ha escrito en el disco, ¿verdad? No obtengo resultados usando este método para el mapa de bits a punto de escribirse en el disco. - Tracio
Siempre me devuelve el valor 0. Indique cómo obtener orientación real. - Anurag Srivastava
Obteniendo 0 siempre, ¿alguna idea de por qué? - Marina Ramesan
Nota: use androidx.exifinterface.media.ExifInterface en lugar de android.media.ExifInterface - Andrés
217
Combinando jason robinson's https://www.youtube.com/watch?v=xB-eutXNUMXJtA&feature=youtu.be a Felix's https://www.youtube.com/watch?v=xB-eutXNUMXJtA&feature=youtu.be y llenando las partes faltantes, aquí está la solución completa final para este problema que hará lo siguiente después de probarlo en Android Android 4.1 (Jelly Bean), Android 4.4 (KitKat) y Android 5.0 (Chupete).
Proceso
Reduzca la escala de la imagen si era más grande que 1024x1024.
Girar la imagen a la orientación correcta , solamente si fue girar 90, 180 o 270 grados.
Recicle la imagen rotada con fines de memoria.
Aquí está la parte del código:
Llame al siguiente método con el actual Context
y la imagen URI
que quieres arreglar
/**
* 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;
}
Aquí está la CalculateInSampleSize
método de lo mencionado anteriormente fuente:
/**
* 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;
}
Luego viene el método que verificará la orientación de la imagen actual para decidir el ángulo de rotación
/**
* 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.getAttributeInt(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;
}
}
Finalmente, el método de rotación en sí
private static Bitmap rotateImage(Bitmap img, int degree) {
Matrix matrix = new Matrix();
matrix.postRotate(degree);
Bitmap rotatedImg = Bitmap.createBitmap(img, 0, 0, img.getWidth(), img.getHeight(), matrix, true);
img.recycle();
return rotatedImg;
}
-No olvides votar por las respuestas de esos tipos por sus esfuerzos y Shirish Herwade quien hizo esta útil pregunta.
Respondido el 13 de Septiembre de 17 a las 03:09
el método rotarImagenSiRequired() funciona muy bien... ¡gracias! - mapa
no funciona para mi A veces, mi teléfono ofrece fotos de retratos, a veces de paisajes, pero la orientación detectada siempre es de 0 grados. - Déjalo dormir
@Makalele ¿Este problema también ocurre al tomar fotos y adjuntarlas a través de WhatsApp? - manoj perumarath
No uso WhatsApp, así que no puedo decirlo, pero lo más probable es que sí. Eso es porque incluso sucede en la aplicación de fotos de archivo (Google Stock Camera). - Déjalo dormir
49
Es fácil detectar la orientación de la imagen y reemplazar el mapa de bits usando:
/**
* 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) {
Matrix matrix = new Matrix();
matrix.postRotate(rotation);
Bitmap rotatedImg = Bitmap.createBitmap(img, 0, 0, img.getWidth(), img.getHeight(), matrix, 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 String[] { "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;
}
Para evitar quedarse sin recuerdos con imágenes grandes, te recomiendo que cambies la escala de la imagen usando:
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;
}
No es posible usar ExifInterface para obtener la orientación debido a un problema con el sistema operativo Android: https://code.google.com/p/android/issues/detail?id=19268
Y aqui esta 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;
}
Respondido el 10 de diciembre de 16 a las 11:12
¿Qué es el método de cálculo de tamaño de muestra aquí? madhu kotagiri
@madhukotagiri, aquí tiene un ejemplo de implementación para calcular el tamaño de la muestra: gist.github.com/anonymous/b7ea25fc2bbc54e43616 - Felix
Gracias hombre, definitivamente eres el indicado! Me pregunto cuánto será útil el cambio de tamaño, si la operación se realiza ocasionalmente. - marina
El parámetro Uri selectedImage no se usa en el método getRotation(...). ¿Cómo necesitamos usarlo? Gracias. - Valerybodak
El parámetro 'selectedImage' no parece usarse en ninguna parte. ¿Alguna razón para estar allí? - Alex
24
Solución de una línea:
Picasso.with(context).load("http://i.imgur.com/DvpvklR.png").into(imageView);
Or
Picasso.with(context).load("file:" + photoPath).into(imageView);
Esto detectará automáticamente la rotación y colocará la imagen en la orientación correcta
Picasso es una biblioteca muy poderosa para manejar imágenes en su aplicación que incluye: Transformaciones de imágenes complejas con un uso mínimo de memoria.
Respondido el 12 de diciembre de 15 a las 14:12
Simplemente carga la imagen en una vista, no le proporciona un mapa de bits ni un archivo que pueda manipular o cargar en un servidor. - Mickäel A.
Su imagen de visualización hizo clic tal como está. No está girando como se requiere. - Seema
@Flawyte puede hacerlo cargando el archivo en el destino en lugar de verlo con devolución de llamada que devuelve un mapa de bits recortado/redimensionado: Picasso.with(this).load(cropUriToLoad.resize(1080, 810).centerInside().into(target); where target = new Target() { Anular public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) { - Voytez
el problema al que todavía me enfrento es que tarda unos segundos en mostrar la imagen: Anu
no funciona para mí ... este problema también existe en Picasso: NehaK
14
He pasado mucho tiempo buscando una solución para esto. Y finalmente logró hacer esto. No olvides votar a favor la respuesta de @Jason Robinson porque mi respuesta está basada en la suya.
Así que lo primero que debes saber es que desde Android 7.0 tenemos que usar FileProvider
y algo llamado ContentUri
, de lo contrario obtendrá un molesto error al intentar invocar su Intent
. Este es un código de muestra:
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étodo getUriFromPath(Context, String)
basado en la versión de usuario de Android crear FileUri (file://...)
or ContentUri (content://...)
y ahí está:
public Uri getUriFromPath(Context context, String 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);
}
}
Después onActivityResult
puedes atrapar eso uri
donde la cámara guarda la imagen, pero ahora debe detectar la rotación de la cámara, aquí usaremos la respuesta modificada de @Jason Robinson:
Primero tenemos que crear ExifInterface
basados en Uri
@Nullable
public ExifInterface getExifInterface(Context context, Uri uri) {
try {
String path = uri.toString();
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;
}
El código anterior se puede simplificar, pero quiero mostrar todo. entonces desde FileUri
podemos crear ExifInterface
basados en String path
, Pero de donde ContentUri
no podemos, Android no es compatible con eso.
En ese caso, tenemos que usar otro constructor basado en InputStream
. Recuerde que este constructor no está disponible de forma predeterminada, debe agregar una biblioteca adicional:
compile "com.android.support:exifinterface:XX.X.X"
Ahora podemos usar getExifInterface
método para obtener nuestro ángulo:
public float getExifAngle(Context context, Uri uri) {
try {
ExifInterface exifInterface = getExifInterface(context, uri);
if(exifInterface == null) {
return -1f;
}
int orientation = exifInterface.getAttributeInt(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;
}
}
Ahora tienes Angle para rotar correctamente tu imagen :).
Respondido el 04 de junio de 17 a las 15:06
implementación 'androidx.exifinterface:exifinterface:XXX' Esto es para aquellos que usan androidx. Gracias por tu publicación - Doongsil
12
// Try this way,hope this will help you to solve your problem...
actividad_principal.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:gravity="center">
<ImageView
android:id="@+id/imgFromCameraOrGallery"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:src="@drawable/ic_launcher"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:id="@+id/btnCamera"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:text="Camera"/>
<Button
android:id="@+id/btnGallery"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_marginLeft="5dp"
android:layout_height="wrap_content"
android:text="Gallery"/>
</LinearLayout>
</LinearLayout>
MainActivity.java
public class MainActivity extends Activity {
private ImageView imgFromCameraOrGallery;
private Button btnCamera;
private Button btnGallery;
private String 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 String getRightAngleImage(String photoPath) {
try {
ExifInterface ei = new ExifInterface(photoPath);
int orientation = ei.getAttributeInt(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 String rotateImage(int degree, String imagePath){
if(degree<=0){
return imagePath;
}
try{
Bitmap b= BitmapFactory.decodeFile(imagePath);
Matrix matrix = new Matrix();
if(b.getWidth()>b.getHeight()){
matrix.setRotate(degree);
b = Bitmap.createBitmap(b, 0, 0, b.getWidth(), b.getHeight(),
matrix, true);
}
FileOutputStream fOut = new FileOutputStream(imagePath);
String imageName = imagePath.substring(imagePath.lastIndexOf("/") + 1);
String imageType = imageName.substring(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 String imagePath){
new AsyncTask<Void,Void,String>(){
@Override
protected String doInBackground(Void... params) {
try {
return getRightAngleImage(imagePath);
}catch (Throwable e){
e.printStackTrace();
}
return imagePath;
}
@Override
protected void onPostExecute(String imagePath) {
super.onPostExecute(imagePath);
imgFromCameraOrGallery.setImageBitmap(decodeFile(imagePath));
}
}.execute();
}
public Bitmap decodeFile(String 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 String getAbsolutePath(Uri uri) {
if(Build.VERSION.SDK_INT >= 19){
String 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 String[] imageColumns = {MediaStore.Images.Media.DATA };
final String imageOrderBy = null;
Uri tempUri = getUri();
Cursor imageCursor = getContentResolver().query(tempUri, imageColumns, MediaStore.Images.Media._ID + "=" + id, null, imageOrderBy);
if (imageCursor.moveToFirst()) {
return imageCursor.getString(imageCursor.getColumnIndex(MediaStore.Images.Media.DATA));
}else{
return null;
}
}else{
return null;
}
}else{
String[] 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.getString(column_index);
} else
return null;
}
}
private Uri getUri() {
String 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;
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
File file = new File(Environment.getExternalStorageDirectory() + "/DCIM/",getString(R.string.app_name) + Calendar.getInstance().getTimeInMillis() + ".png");
imgUri = Uri.fromFile(file);
imgPath = file.getAbsolutePath();
}else {
File file = new File(getFilesDir() ,getString(R.string.app_name) + Calendar.getInstance().getTimeInMillis()+ ".png");
imgUri = Uri.fromFile(file);
this.imgPath = file.getAbsolutePath();
}
return imgUri;
}
public String getImagePath() {
return imgPath;
}
}
Respondido 17 Feb 15, 07:02
12
Simplemente puede leer la orientación del sensor de la cámara como lo indica Google en la documentación: https://developer.android.com/reference/android/hardware/camera2/CameraCharacteristics.html
SENSOR_ORIENTATION
Added in API level 21
Key<Integer> 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.
Código de muestra:
CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
int orientation = 0;
try {
String cameraId = manager.getCameraIdList()[0];
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
orientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
}
catch (Exception e)
{
}
Respondido el 10 de diciembre de 16 a las 11:12
esto debe marcarse como la respuesta. La rotación es el resultado de la orientación de la cámara, ¡así que esto es increíble! - genialcool1994
¿Cómo sabe qué cámara tomó la foto y si el teléfono todavía está en la misma orientación que cuando el usuario tomó la foto? - michele dorigatti
7
de jason robinson https://www.youtube.com/watch?v=xB-eutXNUMXJtA&feature=youtu.be y Sami Eltamawy https://www.youtube.com/watch?v=xB-eutXNUMXJtA&feature=youtu.be son excelentes
Solo una mejora para completar el enfoque, debe usar compat ExifInterface.
com.android.support:exifinterface:${lastLibVersion}
Podrá crear una instancia de ExifInterface (pior API <24) con InputStream
(Desde ContentResolver
) en lugar de rutas uri evitando "Excepciones de archivo no encontrado"
https://android-developers.googleblog.com/2016/12/introducing-the-exifinterface-support-library.html
Respondido el 26 de enero de 18 a las 10:01
4
Normalmente se recomienda resolver el problema con el Interfaz Exif, como sugirió @Jason Robinson. Si este enfoque no funciona, puede intentar buscar el Orientación de la última imagen tomada...
private int getImageOrientation(){
final String[] imageColumns = { MediaStore.Images.Media._ID, MediaStore.Images.ImageColumns.ORIENTATION };
final String 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;
}
}
Respondido el 02 de enero de 13 a las 15:01
Creo que este código solo detecta en qué grado se produjo la rotación. Ahora puedo hacer eso, pero no puedo en la siguiente tarea, es decir, rotar la imagen. - Shirish Herwade
Tienes razón, pero no preguntaste por la rotación en este hilo, así que vamos a mantenerlo limpio;) Es por eso que puse mi respuesta a tu problema de rotación en tu otro hilo... Espero que ayude, funciona para yo: stackoverflow.com/questions/14123809/… - Chris
MediaStore.Images.ImageColumns.ORIENTATION
disponible solo en Android 10 y versiones posteriores. - Ashutosh Sagar
4
Lamentablemente, la respuesta anterior de @jason-robinson no funcionó para mí.
Aunque la función de rotación funciona perfectamente:
public static Bitmap rotateImage(Bitmap source, float angle) {
Matrix matrix = new Matrix();
matrix.postRotate(angle);
return Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(), matrix,
true);
}
Tuve que hacer lo siguiente para obtener la orientación ya que la orientación Exif siempre fue 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();
String[] 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 );
Respondido el 22 de Septiembre de 16 a las 14:09
siempre 0, samsung 7 - djdance
4
Creé una función de extensión de Kotlin que simplifica la operación para los desarrolladores de Kotlin según la respuesta de @Jason Robinson. Espero que ayude.
fun Bitmap.fixRotation(uri: Uri): Bitmap? {
val ei = ExifInterface(uri.path)
val orientation: Int = ei.getAttributeInt(
ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_UNDEFINED
)
return when (orientation) {
ExifInterface.ORIENTATION_ROTATE_90 -> rotateImage( 90f)
ExifInterface.ORIENTATION_ROTATE_180 -> rotateImage( 180f)
ExifInterface.ORIENTATION_ROTATE_270 -> rotateImage( 270f)
ExifInterface.ORIENTATION_NORMAL -> this
else -> this
}
}
fun Bitmap.rotateImage(angle: Float): Bitmap? {
val matrix = Matrix()
matrix.postRotate(angle)
return Bitmap.createBitmap(
this, 0, 0, width, height,
matrix, true
)
}
Respondido el 02 de diciembre de 19 a las 18:12
4
Lo resolví usando un método diferente. Todo lo que tienes que hacer es comprobar si el ancho es mayor que la altura
Matrix rotationMatrix = new Matrix();
if(finalBitmap.getWidth() >= finalBitmap.getHeight()){
rotationMatrix.setRotate(-90);
}else{
rotationMatrix.setRotate(0);
}
Bitmap rotatedBitmap = Bitmap.createBitmap(finalBitmap,0,0,finalBitmap.getWidth(),finalBitmap.getHeight(),rotationMatrix,true);
Respondido 04 Jul 21, 06:07
En mi caso necesito: rotaciónMatrix.setRotate(90); - noor hossain
3
La respuesta seleccionada utiliza el método más común para responder a esta y otras preguntas similares. Sin embargo, no funciona con las cámaras delantera y trasera de Samsung. Para aquellos que buscan una solución que funcione tanto en la cámara frontal como en la trasera de Samsung y otros fabricantes importantes, esta respuesta de nvhausid es increíble:
https://stackoverflow.com/a/18915443/6080472
Para aquellos que no quieren hacer clic, la magia relevante es usar CameraInfo en lugar de confiar en 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);
Código completo en el enlace.
contestado el 23 de mayo de 17 a las 13:05
no, rotación incorrecta en diferentes ángulos (smasung s7). Me refiero a la galería, por supuesto. djdance
2
Si alguien experimenta problemas con ExifInterface
on Android 4.4 (KitKat) para obtener la orientación, podría deberse a un error camino obtenido de la URI. Ver una solución para propoer getPath
en la pregunta de desbordamiento de pila Obtenga una ruta real desde URI, el nuevo marco de acceso al almacenamiento de Android KitKat
contestado el 23 de mayo de 17 a las 11:05
Este comentario es lo que necesitaba. Amigo, muchas gracias. - joel nieman
2
Encuentre a continuación el enlace que esta solución es la mejor https://www.samieltamawy.com/how-to-fix-the-camera-intent-rotated-image-in-android/
Respondido el 26 de diciembre de 19 a las 05:12
2
aquí una solución que se basa en las anteriores pero solo necesita contexto y el archivo de imagen como entradas
public static Bitmap rectifyImage(Context context,File imageFile){
Bitmap originalBitmap= BitmapFactory.decodeFile(imageFile.getAbsolutePath());
try{
Uri uri=Uri.fromFile(imageFile);
InputStream input = context.getContentResolver().openInputStream(uri);
ExifInterface ei;
if (Build.VERSION.SDK_INT > 23)
ei = new ExifInterface(input);
else
ei = new ExifInterface(uri.getPath());
int orientation = ei.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_90:
return rotateImage(originalBitmap, 90);
case ExifInterface.ORIENTATION_ROTATE_180:
return rotateImage(originalBitmap, 180);
case ExifInterface.ORIENTATION_ROTATE_270:
return rotateImage(originalBitmap, 270);
default:
return originalBitmap;
}
}catch (Exception e){
return originalBitmap;
}
}
public static Bitmap rotateImage(Bitmap source, float angle) {
Matrix matrix = new Matrix();
matrix.postRotate(angle);
return Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(),
matrix, true);
}
Respondido 31 Jul 21, 05:07
1
Mejor trata de tomar la foto en una orientación específica.
android:screenOrientation="landscape"
android:configChanges="orientation|keyboardHidden"
Para obtener los mejores resultados, brinde orientación horizontal en la actividad de vista de cámara.
Respondido el 10 de diciembre de 16 a las 11:12
lo siento, no funciona. De hecho, en la pestaña, cada vez que finaliza la ejecución de onActivityResult, extrañamente se llama a onCreate. - Shirish Herwade
lo siento, el problema es como es - Shirish Herwade
1
Esto puede ser evidente, pero recuerde siempre que puede manejar algunos de estos problemas de manejo de imágenes en su servidor. Usé respuestas como las contenidas en este hilo para manejar la visualización inmediata de la imagen. Sin embargo, mi aplicación requiere que las imágenes se almacenen en el servidor (este es probablemente un requisito común si desea que la imagen persista cuando los usuarios cambian de teléfono).
Las soluciones contenidas en muchos de los hilos relacionados con este tema no abordan la falta de persistencia de los datos EXIF que no sobreviven a la compresión de imágenes del mapa de bits, lo que significa que deberá rotar la imagen cada vez que su servidor la cargue. Alternativamente, puede enviar los datos de orientación EXIF a su servidor y luego rotar la imagen allí si es necesario.
Fue más fácil para mí crear una solución permanente en un servidor porque no tenía que preocuparme por las rutas de archivos clandestinas de Android.
Respondido 27 Abr '17, 23:04
¿Puedes girarlo una vez en el momento de la captura de la imagen y guardarlo de esa manera para que nunca más necesite girarse? - jk7
Sí, puedes y ese es en realidad el proceso que terminé implementando al final. Estaba teniendo problemas para obtener la ruta del archivo de la imagen en el teléfono Android que me permitiría hacer eso. Esta es la respuesta que ayudó: stackoverflow.com/a/36714242/5443056 - braden holt
Miles de aplicaciones que pueden rotar imágenes en un teléfono, rotarlas en el servidor en su lugar. Cada situación es diferente, pero huiría de una solución que haga funcionar su servidor. Siempre desea externalizar la informática a los teléfonos de los clientes cuando sea posible. - Vaidas
1
La solución más simple para este problema:
captureBuilder.set(CaptureRequest.JPEG_ORIENTATION,
characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION));
Estoy guardando la imagen en formato jpg.
Respondido 19 Oct 17, 03:10
Que es captureBuilder
? - rmirabelle
1
El siguiente código funcionó conmigo, obtuvo el mapa de bits del fileUri y corrigió la rotación si es necesario:
private fun getCapturedImage(selectedPhotoUri: Uri): Bitmap {
val bitmap = when {
Build.VERSION.SDK_INT < 28 -> MediaStore.Images.Media.getBitmap(
this.contentResolver,
selectedPhotoUri
)
else -> {
val source = ImageDecoder.createSource(this.contentResolver, selectedPhotoUri)
ImageDecoder.decodeBitmap(source)
}
}
// If the image is rotated, fix it
return when (ExifInterface(contentResolver.run { openInputStream(selectedPhotoUri) }).getAttributeInt(
ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED)) {
ExifInterface.ORIENTATION_ROTATE_90 ->
Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, Matrix().apply {
postRotate(90F) }, true)
ExifInterface.ORIENTATION_ROTATE_180 ->
Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, Matrix().apply {
postRotate(180F) }, true)
ExifInterface.ORIENTATION_ROTATE_270 ->
Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, Matrix().apply {
postRotate(270F) }, true)
else -> bitmap
}
}
Respondido el 24 de Septiembre de 19 a las 05:09
0
Esta es Xamarin.Android
Versión:
De @Jason Robinson's https://www.youtube.com/watch?v=xB-eutXNUMXJtA&feature=youtu.be:
Bitmap rotate(Bitmap bitmap, int angle)
{
var matrix = new Matrix();
matrix.PostRotate(angle);
return Bitmap.CreateBitmap(bitmap, 0, 0, bitmap.Width, bitmap.Height, matrix, true);
}
Bitmap rotateIfRequired(Bitmap bitmap, string imagePath)
{
var ei = new ExifInterface(imagePath);
var orientation = ei.GetAttributeInt(ExifInterface.TagOrientation, (int)Android.Media.Orientation.Undefined);
switch (orientation)
{
case (int)Android.Media.Orientation.Rotate90: return rotate(bitmap, 90);
case (int)Android.Media.Orientation.Rotate180: return rotate(bitmap, 180);
case (int)Android.Media.Orientation.Rotate270: return rotate(bitmap, 270);
default: return bitmap;
}
}
Entonces calculateInSampleSize
método:
int calculateInSampleSize(BitmapFactory.Options options, int reqW, int reqH)
{
float h = options.OutHeight;
float w = options.OutWidth;
var inSampleSize = 1;
if (h > reqH || w > reqW)
{
if (reqH == 0) inSampleSize = (int)Math.Floor(w / reqW);
else if (reqW == 0) inSampleSize = (int)Math.Floor(h / reqH);
else
{
var hRatio = (int)Math.Floor(h / reqH);
var wRatio = (int)Math.Floor(w / reqW);
inSampleSize = false ? Math.Max(hRatio, wRatio) : Math.Min(hRatio, wRatio);
}
}
return inSampleSize;
}
De @Sami Eltamawy's https://www.youtube.com/watch?v=xB-eutXNUMXJtA&feature=youtu.be:
Bitmap handleSamplingAndRotationBitmap(string imagePath)
{
var maxHeight = 1024;
var maxWidth = 1024;
var options = new BitmapFactory.Options();
options.InJustDecodeBounds = true;
BitmapFactory.DecodeFile(imagePath, options);
options.InSampleSize = calculateInSampleSize(options, maxWidth, maxHeight);
options.InJustDecodeBounds = false;
var bitmap = BitmapFactory.DecodeFile(imagePath, options);
bitmap = rotateIfRequired(bitmap, imagePath);
return bitmap;
}
contestado el 01 de mayo de 19 a las 13:05
Hola, tengo el problema de rotación en mi xamarin. aplicación Android. El problema es que cuando se usa la cámara trasera, la imagen se guarda en 90 grados a la derecha. Pero al usar la cámara frontal se guarda en 90 grados a la izquierda. Entonces, la rotación se resuelve usando este código que funciona solo en la cámara frontal. ¿Te enfrentaste al problema? - Anand
Hola, creo que es porque la cámara frontal está volteada por defecto. si apaga eso, ¿el resultado de este código para ambas cámaras es igual? - Mehdi Deghani
hola me pueden ayudar en esa parte He hecho una pregunta aquí. Pero aún en la oscuridad. stackoverflow.com/questions/64278491/… - Anand
0
Si está usando Fresco, puede usar esto:
final ImageRequest imageRequest = ImageRequestBuilder.newBuilderWithSource(uri)
.setRotationOptions(RotationOptions.autoRotate())
.build();
mSimpleDraweeView.setController(
Fresco.newDraweeControllerBuilder()
.setImageRequest(imageRequest)
.build());
Esto gira automáticamente las imágenes en función de los datos Exif.
Respondido el 16 de Septiembre de 19 a las 15:09
0
Obtuve una respuesta para este problema sin usar Interfaz Exif. Podemos obtener la rotación de la cámara, ya sea la cámara frontal o la cámara trasera, cualquiera que esté usando, mientras creamos el mapa de bits podemos rotar el mapa de bits usando Matrix.postRotate(grado)
public int getRotationDegree() {
int degree = 0;
for (int i = 0; i < Camera.getNumberOfCameras(); i++) {
Camera.CameraInfo info = new Camera.CameraInfo();
Camera.getCameraInfo(i, info);
if (info.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
degree = info.orientation;
return degree;
}
}
return degree;
}
Después de calcular la rotación, puede rotar su mapa de bits como se muestra a continuación:
Matrix matrix = new Matrix();
matrix.postRotate(getRotationDegree());
Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true);
Herare bm debe ser su mapa de bits.
Si quieres saber la rotación de tu cámara frontal solo cambia Camera.CameraInfo.CAMERA_FACING_BACK a Camera.CameraInfo.CAMERA_FACING_FRONT anterior.
Espero que esto ayude.
Respondido 03 Oct 19, 10:10
Respuesta horrible, pero accidentalmente voté a favor. Este código asume que cada imagen de tu galería está hecha con a tu cámara. Este no es el caso - Estabas
@Zun La pregunta que se hace es para capturar imágenes y no para seleccionar imágenes de la galería. - Om Prakash Agrahari
0
El uso de Biblioteca de deslizamiento trabajó para mi. La rotación se realiza automáticamente.
Bitmap bitmap = Glide.with(myContext).asBitmap().load(imageFilePath).submit(SIZE_ORIGINAL, SIZE_ORIGINAL).get();
Luego, guarda ese mapa de bits en un archivo en formato JPEG, por ejemplo.
Si sólo desea cargar en un ImageView
en lugar de guardar en un archivo:
Glide.with(myContext).load(imageFilePath).into(myImageView)
Respondido 05 Feb 21, 08:02
0
al usar Glide lib puede obtener una imagen con la orientación exacta sin necesidad de verificar la rotación
en kotlin
CoroutineScope(Dispatchers.IO).launch {
var bitmap = Glide.with(context).asBitmap().load(imagePathOrUriOrLink)
/*.apply(
RequestOptions()
.override(MAXIMUM_IMAGE_RESOLUTION)
)*/ //uncomment it if you want original image
/*.diskCacheStrategy(DiskCacheStrategy.NONE).skipMemoryCache(true)*/ //uncomment it you want to not cache image
.submit().get()//this is synchronous approach
}
usando esta dependencia
api 'com.github.bumptech.glide:glide:4.12.0'
kapt 'com.github.bumptech.glide:compiler:4.12.0'
Respondido el 18 de junio de 21 a las 06:06
-2
Hay un comando más simple para corregir este error.
Simplemente agregue después de yourImageView.setBitmap(bitmap); este yourImageView.setRotation(90);
Esta arregló la mía. Espero eso ayude !
Respondido 01 ago 17, 17:08
Como indicó el OP, algunos dispositivos no giran la imagen, algunos la giran 90 grados, algunos 180, etc. Entonces, siempre girarlo 90 sería incorrecto en algunos casos. - jk7
No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas android image camera rotation android-camera-intent or haz tu propia pregunta.
prueba esto en tu actividad menifest android:configChanges="orientation" android:screenOrientation="retrato" - Narendra Pal
como creo que cuando usa la intención interna para tratar con la aplicación de la cámara, entonces gira la imagen. Esto depende de cómo sostenga el dispositivo para capturar la imagen. Por lo tanto, puede restringir al usuario para que tome una imagen de una manera particular, lo que significa que el usuario siempre capturará la imagen sosteniendo el dispositivo en posición vertical u horizontal. Después de eso, puede cambiarlo a un ángulo específico para obtener la imagen que desee. U OTRA OPCIÓN, HAGA SU PROPIA APLICACIÓN DE CÁMARA. - Narendra Pal
Creo que la intención de captura siempre muestra la aplicación de cámara predeterminada que tiene una orientación específica en cada dispositivo y, en consecuencia, una orientación fija de la foto. No depende de la forma en que el usuario sostenga el dispositivo o la orientación de su actividad que invocó la intención. - Alex Cohn
Para evitar el permiso de almacenamiento, consulte este or este responder o usar deslizamiento - Pavel
Alguien encontró alguna solución para ORIENTATION_UNDEFINED, ya que en algunos dispositivos (Emulador de Android 8) la imagen se gira mientras que en algunos dispositivos (Emulador de Android 9) no tiene el mismo valor de Orientación. ¿Cómo saber si la imagen necesita ser rotada o no? - Harshit Saxena