简体   繁体   English

从图库Orientation中选择的Android图像始终为0:Exif TAG

[英]Android image selected from gallery Orientation is always 0 : Exif TAG

When I pick an image from gallery to set it on my imageview in android application then I see that it comes inverted by 180 or 270 or 90 degress . 当我从图库中选择一个图像以在Android应用程序中的我的imageview上设置它时,我发现它被反转180或270或90度
So to check/solve this I used EXIF orientations, but it always gives me "0". 所以为了检查/解决这个问题,我使用了EXIF方向,但总是给我“0”。

I am not able to get what is the problem. 我无法得到什么问题。

code: 码:

Uri selectedImageUri = data.getData();

                    absolutePath = selectedImageUri.getPath();

                    exifMedia = new ExifInterface(absolutePath);
                    String exifOrint = exifMedia.getAttribute(ExifInterface.TAG_ORIENTATION);

                    exifOrientation = Integer.parseInt(exifOrint);

                    System.out.println("Orientation Tag is:"+exifOrientation);

                    /** Convert URI into byte */
                    ContentResolver cr = getBaseContext()
                    .getContentResolver();
                    InputStream inputStream = cr
                    .openInputStream(selectedImageUri);
                    Bitmap bitmap = BitmapFactory.decodeStream(inputStream);

                    rotatedBMP = getResizedBitmapImage(
                            bitmap, 100, 100,exifOrientation);

                    ByteArrayOutputStream stream = new ByteArrayOutputStream();
                    rotatedBMP.compress(Bitmap.CompressFormat.PNG, 100,
                            stream);
                    byteArray = stream.toByteArray();
                    mimProfileImageBrowse.setImageBitmap(rotatedBMP);

method: 方法:

public  Bitmap getResizedBitmapImage(Bitmap bm, int newHeight, int newWidth, int exifOrientation) {
        int width = bm.getWidth();
        int height = bm.getHeight();
        float scaleWidth = ((float) newWidth) / width;
        float scaleHeight = ((float) newHeight) / height;
        /**
         *  create a matrix for the manipulation
         */

        Matrix matrix = new Matrix();
        /**
         *  resize the bit map
         */


        /*

         1 = Horizontal (normal) 
2 = Mirror horizontal 
3 = Rotate 180 
4 = Mirror vertical 
5 = Mirror horizontal and rotate 270 CW 
6 = Rotate 90 CW 
7 = Mirror horizontal and rotate 90 CW 
8 = Rotate 270 CW

         */


        switch (exifOrientation) {
        case ExifInterface.ORIENTATION_ROTATE_270:

            rotate = 270;

            break;


        case ExifInterface.ORIENTATION_ROTATE_180:

            rotate = 180;


            break;

        case ExifInterface.ORIENTATION_ROTATE_90:

            rotate = 90;

            break;

        case ExifInterface.ORIENTATION_TRANSPOSE:

            rotate = 45;

            break;

        default:
            break;
        }


        matrix.postScale(scaleWidth, scaleHeight);
        matrix.postRotate(rotate);

        /**
         * recreate the new Bitmap
         */
        Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, false);
        resizedBitmap = Bitmap.createScaledBitmap(bm, 65, 65, true);

        return resizedBitmap;

    }

Please help. 请帮忙。 Also matrix.postROTATE is not rotating the bitmaps. matrix.postROTATE也不会旋转位图。 I dont know why. 我不知道为什么。

Thanks 谢谢

After you get Uri of selected Image call the below functions using this methods, 获得所选图像的Uri后,使用此方法调用以下函数,
Like this, 像这样,

Uri selectedImageUri = data.getData();
Bitmap bitmap = scaleImage(this,selectedImageUri);

