Android部分手機(jī)拍照后獲取的圖片被旋轉(zhuǎn)問(wèn)題的解決方法
調(diào)用Android系統(tǒng)拍照功能后,三星手機(jī)拍攝后的照片被旋轉(zhuǎn)了90度,橫著拍給你變成豎的,豎的拍給你變成橫的。其它品牌的手機(jī)都是正常的,就三星出現(xiàn)這個(gè)怪事。
在Android適配上,我原來(lái)一直以為國(guó)內(nèi)的小米手機(jī)夠奇葩了,結(jié)果還有更奇葩的!你說(shuō)你沒(méi)事旋轉(zhuǎn)照片干啥,實(shí)在是猜不透其居心何在,純粹是在給開(kāi)發(fā)者制造麻煩??!
解決辦法是獲取到拍照后照片被旋轉(zhuǎn)的角度,再旋轉(zhuǎn)回去就好了。
具體思路:
1、首先在調(diào)用拍照方法時(shí),保存拍照后的相片原圖,得到原圖路徑,(PhotoBitmapUtils是我自己寫的一個(gè)工具類)
String fileName = "";
/**
* 啟動(dòng)相機(jī)拍照
*/
private void addBitmapShoots() {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// 設(shè)置圖片要保存的 根路徑+文件名
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、在獲取相機(jī)返回的回調(diào)方法onActivityResult()中,修復(fù)被旋轉(zhuǎn)的圖片并取得修復(fù)后的圖片路徑,有了這個(gè)路徑后就可以展示出來(lái)了
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// 獲取相機(jī)拍照返回
if (resultCode == Activity.RESULT_OK && requestCode == OPEN_CAMERA) {
// 得到修復(fù)后的照片路徑
String filepath = PhotoBitmapUtils.amendRotatePhoto(fileName, getContext());
}
}
PhotoBitmapUtils類:
/**
* 集合一些圖片工具
*
* Created by zhuwentao on 2016-07-22.
*/
public class PhotoBitmapUtils {
/**
* 存放拍攝圖片的文件夾
*/
private static final String FILES_NAME = "/MyPhoto";
/**
* 獲取的時(shí)間格式
*/
public static final String TIME_STYLE = "yyyyMMddHHmmss";
/**
* 圖片種類
*/
public static final String IMAGE_TYPE = ".png";
// 防止實(shí)例化
private PhotoBitmapUtils() {
}
/**
* 獲取手機(jī)可存儲(chǔ)路徑
*
* @param context 上下文
* @return 手機(jī)可存儲(chǔ)路徑
*/
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();
}
}
/**
* 使用當(dāng)前系統(tǒng)時(shí)間作為上傳圖片的名稱
*
* @return 存儲(chǔ)的根路徑+圖片名稱
*/
public static String getPhotoFileName(Context context) {
File file = new File(getPhoneRootPath(context) + FILES_NAME);
// 判斷文件是否已經(jīng)存在,不存在則創(chuàng)建
if (!file.exists()) {
file.mkdirs();
}
// 設(shè)置圖片文件名稱
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卡中
* 如果沒(méi)有SD卡則存在手機(jī)中
*
* @param mbitmap 需要保存的Bitmap圖片
* @return 保存成功時(shí)返回圖片的路徑,失敗時(shí)返回null
*/
public static String savePhotoToSD(Bitmap mbitmap, Context context) {
FileOutputStream outStream = null;
String fileName = getPhotoFileName(context);
try {
outStream = new FileOutputStream(fileName);
// 把數(shù)據(jù)寫入文件,100表示不壓縮
mbitmap.compress(Bitmap.CompressFormat.PNG, 100, outStream);
return fileName;
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
try {
if (outStream != null) {
// 記得要關(guān)閉流!
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; // 圖片的大小設(shè)置為原來(lái)的十分之一
Bitmap bmp = BitmapFactory.decodeFile(path, options);
options = null;
return bmp;
}
/**
* 處理旋轉(zhuǎn)后的圖片
* @param originpath 原圖路徑
* @param context 上下文
* @return 返回修復(fù)完畢后的圖片路徑
*/
public static String amendRotatePhoto(String originpath, Context context) {
// 取得圖片旋轉(zhuǎn)角度
int angle = readPictureDegree(originpath);
// 把原圖壓縮后得到Bitmap對(duì)象
Bitmap bmp = getCompressPhoto(originpath);;
// 修復(fù)圖片被旋轉(zhuǎn)的角度
Bitmap bitmap = rotaingImageView(angle, bmp);
// 保存修復(fù)后的圖片并返回保存后的圖片路徑
return savePhotoToSD(bitmap, context);
}
/**
* 讀取照片旋轉(zhuǎn)角度
*
* @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;
}
/**
* 旋轉(zhuǎn)圖片
* @param angle 被旋轉(zhuǎn)角度
* @param bitmap 圖片對(duì)象
* @return 旋轉(zhuǎn)后的圖片
*/
public static Bitmap rotaingImageView(int angle, Bitmap bitmap) {
Bitmap returnBm = null;
// 根據(jù)旋轉(zhuǎn)角度,生成旋轉(zhuǎn)矩陣
Matrix matrix = new Matrix();
matrix.postRotate(angle);
try {
// 將原始圖片按照旋轉(zhuǎn)矩陣進(jìn)行旋轉(zhuǎn),并得到新的圖片
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;
}
}
在調(diào)用修復(fù)圖片角度方法的時(shí)候需要注意,現(xiàn)在的手機(jī)像素越來(lái)越大,拍完后一張照片有近10M,所以我們需要對(duì)圖片進(jìn)行壓縮處理。不然在保存圖片時(shí)會(huì)等待挺久的,屏幕會(huì)黑一會(huì)。
參考文檔1
參考文檔2
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android實(shí)現(xiàn)屏幕旋轉(zhuǎn)方法總結(jié)
- Android中利用matrix 控制圖片的旋轉(zhuǎn)、縮放、移動(dòng)
- Android Tween動(dòng)畫之RotateAnimation實(shí)現(xiàn)圖片不停旋轉(zhuǎn)效果實(shí)例介紹
- Android開(kāi)發(fā) 旋轉(zhuǎn)屏幕導(dǎo)致Activity重建解決方法
- Android實(shí)現(xiàn)圖片反轉(zhuǎn)、翻轉(zhuǎn)、旋轉(zhuǎn)、放大和縮小
- Android編程中調(diào)用Camera時(shí)預(yù)覽畫面有旋轉(zhuǎn)問(wèn)題的解決方法
- Android開(kāi)發(fā)之圖形圖像與動(dòng)畫(二)Animation實(shí)現(xiàn)圖像的漸變/縮放/位移/旋轉(zhuǎn)
- Android 圖片縮放與旋轉(zhuǎn)的實(shí)現(xiàn)詳解
- Android編程實(shí)現(xiàn)RotateAnimation設(shè)置中心點(diǎn)旋轉(zhuǎn)動(dòng)畫效果
- android實(shí)現(xiàn)icon動(dòng)態(tài)旋轉(zhuǎn)效果
相關(guān)文章
Android中制作進(jìn)度框和環(huán)形進(jìn)度條的簡(jiǎn)單實(shí)例分享
這篇文章主要介紹了Android中制作進(jìn)度框和環(huán)形進(jìn)度條的簡(jiǎn)單實(shí)例分享,環(huán)形進(jìn)度條帶有基本的百分比顯示,需要的朋友可以參考下2016-03-03
Android入門之Fragment嵌套Fragment的用法詳解
這篇文章主要為大家詳細(xì)介紹了Android中如何實(shí)現(xiàn)Fragment嵌套Fragment的相關(guān)資料,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,需要的可以參考一下2023-02-02
Android Studio升級(jí)到3.0 Terminal 中文顯示異常解決
本篇文章主要介紹了Android Studio升級(jí)到3.0 Terminal 中文顯示異常解決,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2017-10-10
Android6.0指紋識(shí)別開(kāi)發(fā)案例
這篇文章主要為大家分享了Android6.0指紋識(shí)別開(kāi)發(fā)案例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-09-09
Android實(shí)現(xiàn)商城購(gòu)物車功能的實(shí)例代碼
最近公司項(xiàng)目做商城模塊,需要實(shí)現(xiàn)購(gòu)物車功能,主要實(shí)現(xiàn)了單選、全選,金額合計(jì),商品刪除,商品數(shù)量加減等功能,這篇文章主要介紹了Android實(shí)現(xiàn)商城購(gòu)物車功能,需要的朋友可以參考下2019-06-06
Android內(nèi)存溢出及內(nèi)存泄漏原因進(jìn)解析
這篇文章主要介紹了Android內(nèi)存溢出及內(nèi)存泄漏原因解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-08-08
詳解Android studio ndk配置cmake開(kāi)發(fā)native C
這篇文章主要介紹了詳解Android studio ndk配置cmake開(kāi)發(fā)native C,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2017-09-09

