安卓拍照生成縮圖及讀取縮圖、原圖、角度等資訊
阿新 • • 發佈:2019-02-16
最近做專案遇到拍照然後顯示圖片到列表,再上傳縮圖到伺服器。為了避免OOM就在想怎麼做才是最好的,最安全的。下面是我的個人想法,如果有更好的辦法,希望可以給我留言共同學習,謝謝。
解決辦法:安卓拍照會生成原圖和縮圖的uri,我們可以去Media-Db中尋找,不需要手動壓縮圖片,然後顯示到列表,點選載入大圖,列表顯示縮圖。但是安卓手機各有不同,又遇到新問題,入下:
問題一:
小米手機返回的全是file:///storage/emulated/0/ibanshou/20170325_110120.jpg,
三星等其他機器是content://media/external/images/media/25087
問題二:
拍照預設不生成縮圖。
下面我就貼出我的程式碼:
首先是呼叫系統相機拍照。並讓它返回Uri。
intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); if (intent.resolveActivity(getPackageManager()) != null) { ContentValues contentValues = new ContentValues(); if(Build.MANUFACTURER.toLowerCase().equals("samsung")) contentValues.put(MediaStore.Images.Media.ORIENTATION, 90f); contentValues.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg"); //mPhotoUri是拍照返回的Uri mPhotoUri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);intent.putExtra(MediaStore.EXTRA_OUTPUT, mPhotoUri);startActivityForResult(intent, 1);}
接著是在回撥中生成縮圖:
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (resultCode != RESULT_OK) { return; } if (isTakePhoto) {//拍照的 intent.putExtra("imageUri", mPhotoUri.toString()); //根據得到的Uri去生成對於的縮圖,並更新Media資料庫的關聯。 long id = ContentUris.parseId(mPhotoUri); // MINI.KIND是要生成縮圖的質量,不懂可以百度下這個。 MediaStore.Images.Thumbnails.getThumbnail(getContentResolver(), id, MediaStore.Images.Thumbnails.MINI_KIND, null); } else {//相簿選的 if (data != null) { if (data.getExtras() != null) intent.putExtras(data.getExtras()); if (data.getData() != null) intent.setData(data.getData()); } } setResult(1, intent); finish(); }
下面回到列表頁面的回撥,顯示到ImageView:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (data != null) {
mImageCaptureUri = data.getData();
image_path = data.getStringExtra("imageUri");
if (mImageCaptureUri != null) {
//選相簿
FileUtils.getPic(mImageCaptureUri, mContext, image_iv1, imagePath, 0);
} else if (!StringUtils.dealNull(image_path).equals("")) {
//拍照
mImageCaptureUri = Uri.parse(data.getStringExtra("imageUri"));
FileUtils.getPic(mImageCaptureUri, mContext, image_iv1, imagePath, 0);
}
}
}
下面貼出FileUtils的相關程式碼,主要是對Media-DB的操作:
/**
* 獲取縮圖
*/
public static String getThumbnails(Context mContext, long image_id) {
String image_path = "";
ContentResolver cr = mContext.getContentResolver();
String[] projection = {MediaStore.Images.Thumbnails.DATA, MediaStore.Images.Thumbnails.IMAGE_ID};
Cursor cursor = cr.query(MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI, projection,
MediaStore.Images.Thumbnails.IMAGE_ID + "=" + image_id, null, null);
if (cursor != null) {
try {
if (cursor.moveToFirst()) {
int dataColumn = cursor.getColumnIndex(MediaStore.Images.Thumbnails.DATA);
int dataColumn_id = cursor.getColumnIndex(MediaStore.Images.Thumbnails.IMAGE_ID);
do {
image_path = cursor.getString(dataColumn);
Log.i("yfchu", image_path + "\n" + cursor.getInt(dataColumn_id));
} while (cursor.moveToNext());
}
} finally {
cursor.close();
}
}
return image_path;
}
/**
* 獲取圖片Id
*/
public static long getImageId(Uri uri, Context mContext) {
long imageId = -1;
String path = uri.getEncodedPath();
if (path != null)
path = Uri.decode(path);
StringBuffer buff = new StringBuffer();
buff.append("(").append(MediaStore.Images.ImageColumns.DATA).append("=")
.append("'" + path + "'").append(")");
String[] projection = {Images.ImageColumns._ID, Images.ImageColumns.TITLE,
Images.ImageColumns.DISPLAY_NAME, Images.ImageColumns.DATA};
ContentResolver cr = mContext.getContentResolver();
Cursor cursor = cr.query(Images.Media.EXTERNAL_CONTENT_URI, projection,
buff.toString(), null, null);
if (cursor != null) {
try {
if (cursor.moveToFirst()) {
do {
imageId = cursor.getInt(cursor.getColumnIndex(Images.ImageColumns._ID));
String title = cursor.getString(cursor.getColumnIndex(Images.ImageColumns.TITLE));
String name = cursor.getString(cursor.getColumnIndex(Images.ImageColumns.DISPLAY_NAME));
String data = cursor.getString(cursor.getColumnIndex(Images.ImageColumns.DATA));
Log.i("yfchu", imageId + "\n" + title + "\n" + name + "\n" + data);
} while (cursor.moveToNext());
}
} finally {
cursor.close();
}
}
return imageId;
}
/**
* 獲取圖片角度
*/
public static int getImageRotate(Uri uri, Context mContext, long id) {
int rotate = 0;
String path = uri.getEncodedPath();
if (path != null)
path = Uri.decode(path);
String[] projection = {Images.Media.DATA, Images.Media.ORIENTATION};
ContentResolver cr = mContext.getContentResolver();
Cursor cursor = cr.query(Images.Media.EXTERNAL_CONTENT_URI, projection,
Images.Media._ID + "=" + id, null, null);
if (cursor != null) {
try {
if (cursor.moveToFirst()) {
do {
rotate = cursor.getInt(cursor.getColumnIndex(Images.Media.ORIENTATION));
} while (cursor.moveToNext());
}
} finally {
cursor.close();
}
}
return rotate;
}
/*
* 獲取圖片--這是主要方法
* */
public static void getPic(Uri mImageCaptureUri, Context mContext,
ImageView image_iv1, String[] imagePath,int position) {
long image_id = -1;
if (mImageCaptureUri.getScheme().equals("file"))//判斷是file還是content
image_id = FileUtils.getImageId(mImageCaptureUri, mContext);//根據路徑去Db查詢imageId
else
image_id = ContentUris.parseId(mImageCaptureUri);//content的尾部就是imageId直接拿。
int rotate = FileUtils.getImageRotate(mImageCaptureUri, mContext, image_id);//獲取圖片角度
String path = FileUtils.getThumbnails(mContext, image_id);//根據ImageId去Thumbnails中查詢ImageId列中相等的欄位就是它的縮圖
if (path.equals("")) {//為空代表無縮圖
try {
if (image_id != -1) {//得到ImageId但是系統沒有生成縮圖,幫它生成縮圖並關聯。下次再選就有了
MediaStore.Images.Thumbnails.getThumbnail(
mContext.getContentResolver(), image_id,
MediaStore.Images.Thumbnails.MINI_KIND, null);
path = FileUtils.getThumbnails(mContext, image_id);
} else {
//這裡處理特殊情況,就是原圖和縮圖在db中都查詢不到得情況。
//你只能自己壓縮了。這裡寫壓縮圖片方法。
}
} catch (Exception e) {
e.printStackTrace();
}
}
if (image_id != -1) {//一切正常,資料庫查到大圖和縮圖等,直接顯示。
File file = new File(path);
imagePath[position] = file.getAbsolutePath();
if (imagePath[position] != null) {
Picasso.with(mContext).load(file).rotate(rotate).into(image_iv1);
}
}
}
由於程式碼在公司專案裡,沒有單獨整出來,就不發工程了。
根據這些網站總結學習的:
http://blog.csdn.net/csqingchen/article/details/45502813
還有看原始碼,從中知道如何系統生成縮圖到db
MediaStore.Images.Media.insertImage()