三星等機(jī)型上拍照后圖片被旋轉(zhuǎn)90度的解決方案

考慮到Android7.0以后拍照修改了調(diào)用和返回方式,找到了一個(gè)看起來(lái)還不錯(cuò)的第三方庫(kù),實(shí)際可能并非如此。
-TakePhoto

在三星Note3和S6上測(cè)試,發(fā)現(xiàn)豎屏拍照后返回的照片是橫屏的,在其它手機(jī)上又是正常的。查了資料發(fā)現(xiàn)三星手機(jī)很多都有這個(gè)問(wèn)題,看到了歪果仁開(kāi)發(fā)者對(duì)這個(gè)問(wèn)題近乎罵街的回復(fù),發(fā)現(xiàn)這屬于三星的一個(gè)系統(tǒng)級(jí)Bug。豎屏拍照后得到的照片文件就是橫屏的,只有應(yīng)用對(duì)這些照片重新處理。

/**
     * 讀取圖片的旋轉(zhuǎn)的角度
     *
     * @param path 圖片絕對(duì)路徑
     * @return 圖片的旋轉(zhuǎn)角度
     */
    private int getBitmapDegree(String path) {
        int degree = 0;
        try {
            // 從指定路徑下讀取圖片,并獲取其EXIF信息
            ExifInterface exifInterface = new ExifInterface(path);
            // 獲取圖片的旋轉(zhuǎn)信息
            int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION,
                    ExifInterface.ORIENTATION_NORMAL);
            switch (orientation) {
                case ExifInterface.ORIENTATION_ROTATE_90:
                    degree = 90;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_180:
                    degree = 180;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_270:
                    degree = 270;
                    break;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return degree;
    }

如上代碼可以獲取圖片文件的旋轉(zhuǎn)角度,可以發(fā)現(xiàn)在這些三星手機(jī)上的到的返回值都是ExifInterface.ORIENTATION_ROTATE_90,也就是說(shuō)這些三星手機(jī)即便是豎屏拍照,的到的圖片文件被順時(shí)針旋轉(zhuǎn)90度后,就變成了橫屏文件。

還好查了一下庫(kù)本身支持設(shè)置重新調(diào)整角度的配置,在

TakePhotoOptions
/**
     * 是對(duì)拍的照片進(jìn)行旋轉(zhuǎn)角度糾正
     */
    private boolean correctImage;
public void setCorrectImage(boolean correctImage) {
        this.correctImage = correctImage;
    }

但是設(shè)置后發(fā)現(xiàn)問(wèn)題依然存在,不再通過(guò)gradle引入遠(yuǎn)程代碼的方式,下載了TakePhoto的源碼,重新以Library module的方式引入到項(xiàng)目中。

調(diào)試代碼定位到了問(wèn)題所在

ImageRotateUtil
/**
     * 將圖片按照某個(gè)角度進(jìn)行旋轉(zhuǎn)
     *
     * @param bm     需要旋轉(zhuǎn)的圖片
     * @param degree 旋轉(zhuǎn)角度
     * @return 旋轉(zhuǎn)后的圖片
     */
    private Bitmap rotateBitmapByDegree(Bitmap bm, int degree) {
        Bitmap returnBm = null;

        // 根據(jù)旋轉(zhuǎn)角度,生成旋轉(zhuǎn)矩陣
        Matrix matrix = new Matrix();
        matrix.postRotate(degree);
        try {
            // 將原始圖片按照旋轉(zhuǎn)矩陣進(jìn)行旋轉(zhuǎn),并得到新的圖片
            returnBm = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true);
        } catch (OutOfMemoryError e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (returnBm == null) {
            returnBm = bm;
        }
        if (bm != returnBm) {
            bm.recycle();
        }
        return returnBm;
    }

在如上代碼中returnBm重新賦值的時(shí)候,也就是將原始圖片重新旋轉(zhuǎn)角度得到正確角度的圖片這里,這個(gè)地方尼瑪OOM了。由于庫(kù)沒(méi)有做壓縮,一張圖片在重新做旋轉(zhuǎn)的時(shí)候竟然需要60M的內(nèi)存空間,GGG。

好吧,問(wèn)題找到了,那就先改來(lái)能用吧,

/**
     * 糾正照片的旋轉(zhuǎn)角度
     * @param path
     */
    public void correctImage(Context context,Uri path){

        String imagePath=TUriParse.parseOwnUri(context,path);
        int degree;
        if((degree=getBitmapDegree(imagePath))!=0){
            // *** add to fix oom
            BitmapFactory.Options opts = new BitmapFactory.Options();
            opts.inJustDecodeBounds = true; // 設(shè)置成了true,不占用內(nèi)存,只獲取bitmap寬高
            BitmapFactory.decodeFile(imagePath, opts);

            opts.inSampleSize = calculateInSampleSize(opts, 360, 640); // 調(diào)用上面定義的方法計(jì)算inSampleSize值
            opts.inJustDecodeBounds = false;// 使用獲取到的inSampleSize值再次解析圖片
            opts.inPreferredConfig = Bitmap.Config.RGB_565;
            opts.inDither = true;
            Bitmap bitmap = BitmapFactory.decodeFile(imagePath, opts);

            // *** add to fix end
            if(bitmap==null)return;
            Bitmap resultBitmap=rotateBitmapByDegree(bitmap,degree);
            if(resultBitmap==null)return;
            try {
                resultBitmap.compress(Bitmap.CompressFormat.JPEG,100,new FileOutputStream(new File(imagePath)));
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }catch (OutOfMemoryError e){
                e.printStackTrace();
            }
        }
    }

總的來(lái)說(shuō)就是先壓縮圖片,編碼格式改為Bitmap.Config.RGB_565,減少圖片編碼大小;設(shè)置opts.inSampleSize來(lái)壓縮圖片大小,盡量按照你需要的圖片大小來(lái)壓縮圖片,減少OOM發(fā)生的可能性。

驗(yàn)證完美。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,366評(píng)論 25 708
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 15,820評(píng)論 4 61
  • 剛剛想起來(lái)前幾天面試的時(shí)候遇到的一個(gè)問(wèn)題,問(wèn)題大概是這樣的做拍照上傳圖片功能的時(shí)候,在三星手機(jī)上拍出的照片是旋轉(zhuǎn)了...
    CokaZhang閱讀 3,348評(píng)論 0 3
  • 在外人看來(lái)你很努力,很要強(qiáng),盡量把每件事情都做好,可是在他眼里你做什么,他都覺(jué)得不好,你身上的每個(gè)毛病都會(huì)被他放大...
    小蓮2017閱讀 349評(píng)論 0 0
  • 2017,繼續(xù)探尋多彩的世界和未知的自己,加油!
    fourcai閱讀 109評(píng)論 0 0

友情鏈接更多精彩內(nèi)容