考慮到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)證完美。