То, почему делает изображение, захваченное, используя намерение камеры, вращается на некоторых устройствах на Android?

Я захватываю изображение и устанавливаю его в представление изображения.

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;
    }
}

Но проблема, изображение на некоторых устройствах каждый раз, когда это вращается. Например, на устройстве Samsung это работает хорошее, но на a Sony Xperia изображение вращается 90 градусами и на Toshiba Thrive (таблетка) 180 градусами.

250
как я думаю, когда вы используете внутреннее намерение для контакта с приложением для камеры, тогда это вращает изображение. Это, зависит от того, как вы держите устройство, чтобы захватить изображение. Таким образом, можно ограничить пользователя, чтобы взять изображение в особенности, способ означает, что пользователь будет всегда захватывать изображение, держа устройство в портрете или пейзаже. После этого можно изменить его на определенный угол, чтобы получить изображение, как вы хотите.. ИЛИ ДРУГОЙ ВЫБОР, СДЕЛАЙТЕ СВОЙ СОБСТВЕННЫЙ APP КАМЕРЫ.
добавлено автор Narendra Pal, источник
попробуйте это в вас деятельность menifest android:configChanges = "ориентация" android:screenOrientation = "портрет"
добавлено автор Narendra Pal, источник
@nick это doesn' t работа, теперь изображение вращается до 90 градусов, а не 180 градусов на счете
добавлено автор S H, источник
@nick "можно ли ограничить пользователя, чтобы взять изображение в особенности, способ" означает, он то же самое как урегулирование ориентации = "potrait"? И как к "После этого можно изменить его на определенный угол, чтобы получить изображение, как вы хотите", достигают? Пожалуйста, можете вы давать некоторые полезные ссылки
добавлено автор S H, источник
Я полагаю, что намерение захвата всегда поднимает приложение для камеры по умолчанию, у которого есть определенная ориентация на каждом устройстве и следовательно - зафиксированная фото ориентация. Это не зависит от способа, которым пользователь держит устройство или ориентацию вашей деятельности, которая призвала намерение.
добавлено автор Alex Cohn, источник

17 ответы

Большинство телефонных камер - пейзаж, означая, делаете ли вы фотографию в портрете, получающиеся фотографии будут вращаться 90 градусов. В этом случае программное обеспечение камеры должно населить Exif данные с ориентацией, в которой должна быть рассмотрена фотография.

Обратите внимание, что ниже решения зависит от программного обеспечения/производителя устройств камеры, населяющего данные Exif, таким образом, это будет работать в большинстве случаев, но это не 100%-е надежное решение.

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;
}

Вот rotateImage метод:

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);
}
327
добавлено
@user1744228 вы проходите в своем исходном растровом изображении в том методе.
добавлено автор Jason Robinson, источник
@FatihOzcan Это должна быть та же самая скорость независимо от фото размера потому что it' s, только читая заголовки Exif. It' s, не читая пиксельные данные. Если у вас есть Битовый массив, который вы вручную захватили, то не было бы никаких данных Exif, связанных с ним так или иначе.
добавлено автор Jason Robinson, источник
@FatihOzcan похож , ExitInterface поддерживает Файл и InputStream, таким образом, вы могли создайте InputStream.
добавлено автор Jason Robinson, источник
Второй вариант exif.getAttributeInt использующий ExifInterface. ORIENTATION_UNDEFINED является почти тем же самым, как второй параметр - значение по умолчанию в случае, если функция не предоставляет стоимость.
добавлено автор Darpan, источник
Этот код для изображения, уже написанный диску, правильно? Я не получаю результатов, используя этот метод для битового массива, собирающегося быть написанным диску.
добавлено автор Thracian, источник
@Jason Робинсон, этот код очень полезен для получения изображения от диска и вращения его соответственно, но когда вы делаете hardwork как, я делаю, я получаю 4k изображение от камеры и сливаю его с холстом, тянущим после вычисления рисунка от предварительного просмотра камеры до 4k, и сохраняю его на диск. Открытие потока снова не эффективно, вращение битового массива с поствращает() метод matix прежде, чем сохранить образ, достаточный для меня. В моем случае пользователь должен выбрать вращение вручную
добавлено автор Thracian, источник
@Jason Робинсон, это должна быть та же самая скорость, но открытие потока после экономии битового массива как png или jpeg является дополнительной работой. Да, точно что я спрашивал первое место, не сохраняя образ вы don' у t есть exif информация. Я должен был вращать изображение прежде, чем спасти ему диск, потому что у некоторых моделей как Nexus 5x есть перевернутая ориентация. Спасибо за ответы.
добавлено автор Thracian, источник
От @JasonRobinson code' s я изучаю, как получить фактическую ориентацию и объединившись с они кодируют I' m успешно справляются с ориентацией.
добавлено автор Raditya Kurnianto, источник
битовый массив - интервал, но rotateImage берет Битовый массив. Что я должен сделать?
добавлено автор user1744228, источник
это работает как очарование над моим s3 (kitkat), отмечают 3 (леденец на палочке) nexus 5 (зефир), но не на моем s6edge (нуга), кто-то может сказать мне почему?
добавлено автор ismail alaoui, источник

