調用系統相機/相冊獲取圖片的完美解決方案



調用系統相機/相冊獲取圖片,並裁剪圖片,在百度上找一下能搜到一大堆文章,然而拿過來在真機上跑一下大部分都有問題,根本達不到想要的效果。
爲什麼會拿不到想要的圖片呢,最主要的原因是因爲圖片太大,而獲取的圖片數據是放在Intent中的。而現在手機的像素普遍都是800W+,一張普通的尺寸爲3200*2400px的照片要消耗30MB的內存空間,而一個Intent能傳遞的數據怎麼可能支持這麼大的空間,我測試過一些手機能有1MB已經很開心了。


那麼圖片不放在Intent中,放在哪裏呢。好吧,重要的事情我要說三遍:

“截大圖用Uri,截小圖用Bitmap”
“截大圖用Uri,截小圖用Bitmap”

“截大圖用Uri,截小圖用Bitmap”


對待大圖片時應該用Uri返回數據,小圖片才用Bitmap返回數據,不過現在基本都是大圖片,還是放棄Bitmap的方式吧。

裁剪圖片的關鍵代碼:

intent.putExtra("return-data", false);
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);


實現代碼如下:


	private static final String IMAGE_FILE_LOCATION = "file://" + new File(Environment.getExternalStorageDirectory(), "temp.jpg").getAbsolutePath();//temp file
	private Uri imageUri = Uri.parse(IMAGE_FILE_LOCATION);//The Uri to store the big bitmap
	
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		//Log.i(TAG, "onActivityResult() requestCode = " + requestCode + "   resultCode = " + resultCode);
		if (resultCode == RESULT_OK) {
			switch (requestCode) {
			case Constant.UPLOAD_LOCAL_IMAGE: // 獲取本地相片
				// 獲取本地相片的地址
				getImagpath(data);
				startPhotoZoom(data.getData());
				break;
			case Constant.UPLOAD_CAMERA_IMAGE: // 拍攝照片
				//Log.i(TAG, "onActivityResult() case Constant.UPLOAD_CAMERA_IMAGE ");
				// 獲取原圖
				getYuanTu();
				break;
			case Constant.CAI_JIAN_IMAGE:
				Log.i(TAG, "onActivityResult() requestCode = case Constant.CAI_JIAN_IMAGE (imageUri != null) = " + (imageUri != null));
				if(imageUri != null){
			        Bitmap bitmap = decodeUriAsBitmap(imageUri);//decode bitmap
			        Log.i(TAG, "onActivityResult() CAI_JIAN_IMAGE = bitmap " + bitmap);
			        if (bitmap != null) {
			        	mImageColorTip.setImageBitmap(bitmap);
					}
			    }
				break;
			}
		}
		if (resultCode == Constant.ACTIVIT_FINISH) {
			//Log.i(TAG, "onActivityResult() (resultCode == Constant.ACTIVIT_FINISH)");
			finish();
		}
		//super.onActivityResult(requestCode, resultCode, data);
	}
	
	private Bitmap decodeUriAsBitmap(Uri uri){
	    Bitmap bitmap = null;
	    try {
	        bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri));
	    } catch (FileNotFoundException e) {
	        Log.w(TAG, "decodeUriAsBitmap()", e);
	        return null;
	    }
	    return bitmap;
	}

	private void takePicture() {
		String sDCard = SDCardPath.checkSDCard();
		//Log.i(TAG, "takePicture() (sDCard == null) = " + (sDCard == null));
		if (sDCard == null) {
			showToast(R.string.text_sd_card_invailable);
		} else {
			try {
				String filePath = SDCardPath.getFilePath(sDCard);
				String imagePath = SDCardPath.getImagePath(filePath);
				// 下面這句指定調用相機拍照後的照片存儲的路徑
				File dir = new File(filePath + "/");
				if (!dir.exists()) {
					dir.mkdirs();
				}
				File tmpFile = new File(dir, imagePath);
				if (!tmpFile.exists()) {
						tmpFile.createNewFile();
				}
				Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
				intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(tmpFile));
				TakePhotoColorActivity.sImagePath = tmpFile.getAbsolutePath();
				startActivityForResult(intent,Constant.UPLOAD_CAMERA_IMAGE);
			} catch (IOException e) {
				Log.e(TAG, "openAlbum() IOException", e);
			}
		}
	}

	private void openAlbum() {
		//Log.i(TAG, "openAlbum()");
		Intent intent = new Intent(Intent.ACTION_PICK, null);
		intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
		startActivityForResult(intent,Constant.UPLOAD_LOCAL_IMAGE);
	}
	
	/**
	 * 獲取原圖的方法
	 */
	private void getYuanTu() {
		//Log.i(TAG, "getYuanTu() PictureColorActivity.sImagePath = " + PictureColorActivity.sImagePath);
		File f = new File(TakePhotoColorActivity.sImagePath);
//		Log.i(TAG, "getYuanTu() filePath = " + (f == null ? "iOnesNull" : f.getAbsolutePath()));
		try {
			String imgURL = null;
			try {
				imgURL = android.provider.MediaStore.Images.Media.insertImage(getContentResolver(), f.getAbsolutePath(), null, null);
			} catch (Exception e) {
				Log.e(TAG, "getYuanTu() imgURL", e);
			}
//			Log.i(TAG, "getYuanTu() imgURL = " + imgURL);
			Uri u = null;
			if (imgURL != null) {
				u = Uri.parse(imgURL);
			} else {
				u = Uri.fromFile(f);
			}
//			Log.i(TAG, "getYuanTu() uri = " + (u == null ? "iOnesNull" : u.toString()));
			startPhotoZoom(u);
		} catch (Exception e) {
			Log.e(TAG, "getYuanTu()", e);
		}
	}
	
	/**
	 * 獲取本地圖片的路徑
	 * 
	 * @param data
	 */
	private void getImagpath(Intent data) {
		//Log.i(TAG, "getImagpath() PictureColorActivity.sImagePath = " + PictureColorActivity.sImagePath);
		Uri originalUri = data.getData(); // 獲得圖片的uri
		String[] proj = { MediaStore.Images.Media.DATA };
		// 好像是android多媒體數據庫的封裝接口,具體的看Android文檔
//		Cursor cursor = managedQuery(originalUri, proj, null, null, null);
		Cursor cursor = getContentResolver().query(originalUri, proj, null, null, null);
		// 按我個人理解 這個是獲得用戶選擇的圖片的索引值
		int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
		// 將光標移至開頭 ,這個很重要,不小心很容易引起越界
		cursor.moveToFirst();
		// 最後根據索引值獲取圖片路徑
		String path = cursor.getString(column_index);
		TakePhotoColorActivity.sImagePath = path;
	}
	
	/**
	 * 裁剪圖片方法實現
	 * 
	 * @param uri
	 */
	public void startPhotoZoom(Uri uri) {
		//Log.i(TAG, "startPhotoZoom() PictureColorActivity.sImagePath = " + PictureColorActivity.sImagePath);
		Intent intent = new Intent("com.android.camera.action.CROP");
		intent.setDataAndType(uri, "image/*");
		// 下面這個crop=true是設置在開啓的Intent中設置顯示的VIEW可裁剪
		intent.putExtra("crop", "true");
		// aspectX aspectY 是寬高的比例
		intent.putExtra("aspectX", 1);
		intent.putExtra("aspectY", 1);
		intent.putExtra("scale", true);
		// outputX outputY 是裁剪圖片寬高
		// TODO 詳情參考:http://my.oschina.net/ryanhoo/blog/86842
		intent.putExtra("outputX", 500);
		intent.putExtra("outputY", 500);
		intent.putExtra("noFaceDetection", true);
		intent.putExtra("return-data", false);
		Log.i(TAG, "startPhotoZoom() (imageUri != null) = " + (imageUri != null));
		intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
		intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
		startActivityForResult(intent, Constant.CAI_JIAN_IMAGE);
	}

	/** 大圖圖片的路徑 */
	private static String sImagePath = "";
	
	public interface Constant {
		/**
		 * 獲取本地圖片
		 */
		public static  final int UPLOAD_LOCAL_IMAGE  = 0x0001; 
	  /**
	   * 獲取相機圖片
	   */
		public  static final int UPLOAD_CAMERA_IMAGE = 0x0002;  
		public  static final String SD_CARD_ROOT = "sdcard";
		/**
		 * 裁剪圖片
		 */
		public  static final  int CAI_JIAN_IMAGE=0x0003;
		/**
		 * 回調結束當前界面
		 */
		public static final int ACTIVIT_FINISH = 0x0004; 
		/**相機裁剪後的照片*/
		public static final int IMAGE_CODE_PATH = 0x0005;

	}


如果對你有幫助,不要謝我。大神在這裏:http://my.oschina.net/ryanhoo/blog/86842 


發佈了50 篇原創文章 · 獲贊 22 · 訪問量 13萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章