1. 程式人生 > >Android 解決部分手機拍照後獲取的圖片被旋轉的問題

Android 解決部分手機拍照後獲取的圖片被旋轉的問題

最近又被測試MM找茬了,呼叫Android系統拍照功能後,三星手機拍攝後的照片被旋轉了90度,橫著拍給你變成豎的,豎的拍給你變成橫的。。。其它品牌的手機都是正常的,就三星出現這個怪事。

在Android適配上,我原來一直以為國內的小米手機夠奇葩了,結果還有更奇葩的!你說你沒事旋轉照片幹啥,實在是猜不透其居心何在,純粹是在給開發者製造麻煩啊!

解決辦法是獲取到拍照後照片被旋轉的角度,再旋轉回去就好了。

具體思路:

1、首先在呼叫拍照方法時,儲存拍照後的相片原圖,得到原圖路徑,(PhotoBitmapUtils是我自己寫的一個工具類)

    String fileName = "";
    /**
     * 啟動相機拍照
     */
    private void addBitmapShoots() {
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        // 設定圖片要儲存的 根路徑+檔名
        fileName = PhotoBitmapUtils.getPhotoFileName(getContext());
        File file = new File(fileName);
        if (!file.exists()) {
            try {
                file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file));
        startActivityForResult(intent, OPEN_CAMERA);
    }

2、在獲取相機返回的回撥方法onActivityResult()中,修復被旋轉的圖片並取得修復後的圖片路徑,有了這個路徑後就可以展示出來了

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        // 獲取相機拍照返回
        if (resultCode == Activity.RESULT_OK && requestCode == OPEN_CAMERA) {
            // 得到修復後的照片路徑
            String filepath = PhotoBitmapUtils.amendRotatePhoto(fileName, getContext());
        }
    }

PhotoBitmapUtils類:

/**
 * 集合一些圖片工具
 *
 * Created by zhuwentao on 2016-07-22.
 */
public class PhotoBitmapUtils {

    /**
     * 存放拍攝圖片的資料夾
     */
    private static final String FILES_NAME = "/MyPhoto";
    /**
     * 獲取的時間格式
     */
    public static final String TIME_STYLE = "yyyyMMddHHmmss";
    /**
     * 圖片種類
     */
    public static final String IMAGE_TYPE = ".png";

    // 防止例項化
    private PhotoBitmapUtils() {
    }