By combining Jason Robinson's answer with Felix's answer and filling the missing parts, here is the final complete solution for this issue that will do the following after testing it on Android Android 4.1 (Jelly Bean), Android 4.4 (KitKat) and Android 5.0 (Lollipop).

Шаги

  1. Постепенное уменьшение изображение, если это было больше, чем 1024x1024.

  2. Вращает изображение к правильной ориентации только , если это было, вращаются 90, 180 или 270 степеней.

  3. Перерабатывает вращаемое изображение в целях памяти.

Вот кодовая часть:

Назовите следующий метод с током Контекст и изображение URI , что вы хотите зафиксировать

/**
 * 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;
}

Вот 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
  */
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;
}

Тогда прибывает метод, который проверит ориентацию текущего изображения, чтобы решить угол вращения

 /**
 * 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;
    }
}

Наконец сам метод вращения

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;
}

- Не забывайте признавать за те ответы парней для их усилий и Shirish Herwade , кто задал этот полезный вопрос.

118
добавлено
Его Уокинг для меня Отлично. Спасибо
добавлено автор Shohel Rana, источник

Легко обнаружить ориентацию изображения и заменить растровое использование:

 /**
 * 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;
}

Чтобы избежать Из воспоминаний с большими изображениями, я рекомендовал бы вам повторно измерить использование изображения:

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;
}

It's not posible to use ExifInterface to get the orientation because an Android OS issue: https://code.google.com/p/android/issues/detail?id=19268

And here is 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;
}
35
добавлено
Параметр ' selectedImage' doesn' t, кажется, используются где угодно. Какая-либо причина быть там?
добавлено автор Alex, источник
rotateImageIfRequired (img, selectedImage); вы передаете два параметра, тогда как в вашем определении метода вы определили три частный статический Битовый массив rotateImageIfRequired (Контекст контекста, Битовый массив img, Ури selectedImage) , В чем я прохожу как контекст от моей деятельности?
добавлено автор Romantic Electron, источник
Параметр Uri selectedImage, не используемый в getRotation (...) метод. Как мы должны использовать его?Thank you.
добавлено автор anivaler, источник
Боровшийся некоторое время с методом вращения с тех пор на некотором устройстве, прикрепляя фотографию в режиме портрета простое вращение делает изображение протянутым. Найденное решение было: кодовая матрица Матрицы = новая Матрица (); matrix.postTranslate (-ширина / 2, - высота / 2); matrix.postRotate (угол); matrix.postTranslate (ширина / 2, высота / 2);
добавлено автор fox, источник
@madhukotagiri здесь у вас есть пример implementantion для calculateInSampleSize: gist.github.com/anonymous/b7ea25fc2bbc54e43616
добавлено автор Felix, источник
Человек спасибо, you' ре определенно то! I' m просто задающийся вопросом, насколько изменение размеров будет полезно, если операция будет выполняться просто иногда.
добавлено автор marino, источник
что такое calculateInSampleSize метод здесь
добавлено автор madhu kotagiri, источник

Одно решение для линии:

Picasso.with(context).load("http://i.imgur.com/DvpvklR.png").into(imageView);

Или

Picasso.with(context).load("file:" + photoPath).into(imageView);

Это опознает автоматически вращение и поместит изображение в правильную ориентацию

Picasso is a very powerful library fИли handling images in your app includes: Complex image transformations with minimal memory use.

16
добавлено
Это просто загружает изображение в представление, это doesn' t дают вам битовый массив или файл, которым можно управлять или загрузить на сервер.
добавлено автор Mickaël A., источник
Интересное решение
добавлено автор Bhavik Mehta, источник
Его изображение показа щелкнуло как есть, Это не вращается как требуется.
добавлено автор seema, источник
@Flawyte можно сделать это, загрузив файл в цель вместо представления с отзывом, который прибыль подрезала/изменила размеры битовый массив: Picasso.with (этот) .load (cropUriToLoad.resize (1080, 810) .centerInside() .into (цель); где цель = новая Цель() {Отвергает общественную пустоту onBitmapLoaded (Растровый битовый массив, Пикассо. LoadedFrom от) {
добавлено автор voytez, источник
// Try this way,hope this will help you to solve your problem...

activity_main.xml



    
        
    

    
        <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"/>

    

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(){
            @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;
    }
}
10
добавлено

You can just read the orientation of the camera sensor like indicated by Google in the 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.

Пример кода:

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)
{
}
5
добавлено
Этот работал на меня.Thank you!
добавлено автор Zack Kaytranada, источник

Обычно рекомендуется решить проблему с ExifInterface, как @Jason Робинсон действительно предлагал. Если этот подход не работает, вы могли бы попытаться искать Ориентация из последнего взятого изображения...

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;
    }
}
4
добавлено
Я думаю, что этот код только обнаруживает в том, какое вращение степени произошло. Теперь I' m способный сделать это, но неспособный в следующей задаче т.е. вращать изображение.
добавлено автор S H, источник
You' право ре, но вы didn' t просят вращение в этой Нити, таким образом, let' s содержат его в чистоте;) That' s, почему я поместил свой ответ на вашу проблему вращения в вашу другую Нить... Надежда, которая помогает, это действительно работает на меня: stackoverflow.com/questions/14123809/…
добавлено автор Chris Conway, источник

Я провел много времени, ища решение для этого. И наконец управляемый, чтобы сделать это. Не забывайте к upvote @Jason ответ Робинсона, потому что мой на основе его.

Таким образом, первая вещь, вы, sholuld знают, что начиная с Android 7.0 мы должны использовать <кодируете> FileProvider , и что-то названное ContentUri , иначе вы получите раздражающую ошибку при попытке призвать ваш Намерение . Это - пример кода:

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);

Метод getUriFromPath (Контекст, Последовательность) основание на пользовательской версии Android создает FileUri (file://...) или ContentUri (content://...) , и там это:

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);
    }
}

После onActivityResult можно поймать тот uri , где образ сохраняется камерой, но теперь необходимо обнаружить вращение камеры, здесь мы будем использовать moddified @Jason ответ Робинсона:

First we need to create ExifInterface based on 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;
}

Выше кода может быть упрощен, но я хочу показать все. Таким образом из FileUri , который мы можем создать ExifInterface на основе путь Последовательности , но из ContentUri мы не можем, Android не поддержать это.

В этом случае мы должны использовать другого конструктора на основе InputStream . Помните, что этот конструктор не доступен по умолчанию, необходимо добавить дополнительную библиотеку:

compile "com.android.support:exifinterface:XX.X.X"

Теперь мы можем использовать getExifInterface метод, чтобы получить наш угол:

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;
    }
}

Теперь у вас есть Энгл, чтобы правильно вращать вас изображение:).

4
добавлено

К сожалению, @jason-robinson ответ выше не работал на меня.

Хотя вращать функция работает отлично:

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);
}

Я должен был сделать следующее, чтобы получить ориентацию, как ориентация Exif всегда была 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 );
3
добавлено
alwasys 0, Samsung 7
добавлено автор djdance, источник

If somebody experiences problems with ExifInterface on Android 4.4 (KitKat) for getting the orientation, it might be because of wrong path got from the URI. See a solution for propoer getPath in Stack Overflow question Get real path from URI, Android KitKat new storage access framework

2
добавлено
Этот комментарий - то, в чем я нуждался. Чувак, огромное спасибо.
добавлено автор Joel Nieman, источник

Лучше попытайтесь сделать снимок в определенной ориентации.

android:screenOrientation="landscape"
android:configChanges="orientation|keyboardHidden"

Поскольку лучшие результаты дают альбомную ориентацию в cameraview деятельности.

1
добавлено
жаль, проблема состоит в том, как это
добавлено автор S H, источник
жаль, это doesn' t работа. На самом деле на счете, каждый раз после заканчивающегося выполнения onActivityResult, странно onCreate называют.
добавлено автор S H, источник

Это, возможно, само собой разумеется, но всегда помните, что можно обращаться с некоторыми из этих проблем обработки изображения о сервере. Я использовал ответы как те содержавшиеся в этой нити, чтобы обращаться с непосредственным показом изображения. Однако, мое заявление требует, чтобы изображения были сохранены на сервере (это - вероятно, общее требование, если вы хотите, чтобы изображение сохранилось, поскольку пользователи переключают телефоны).

Решения, содержавшиеся во многих нитях относительно этой темы, не обсуждают отсутствие постоянства данных EXIF, которые не переживают сжатие изображения Битового массива, означая, что необходимо будет вращать изображение каждый раз, когда сервер загружает его. Альтернативно, можно послать данные об ориентации EXIF в сервер, и затем вращать изображение там в случае необходимости.

Для меня было легче создать постоянное решение на сервере, потому что я не должен был волноваться о тайных путях к файлам Android.

1
добавлено
Да вы можете и that' s на самом деле процесс я закончил тем, что осуществил в конце. Я испытывал затруднения при получении пути к файлу от изображения на телефоне на базе Android, который позволит мне делать это. Это - ответ, который помог: stackoverflow.com/a/36714242/5443056
добавлено автор Braden Holt, источник
Можно ли вращать его однажды во время захвата изображения и спасти ли ему тот путь, таким образом, это никогда не должно вращаться снова?
добавлено автор jk7, источник

Джейсон Робинсон ответ и Сами Элтамави ответ превосходны.

Просто улучшение, чтобы закончить подход, необходимо использовать compat ExifInterface.

com.android.support:exifinterface: $ {lastLibVersion}

You will be able to instantiate the ExifInterface(pior API <24) with InputStream (from ContentResolver) instead of uri paths avoiding "File not found exceptions"

https://android-developers.googleblog.com/2016/12/introducing-the-exifinterface-support-library.html

1
добавлено

Отобранный ответ использует наиболее распространенный метод, которому отвечают на это и подобные вопросы. Однако это не работает с обеими камерами передней и задней части на Samsung. Для тех, которые ищут решение, которое работает и через камеры передней и задней части на Samsung и через других крупнейших производителей, этот ответ nvhausid потрясающий:

https://stackoverflow.com/a/18915443/6080472

Для тех, кто не хочет щелкать через, соответствующее волшебство состоит в том, чтобы использовать CameraInfo, скорее тогда полагающийся на 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);

Полный код в связи.

1
добавлено
нет, неправильное вращение в различных углах (smasung s7). Я имею в виду галерею, конечно,
добавлено автор djdance, источник

Есть более простая команда, чтобы зафиксировать эту ошибку.

Просто добавьте после yourImageView.setBitmap (битовый массив); этот yourImageView.setRotation (90);

Эта фиксированная шахта. Надежда это помогает!

1
добавлено
Как указанный OP, некоторые устройства don' t вращают изображение, некоторые вращают его 90 градусов, приблизительно 180.. и т.д. Таким образом, всегда вращение его 90 было бы неправильным в некоторых случаях.
добавлено автор jk7, источник

Попробуйте следующее, если вы, стоят перед проблемой с S4.

android:configChanges="locale|touchscreen|orientation|screenLayout|screenSize|keyboardHidden|uiMode"
0
добавлено
делая фотографию прикладные намерения к камере. вы не можете управлять камерой, добавляя признак в Декларации.
добавлено автор milad zahedi, источник
Спасибо. это решает мою проблему
добавлено автор ayesh don, источник

Простое решение для этой проблемы:

captureBuilder.set(CaptureRequest.JPEG_ORIENTATION,
                   characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION));

Я сохраняю образ в формате jpg.

0
добавлено
Mobile Dev Jobs — вакансии и аналитика
Mobile Dev Jobs — вакансии и аналитика
6 187 участник(ов)

Публикуем вакансии и запросы на поиск работы по направлению iOS, Android, Xamarin и т.д. ВАЖНО: Правила публикации и правила канала: Ссылка – https://telegra.ph/Pravila-oformleniya-vakansij-i-rezyume-11-09-2

Android Developers
Android Developers
4 476 участник(ов)

Общаемся на темы, посвященным Android-разработке, SDK, Kotlin, Realm и т.д.

Верстка сайтов HTML/CSS/JS/PHP
Верстка сайтов HTML/CSS/JS/PHP
3 439 участник(ов)

Правила группы: напишите !rules в чате. Группа Вк: vk.com/web_structure Freelancer: @web_fl Веб Дизайн: @dev_design Маркетолог: @topmarkening Автор: @M_Boroda

Android Architecture
Android Architecture
2 186 участник(ов)

Русскоязычный чат по архитектуре в андроид приложениях. Подробнее: http://telegra.ph/Android-Architecture-12-24

rus-speaking/android
rus-speaking/android
1 705 участник(ов)

Основной чат по Android разработке (вопрос-ответ). ПРАВИЛА: bit.ly/andr-rules. NEWS: bit.ly/AnrdResId ЧАТЫ: Основной: bit.ly/andr-main IDE, сборка, Git, сервисы: bit.ly/andr-tools Оффтоп: bit.ly/andr-offtop Конференции, события: bit.ly/andr-events Вакансии, найм: bit.ly/andr-job Архитектура: bit.ly/andr-patterns Rx: bit.ly/andr-rx Тестирование: bit.ly/andr-test Kotlin: bit.ly/andr-kotlin Хаmarin: bit.ly/andr-xamarin За мат, спам, агрессию, предложения о работе, оффтоп в этом канале - бан на сутки и более ☢☢☢

CSS — русскоговорящее сообщество
CSS — русскоговорящее сообщество
1 502 участник(ов)

Сообщество любителей CSS Возникли проблемы с CSS? – пиши сюда, обсудим и предложим самое лучшее решение Работа: @css_ru_jobs Правила: https://teletype.in/@css_ru/r1EWtQ2w7 Приходите в наши чаты @javascript_ru и @frontend_ru Флуд: @css_flood

Android Dev Подкаст
Android Dev Подкаст
1 325 участник(ов)

Комната для обсуждения Android Dev подкаста apptractor.ru/AndroidDev/ Общее обсуждение Android: https://t.me/android_ru Остальные чаты про Android: http://t.me/devChats Наши новости https://t.me/androiddevpodcast_news

Чат — Типичный Верстальщик
Чат — Типичный Верстальщик
1 080 участник(ов)

Основной канал: @tpverstak Обратная связь: @annblok Все ссылки на соц.сети проекта: http://taplink.cc/tpverstak ПРАВИЛА ЧАТА — https://teletype.in/@annblok/BygPgC3E7

Android Guards
Android Guards
602 участник(ов)

Обсуждение любых вопросов касающихся безопасности Android. - Защита системы и приложений - Уязвимости и эксплойты - Вредоносное ПО - Копание в кишках системы и приложений (RE)

Android JOB
Android JOB
466 участник(ов)

Публикуем вакансии и запросы на поиск работы по направлению Android (full-time, part-time, remote и разовые подработки)

AndroidDev :: Разработка. It's Android time now!
AndroidDev :: Разработка. It's Android time now!
458 участник(ов)

It's Android time now! Чат разработчиков Android. Вакансии, резюме и информацию о митапах размещать можно. Публикацию скрытой и явной рекламы ваших каналов и сайтов после получения разрешения от @olegushakov

Aandroid Talks!
Aandroid Talks!
212 участник(ов)

Чат об общих вопросах по ОС Android. Чат для разработки под андроид - pro.android: https://t.me/joinchat/AAAAAEKIFKnmRT9cMebb9w

Веб-Технологи: UI/UX, Вёрстка, Фронтенд
Веб-Технологи: UI/UX, Вёрстка, Фронтенд
167 участник(ов)

Всё про веб-дизайн и вёрстку. А также: HTML, CSS, флекс и бутстрапы, шаблонизаторы, препроцессоры, методологии, аглифаеры, улучшаторы и обфускаторы. Обсуждаем темы юзабилити, устраиваем А/В тесты лендингов, и проводим аудит.

DTP :: @DTPublish
DTP :: @DTPublish
147 участник(ов)

Обсуждаемые темы: полиграфия, препресс, верстка, дизайн, иллюстрации, скрипты, плагины. Канал - @DTPublishing

Android Rus
Android Rus
68 участник(ов)

css_jobs
css_jobs
26 участник(ов)

Чат для вопросов по css и html: @css_ru Флуд: @css_flood Канал с вакансиями и резюме: @css_jobs_feed

css_флуд
css_флуд
10 участник(ов)