仅在三星设备中从相机单击时图像会旋转

Posted

技术标签:

【中文标题】仅在三星设备中从相机单击时图像会旋转【英文标题】:Image is getting rotated when clicked from camera only in Samasung device 【发布时间】:2016-12-06 11:59:30 【问题描述】:

在我的应用程序中,当在纵向模式下从相机中单击图像时,图像会旋转,这仅适用于三星设备,其余设备工作正常。在研究堆栈溢出后,我实现了以下代码:

ExifInterface ei = new ExifInterface(imgFile.getPath());
int orientation = ei.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED);

switch (orientation) 
case ExifInterface.ORIENTATION_UNDEFINED:
mBitmap = rotateImage(bitmap, 90);
break;

这段代码帮助我解决了三星中的这个问题,但是现在当从相机点击图像时,由于这段代码,它在其他设备中被旋转。

请告诉我如何解决此问题。

【问题讨论】:

就文档而言:getAttributeInt "返回指定标签的整数值。如果图像文件中没有这样的标签或该值无法解析为整数,则返回 defaultValue。" , 这意味着标签未定义,并且返回 ExifInterface.ORIENTATION_UNDEFINED (0),或者您的开关未处理 ORIENTATION_(something) 情况。添加一个默认子句,并记录返回的orientation 好的,非常感谢..会这样做..我在切换之前检查了方向的值,它说 0.. 还要注意这个“问题”是旧的,since 2012 知道三星不会正确保存 Exif 数据。 Even the Exif standard 存在导致不兼容情况的问题。由于三星不支持 Exif 界面,您可以自己编辑该设置(如果您要求相机意图,请使用设备方向)或检查位图高度/宽度,并相应地翻转图像。 好的好的..非常感谢 【参考方案1】:

使用下面的类

 String path="path of your image";

 imageview.setImageBitmap(ExifUtil.rotateBitmap(path, BitmapFactory.decodeFile(path)));

ExifUtil.java

public class ExifUtil 
    /**
     * @see http://sylvana.net/jpegcrop/exif_orientation.html
     */
    public static Bitmap rotateBitmap(String src, Bitmap bitmap) 
        try 
            int orientation = getExifOrientation(src);

            if (orientation == 1) 
                return bitmap;
            

            Matrix matrix = new Matrix();
            switch (orientation) 
            case 2:
                matrix.setScale(-1, 1);
                break;
            case 3:
                matrix.setRotate(180);
                break;
            case 4:
                matrix.setRotate(180);
                matrix.postScale(-1, 1);
                break;
            case 5:
                matrix.setRotate(90);
                matrix.postScale(-1, 1);
                break;
            case 6:
                matrix.setRotate(90);
                break;
            case 7:
                matrix.setRotate(-90);
                matrix.postScale(-1, 1);
                break;
            case 8:
                matrix.setRotate(-90);
                break;
            default:
                return bitmap;
            

            try 
                Bitmap oriented = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
                bitmap.recycle();
                return oriented;
             catch (OutOfMemoryError e) 
                e.printStackTrace();
                return bitmap;
            
         catch (IOException e) 
            e.printStackTrace();
         

        return bitmap;
    

    private static int getExifOrientation(String src) throws IOException 
        int orientation = 1;

        try 
            /**
             * if your are targeting only api level >= 5
             * ExifInterface exif = new ExifInterface(src);
             * orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1);
             */
            if (Build.VERSION.SDK_INT >= 5) 
                Class<?> exifClass = Class.forName("android.media.ExifInterface");
                Constructor<?> exifConstructor = exifClass.getConstructor(new Class[]  String.class );
                Object exifInstance = exifConstructor.newInstance(new Object[]  src );
                Method getAttributeInt = exifClass.getMethod("getAttributeInt", new Class[]  String.class, int.class );
                Field tagOrientationField = exifClass.getField("TAG_ORIENTATION");
                String tagOrientation = (String) tagOrientationField.get(null);
                orientation = (Integer) getAttributeInt.invoke(exifInstance, new Object[]  tagOrientation, 1);
            
         catch (ClassNotFoundException e) 
            e.printStackTrace();
         catch (SecurityException e) 
            e.printStackTrace();
         catch (NoSuchMethodException e) 
            e.printStackTrace();
         catch (IllegalArgumentException e) 
            e.printStackTrace();
         catch (InstantiationException e) 
            e.printStackTrace();
         catch (IllegalAccessException e) 
            e.printStackTrace();
         catch (InvocationTargetException e) 
            e.printStackTrace();
         catch (NoSuchFieldException e) 
            e.printStackTrace();
        

        return orientation;
    

【讨论】:

你的问题解决了吗?【参考方案2】:

通过返回度来转换位图,

try 
       ExifInterface exif = new ExifInterface(imgPath);  
        String rotationAmount = exif
                .getAttribute(ExifInterface.TAG_ORIENTATION);
        if (!TextUtils.isEmpty(rotationAmount)) 
            int rotationParam = Integer.parseInt(rotationAmount);
            switch (rotationParam) 
            case ExifInterface.ORIENTATION_NORMAL:
                return 0;
            case ExifInterface.ORIENTATION_ROTATE_90:
                return 90;
            case ExifInterface.ORIENTATION_ROTATE_180:
                return 180;
            case ExifInterface.ORIENTATION_ROTATE_270:
                return 270;
            default:
                return 0;
            
         else 
            return 0;
        
     catch (Exception ex) 
        return 0;
    

【讨论】:

我总是将旋转量设为 0.. 所以它总是在旋转 查看更新代码,根据图片获取旋转,先获取图片位置,再找到位图旋转需求。【参考方案3】:

如果您确信这只是三星设备的问题,您可以检查设备制造商并将其添加到您的 if(...) 条件中。 This 库可以提供很大帮助。

还可以查看 Jared Rummler 对this 问题的回答:

但是,如果这是特定于设备的问题,它也可能出现在其他设备上,或者最终可能在较新的三星设备操作系统更新中得到纠正。好好检查一下。

【讨论】:

以上是关于仅在三星设备中从相机单击时图像会旋转的主要内容,如果未能解决你的问题,请参考以下文章

android中三星设备上的相机捕捉方向

Firebase 存储图像被旋转

仅在单击按钮后请求相机权限

从相机/图库加载图像位图时会旋转 [Android 9]

如果相机旋转,来自相机的图像为空

仅在 Pixel_Api_26 模拟器中从相机拍摄照片后,无法在 ImageView 中放置图像