1. 程式人生 > >安卓拍照生成縮圖及讀取縮圖、原圖、角度等資訊

安卓拍照生成縮圖及讀取縮圖、原圖、角度等資訊

最近做專案遇到拍照然後顯示圖片到列表,再上傳縮圖到伺服器。為了避免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()