    /**
     * 獲取手機可儲存路徑
     *
     * @param context 上下文
     * @return 手機可儲存路徑
     */
    private static String getPhoneRootPath(Context context) {
        // 是否有SD卡
        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)
                || !Environment.isExternalStorageRemovable()) {
            // 獲取SD卡根目錄
            return context.getExternalCacheDir().getPath();
        } else {
            // 獲取apk包下的快取路徑
            return context.getCacheDir().getPath();
        }
    }

    /**
     * 使用當前系統時間作為上傳圖片的名稱
     *
     * @return 儲存的根路徑+圖片名稱
     */
    public static String getPhotoFileName(Context context) {
        File file = new File(getPhoneRootPath(context) + FILES_NAME);
        // 判斷檔案是否已經存在,不存在則建立
        if (!file.exists()) {
            file.mkdirs();
        }
        // 設定圖片檔名稱
        SimpleDateFormat format = new SimpleDateFormat(TIME_STYLE, Locale.getDefault());
        Date date = new Date(System.currentTimeMillis());
        String time = format.format(date);
        String photoName = "/" + time + IMAGE_TYPE;
        return file + photoName;
    }

    /**
     * 儲存Bitmap圖片在SD卡中
     * 如果沒有SD卡則存在手機中
     *
     * @param mbitmap 需要儲存的Bitmap圖片
     * @return 儲存成功時返回圖片的路徑,失敗時返回null
     */
    public static String savePhotoToSD(Bitmap mbitmap, Context context) {
        FileOutputStream outStream = null;
        String fileName = getPhotoFileName(context);
        try {
            outStream = new FileOutputStream(fileName);
            // 把資料寫入檔案,100表示不壓縮
            mbitmap.compress(Bitmap.CompressFormat.PNG, 100, outStream);
            return fileName;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            try {
                if (outStream != null) {
                    // 記得要關閉流!
                    outStream.close();
                }
                if (mbitmap != null) {
                    mbitmap.recycle();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 把原圖按1/10的比例壓縮
     *
     * @param path 原圖的路徑
     * @return 壓縮後的圖片
     */
    public static Bitmap getCompressPhoto(String path) {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = false;
        options.inSampleSize = 10;  // 圖片的大小設定為原來的十分之一
        Bitmap bmp = BitmapFactory.decodeFile(path, options);
        options = null;
        return bmp;
    }

    /**
     * 處理旋轉後的圖片
     * @param originpath 原圖路徑
     * @param context 上下文
     * @return 返回修復完畢後的圖片路徑
     */
    public static String amendRotatePhoto(String originpath, Context context) {

        // 取得圖片旋轉角度
        int angle = readPictureDegree(originpath);

        // 把原圖壓縮後得到Bitmap物件
        Bitmap bmp = getCompressPhoto(originpath);;

        // 修復圖片被旋轉的角度
        Bitmap bitmap = rotaingImageView(angle, bmp);

        // 儲存修復後的圖片並返回儲存後的圖片路徑
        return savePhotoToSD(bitmap, context);
    }

    /**
     * 讀取照片旋轉角度
     *
     * @param path 照片路徑
     * @return 角度
     */
    public static int readPictureDegree(String path) {
        int degree = 0;
        try {
            ExifInterface exifInterface = new ExifInterface(path);
            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;
    }

    /**
     * 旋轉圖片
     * @param angle 被旋轉角度
     * @param bitmap 圖片物件
     * @return 旋轉後的圖片
     */
    public static Bitmap rotaingImageView(int angle, Bitmap bitmap) {
        Bitmap returnBm = null;
        // 根據旋轉角度,生成旋轉矩陣
        Matrix matrix = new Matrix();
        matrix.postRotate(angle);
        try {
            // 將原始圖片按照旋轉矩陣進行旋轉,並得到新的圖片
            returnBm = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
        } catch (OutOfMemoryError e) {
        }
        if (returnBm == null) {
            returnBm = bitmap;
        }
        if (bitmap != returnBm) {
            bitmap.recycle();
        }
        return returnBm;
    }
}

在呼叫修復圖片角度方法的時候需要注意,現在的手機畫素越來越大,拍完後一張照片有近10M,所以我們需要對圖片進行壓縮處理。不然在儲存圖片時會等待挺久的,螢幕會黑一會。

參考文件1

參考文件2

相關推薦

Android 解決部分手機拍照獲取圖片旋轉的問題

最近又被測試MM找茬了,呼叫Android系統拍照功能後,三星手機拍攝後的照片被旋轉了90度,橫著拍給你變成豎的,豎的拍給你變成橫的。。。其它品牌的手機都是正常的,就三星出現這個怪事。 在Android適配上,我原來一直以為國內的小米手機夠奇葩了,結果還有更奇葩的!你說你沒

android解決三星手機拍照獲取圖片的問題

最近在專案中用到了拍照獲取圖片上傳的功能。在其它的手機上測試功能正常,但是在我自己用的三星s3上面就出現了問題。這個問題困擾了我好幾天。最後發現了一個問題,三星手機在拍照時預設是橫屏的,我的應用預設是

Android開發:解決三星裝置拍照獲取圖片旋轉的問題

呼叫Android系統拍照功能後,三星手機拍攝後的照片被旋轉了90度,橫著拍變成豎的,豎著拍變成橫的。。。測試其它品牌的手機是正常的,就三星出現這個問題。 解決方法: 1、首先在呼叫拍照方法時,儲存拍照後的相片原圖,得到原圖路徑,(PhotoBitmapUtils是我

Android之如何解決部分手機拍照拍出來的照片是黑色

如何解決部分手機拍照拍出來的照片是黑色          最近專案做的是遠端拍照和遠端截圖的問題,遠端截圖用的是Android 5.0之後的API,MediaPrejectionManger,          拍照用的是呼叫系統的camera,用的surfaceView進

關於android中呼叫系統拍照,返回圖片旋轉90度..

由於專案的需要,沒有自定義拍照功能,僅僅呼叫了系統的拍照程式..但是出現了一個問題,就是拍照完成顯示圖片居然是被旋轉的圖片....解決辦法:/** * 獲取圖片的旋轉角度,有些系統把拍照的圖片旋轉了,有的沒有旋轉 */ int degree

解決android有的手機拍照上傳圖片旋轉的問題

需求:做仿新浪發微博的專案,能夠上傳圖片還有兩外一個專案用到手機拍攝圖片,這兩個都需要把圖片上傳到伺服器 遇到問題:有的手機拍攝的圖片旋轉90度,有的圖片旋轉了180度,有的手機是正常的,伺服器要求的是正的,這樣問題就來了,不能使用者發個照片在微博上看到的是被旋轉了的啊,另

android手機拍照上傳圖片旋轉的問題

原貼子連結: http://blog.csdn.net/walker02/article/details/8211628/,謝謝點選開啟連結 遇到問題:有的手機拍攝的圖片旋轉90度,有的圖片旋轉了180度,有的手機是正常的,伺服器要求的是正的,這樣問題就來了,不能使用者發

Android手機拍照儲存高清原圖

Android手機中呼叫系統相機進行拍照的操作很簡單: 1.呼叫系統相機 Intent openCameraIntent = new Intent(MediaStore.ACTION_IMAGE

Android 拍照獲取真實路徑

普通的獲取圖片方式: 得到的將是縮圖,而且因手機的不同, 縮圖的大小也不一樣 Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); startActivityForResult(intent, RESUL

Android 解決小米手機選取圖片返回值為null

之前寫過一篇呼叫系統相機拍照和選取本地圖片並裁剪的部落格,然後昨天有人和我說你的那個demo在小米手機上在本地相簿中選取圖片之後會崩掉,然後我在這裡解答一下這個問題,問題原因是因為小米手機在選取圖片之

Android手機拍照照片旋轉或者需要旋轉的問題

1、讀取圖片的旋轉屬性 /** * 讀取圖片的旋轉的角度 * * @param path *            圖片絕對路徑 * @return 圖片的旋轉角度

Android 7.0實現拍照獲取相簿圖片上傳頭像功能

對網上關於Android7.0的上傳頭像進行整理 1.新增許可權管理。內容例如以下: <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-pe

Android部分手機(oppo r9s)安裝app出現崩潰問題解決辦法

1、問題現象 部分手機(oppo r9s)安裝release版本的apk出現了崩潰,但是部分手機安裝正常 2、崩潰日誌 01-15 09:42:37.239 5889 5889 E AndroidRuntime: java.lang.OutOfMemoryError

android 呼叫系統相機拍照圖片上顯示文字

 先說說自己的思路(有什麼欠缺的望噴。。。)    1、在xml 檔案寫入Imageview(用來顯示拍照圖片) 和textview (顯示想要顯示的文字)  2、將xml 佈局通過   LayoutInflater.from(context).inflate轉換為view檢

解決Android呼叫系統相機拍照相片無法在相簿中顯示問題

目前自己使用傳送廣播實現了效果public void photo() { Intent openCameraIntent = new Intent(android.provider.MediaSt

Android MIUI系統呼叫拍照不返回當前activity如何解決

在實際應用過程中,由於需要插入圖片,所以要支援利用攝像頭拍照和從相簿中的相簿選擇圖片的功能。從相簿選圖沒有任何問題,但是拍照的時候,在小米的miui系統下就出現了其他機型沒有出現的bug。我們先來看程式碼,先寫呼叫camera的程式碼:    camera_picname=

Android呼叫相機實現拍照並裁剪圖片,呼叫手機中的相簿圖片並裁剪圖片

在 Android應用中,很多時候我們需要實現上傳圖片,或者直接呼叫手機上的拍照功能拍照處理然後直接顯示並上傳功能,下面將講述呼叫相機拍照處理圖片然後顯示和呼叫手機相簿中的圖片處理然後顯示的功能,要想實現上傳功能,一般都是上傳到資料庫中,將imageView中的圖片取出來然

如何獲得android手機拍照照片的存放目錄

我現在的解決方法是,在系統的Images的ContentProvider中註冊觀察者,這樣拍照引起資料庫改變後,觀察者就能知道。但這樣做是不能準確分辨出照片和複製貼上的圖片或者其他渠道產生的圖片的。所以還有加上過濾。我現在的過濾方法有兩個,一個是用新加入的檔名和圖片大小,

HTML5+Canvas+jQuery調用手機拍照功能實現圖片上傳(二)

customer mkdir 狀態保存 ont false lan else if 項目 action 上一篇僅僅講到前臺操作,這篇專門涉及到Java後臺處理。前臺通過Ajax提交將Base64編碼過的圖片數據信息傳到Java後臺,然後Java這邊進行接收處理。通過

百度地圖手機端單觸點單擊和長按事件,解決部分手機(小米手機)地圖單擊事件失效,多觸點、拖動依然觸發長按的bug

|| ble apply timeout console dto eat 問題 int /** * Author 嶽曉 * * 對百度地圖的事件擴展,目前擴展了fastclick和longclick, * 解決某些設備click不執行的問題