The two functions to include in your activity are, 要在您的活动中包含的两个功能是,

 public static Bitmap scaleImage(Context context, Uri photoUri) throws IOException {
        InputStream is = context.getContentResolver().openInputStream(photoUri);
        BitmapFactory.Options dbo = new BitmapFactory.Options();
        dbo.inJustDecodeBounds = true;
        BitmapFactory.decodeStream(is, null, dbo);
        is.close();

        int rotatedWidth, rotatedHeight;
        int orientation = getOrientation(context, photoUri);

        if (orientation == 90 || orientation == 270) {
            rotatedWidth = dbo.outHeight;
            rotatedHeight = dbo.outWidth;
        } else {
            rotatedWidth = dbo.outWidth;
            rotatedHeight = dbo.outHeight;
        }

        Bitmap srcBitmap;
        is = context.getContentResolver().openInputStream(photoUri);
        if (rotatedWidth > MAX_IMAGE_DIMENSION || rotatedHeight > MAX_IMAGE_DIMENSION) {
            float widthRatio = ((float) rotatedWidth) / ((float) MAX_IMAGE_DIMENSION);
            float heightRatio = ((float) rotatedHeight) / ((float) MAX_IMAGE_DIMENSION);
            float maxRatio = Math.max(widthRatio, heightRatio);

            // Create the bitmap from file
            BitmapFactory.Options options = new BitmapFactory.Options();
            options.inSampleSize = (int) maxRatio;
            srcBitmap = BitmapFactory.decodeStream(is, null, options);
        } else {
            srcBitmap = BitmapFactory.decodeStream(is);
        }
        is.close();

        /*
         * if the orientation is not 0 (or -1, which means we don't know), we
         * have to do a rotation.
         */
        if (orientation > 0) {
            Matrix matrix = new Matrix();
            matrix.postRotate(orientation);

            srcBitmap = Bitmap.createBitmap(srcBitmap, 0, 0, srcBitmap.getWidth(),
                    srcBitmap.getHeight(), matrix, true);
        }

        String type = context.getContentResolver().getType(photoUri);
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        if (type.equals("image/png")) {
            srcBitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
        } else if (type.equals("image/jpg") || type.equals("image/jpeg")) {
            srcBitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
        }
        byte[] bMapArray = baos.toByteArray();
        baos.close();
        return BitmapFactory.decodeByteArray(bMapArray, 0, bMapArray.length);
    }

    public static int getOrientation(Context context, Uri photoUri) {
        /* it's on the external media. */
        Cursor cursor = context.getContentResolver().query(photoUri,
                new String[] { MediaStore.Images.ImageColumns.ORIENTATION }, null, null, null);

        if (cursor.getCount() != 1) {
            return -1;
        }

        cursor.moveToFirst();
        return cursor.getInt(0);
    }

To get Uri from File use this : 要从File获取Uri,请使用以下命令:

public static Uri getImageContentUri(Context context, File imageFile) {
        String filePath = imageFile.getAbsolutePath();
        Cursor cursor = context.getContentResolver().query(
                MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                new String[] { MediaStore.Images.Media._ID },
                MediaStore.Images.Media.DATA + "=? ",
                new String[] { filePath }, null);
        if (cursor != null && cursor.moveToFirst()) {
            int id = cursor.getInt(cursor
                    .getColumnIndex(MediaStore.MediaColumns._ID));
            Uri baseUri = Uri.parse("content://media/external/images/media");
            return Uri.withAppendedPath(baseUri, "" + id);
        } else {
            if (imageFile.exists()) {
                ContentValues values = new ContentValues();
                values.put(MediaStore.Images.Media.DATA, filePath);
                return context.getContentResolver().insert(
                        MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
            } else {
                return null;
            }
        }
    }

Q. Can you plz tell me what is "MAX_IMAGE_DIMENSION"? 问:你能告诉我什么是“MAX_IMAGE_DIMENSION”吗? – Dhrupal Mar 13 '13 A. its based on your imageview size or the image size what you want to show.. whatever it is 60X60 then 60, 100X100 then 100 @Dhrupal - Dhrupal 3月13日'13 A.它根据你的imageview大小或图像大小你想要显示..无论它是60X60然后60,100X100然后100 @Dhrupal

I guess you should not use " selectedImageUri.getPath() " to get the path since it does not really return the image file path. 我猜你不应该使用“ selectedImageUri.getPath() ”来获取路径,因为它并没有真正返回图像文件路径。 Instead you should use ContentResolver to query the value of MediaStore.Images.ImageColumns.DATA which is the actual path of the image. 相反,您应该使用ContentResolver来查询MediaStore.Images.ImageColumns.DATA的值,这是图像的实际路径。

Actually if you only want to get the orientation, you don't have to get that from the Exif, simply query the value of MediaStore.Images.ImageColumns.ORIENTATION can give you that. 实际上,如果你只想获得方向,你不必从Exif得到它,只需查询MediaStore.Images.ImageColumns.ORIENTATION的值就可以得到它。

it has been long time since questioning. 自提问以来已经很久了。 but i countered with same problem, and solved this. 但我反击同样的问题,并解决了这个问题。 when you put file path into contructor of exifInterface, use real path, like "/storage/sdcard0/DCIM/Camera/blahbalh.jpg", not using something like /content:/media/external/images/media/blah, whiich gives always 0 info. 当你把文件路径放到exifInterface的构造函数中时,使用真实的路径,比如“/storage/sdcard0/DCIM/Camera/blahbalh.jpg”,而不是像/ content:/ media / external / images / media / blah这样的东西。总是0信息。 hope somebody will be helped. 希望有人会得到帮助。 regrads. regrads。

Oops. 哎呀。 below one is same approach. 下面是一个相同的方法。 and here is more. 而且还有更多。 use this. 用这个。

/**
 * @ref http://stackoverflow.com/questions/3401579/get-filename-and-path-from-uri-from-mediastore
 * @param contentUri
 * @return
 */
public String getRealPathFromURI(Uri contentUri) {
    String[] proj = { MediaStore.Images.Media.DATA };
    Cursor cursor = getContentResolver().query(contentUri, proj, null, null, null);
    int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
    cursor.moveToFirst();
    return cursor.getString(column_index);
}

try below code :- 尝试以下代码: -

ExifInterface exif = new ExifInterface(filename);  
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED);  
Bitmap bmRotated = rotateBitmap(bitmap, orientation); 

