考慮到Android7.0以后拍照修改了調(diào)用和返回方式钱雷,找到了一個(gè)看起來還不錯(cuò)的第三方庫簿训,實(shí)際可能并非如此统阿。
-TakePhoto
在三星Note3和S6上測試玷氏,發(fā)現(xiàn)豎屏拍照后返回的照片是橫屏的绩社,在其它手機(jī)上又是正常的摔蓝。查了資料發(fā)現(xiàn)三星手機(jī)很多都有這個(gè)問題,看到了歪果仁開發(fā)者對(duì)這個(gè)問題近乎罵街的回復(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赌渣,也就是說這些三星手機(jī)即便是豎屏拍照魏铅,的到的圖片文件被順時(shí)針旋轉(zhuǎn)90度后,就變成了橫屏文件坚芜。
還好查了一下庫本身支持設(shè)置重新調(diào)整角度的配置览芳,在
TakePhotoOptions
/**
* 是對(duì)拍的照片進(jìn)行旋轉(zhuǎn)角度糾正
*/
private boolean correctImage;
public void setCorrectImage(boolean correctImage) {
this.correctImage = correctImage;
}
但是設(shè)置后發(fā)現(xiàn)問題依然存在,不再通過gradle引入遠(yuǎn)程代碼的方式鸿竖,下載了TakePhoto的源碼沧竟,重新以Library module的方式引入到項(xiàng)目中。
調(diào)試代碼定位到了問題所在
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了糕非。由于庫沒有做壓縮,一張圖片在重新做旋轉(zhuǎn)的時(shí)候竟然需要60M的內(nèi)存空間,GGG峰弹。
好吧店量,問題找到了,那就先改來能用吧鞠呈,
/**
* 糾正照片的旋轉(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();
}
}
}
總的來說就是先壓縮圖片,編碼格式改為Bitmap.Config.RGB_565蚁吝,減少圖片編碼大泻当;設(shè)置opts.inSampleSize來壓縮圖片大小窘茁,盡量按照你需要的圖片大小來壓縮圖片怀伦,減少OOM發(fā)生的可能性。
驗(yàn)證完美山林。