call below method:- 以下方法致电: -

public static Bitmap rotateBitmap(Bitmap bitmap, int orientation) {

    try{
        Matrix matrix = new Matrix();
        switch (orientation) {
            case ExifInterface.ORIENTATION_NORMAL:
                return bitmap;
            case ExifInterface.ORIENTATION_FLIP_HORIZONTAL:
                matrix.setScale(-1, 1);
                break;
            case ExifInterface.ORIENTATION_ROTATE_180:
                matrix.setRotate(180);
                break;
            case ExifInterface.ORIENTATION_FLIP_VERTICAL:
                matrix.setRotate(180);
                matrix.postScale(-1, 1);
                break;
            case ExifInterface.ORIENTATION_TRANSPOSE:
                matrix.setRotate(90);
                matrix.postScale(-1, 1);
                break;
           case ExifInterface.ORIENTATION_ROTATE_90:
               matrix.setRotate(90);
               break;
           case ExifInterface.ORIENTATION_TRANSVERSE:
               matrix.setRotate(-90);
               matrix.postScale(-1, 1);
               break;
           case ExifInterface.ORIENTATION_ROTATE_270:
               matrix.setRotate(-90);
               break;
           default:
               return bitmap;
        }
        try {
            Bitmap bmRotated = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
            bitmap.recycle();
            return bmRotated;
        }
        catch (OutOfMemoryError e) {
            e.printStackTrace();
            return null;
        }
    }
    catch (IOException e) {
        e.printStackTrace();
        return null;
    }
    return bitmap;
}

You should use getRealPathFromURI function: 你应该使用getRealPathFromURI函数:

public static String getRealPathFromURI(Context context, Uri uri,
            String data) {

    String[] largeFileProjection = { MediaStore.Images.ImageColumns._ID,
            MediaStore.Images.ImageColumns.DATA };

    String largeFileSort = MediaStore.Images.ImageColumns._ID + " DESC";
    Cursor myCursor = context.getContentResolver().query(
            MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
            largeFileProjection, null, null, largeFileSort);
    String largeImagePath = "";
    try {
        myCursor.moveToFirst();
        largeImagePath = myCursor
                .getString(myCursor
                        .getColumnIndexOrThrow(MediaStore.Images.ImageColumns.DATA));
    } finally {
        myCursor.close();
    }

    return largeImagePath;
}

I couldn't get either the cursor or Exif interface method to work for me. 我无法让光标或Exif接口方法为我工作。 I wasn't able to get reliable rotation numbers for both front and back cameras on Samsung. 我无法为三星的前后摄像头获得可靠的旋转数字。

For those looking for a solution which works across both front and back cameras for Samsung and other major manufacturers, this answer by nvhausid is awesome: 对于寻求适用于三星和其他主要制造商的前后摄像头解决方案的人来说,nvhausid的答案非常棒:

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

For those who don't want to click through, the relevant magic is to use the CameraInfo rather then relying on EXIF. 对于那些不想点击的人,相关的魔力是使用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);

Full code in the link. 链接中的完整代码。

When image is captured, it stores an exif data as information about rotation type (portrait - landscape). 捕获图像时,它会将exif数据存储为有关旋转类型(纵向 - 横向)的信息。 So the only thing you need to check is the exif data: 所以你唯一需要检查的是exif数据:

ExifInterface exifData = new ExifInterface(uri);
        int orientation = exifData.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1);
        Matrix matrix;
        switch (orientation) {
        case 6:
             matrix = new Matrix();
            matrix.postRotate(90);
            bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
            break;
        case 3:
             matrix = new Matrix();
            matrix.postRotate(180);
            bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
            break;
        case 8:
            matrix = new Matrix();
            matrix.postRotate(270);
            bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
            break;
        default:
            break;

Have you already checked if you had set Write and Read permissions in your manifest? 您是否已经检查过清单中是否设置了“写入”和“读取”权限? because if you did not set them you cant access to exif data of your bitmap, i'm talking about android M. This is the snippet to rotate a bitmap based on its exif dada. 因为如果你没有设置它们你就无法访问你的位图的exif数据,我正在谈论android M.这是基于它的exif dada旋转位图的片段。

public static Bitmap rotateBitmap(String filePath, Bitmap bitmap) {
    ExifInterface exif;
    try {
        exif = new ExifInterface(filePath);

        int orientation = exif.getAttributeInt(
                ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
        Log.d("EXIF", "Exif: " + orientation);
        Matrix matrix = new Matrix();
        if (orientation == 6) {
            matrix.postRotate(90);
            Log.d("EXIF", "Exif: " + orientation);
        } else if (orientation == 3) {
            matrix.postRotate(180);
            Log.d("EXIF", "Exif: " + orientation);
        } else if (orientation == 8) {
            matrix.postRotate(270);
            Log.d("EXIF", "Exif: " + orientation);
        }
        return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
    } catch (IOException e) {
        e.printStackTrace();
        return null;
    }


}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM