獲取相冊照片和獲取拍照照片

在Android的開發過程中,我們可能會讀取手機裏面的照片或者通過相機拍攝獲取照片,這是兩種常用的獲取圖片的方式,在做項目過程中也會經常遇到,下面來介紹一下這兩種獲取方式..

一、需要裁剪
1.定義相關常量以及照片的名稱和路徑

private static final int REQUEST_CODE_PICK_IMAGE = 1;
	private static final int REQUEST_CODE_CAPTURE_CAMEIA = 2;
	private static final int PHOTO_REQUEST_CUT = 3;

	private File tempFile = new File(Environment.getExternalStorageDirectory(),
			getPhotoFileName());

	// 使用系統當前日期加以調整作爲照片的名稱
	private String getPhotoFileName() {
		Date date = new Date(System.currentTimeMillis());
		SimpleDateFormat dateFormat = new SimpleDateFormat(
				"'IMG'_yyyyMMdd_HHmmss");
		return dateFormat.format(date) + ".jpg";
	}

2.從本地相冊獲取照片:
一般就是寫出這個方法

protected void getImageFromAlbum() {  
       Intent intent = new Intent(Intent.ACTION_PICK);
	intent.setType("image/*");// 相片類型
	startActivityForResult(intent, REQUEST_CODE_PICK_IMAGE);
   }  


3.從照相機獲取照片
一般就是寫出這個方法

protected void getImageFromCamera() { 
        String state = Environment.getExternalStorageState();
	if (state.equals(Environment.MEDIA_MOUNTED)) {
	Intent getImageByCamera = new Intent(
	MediaStore.ACTION_IMAGE_CAPTURE);
	getImageByCamera.putExtra(MediaStore.EXTRA_OUTPUT,
	Uri.fromFile(tempFile));
	startActivityForResult(getImageByCamera,
	REQUEST_CODE_CAPTURE_CAMEIA);
	} else {
	Toast.makeText(getApplicationContext(), "請確認已經插入SD卡",
	Toast.LENGTH_LONG).show();
	}
   } 


4.寫完這個方法後,一般我們還需要通過響應這個方法去獲取圖片

@Override  
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		{
			switch (requestCode) {
			case REQUEST_CODE_PICK_IMAGE:// 當選擇從本地獲取圖片時
				// 做非空判斷,當我們覺得不滿意想重新剪裁的時候便不會報異常,下同
				if (data != null)
					startPhotoZoom(data.getData());
				break;
			case REQUEST_CODE_CAPTURE_CAMEIA:// 當選擇拍照時調用
				startPhotoZoom(Uri.fromFile(tempFile));
				break;
			case PHOTO_REQUEST_CUT:// 返回的結果
				if (data != null)
					// setPicToView(data);
					sentPicToNext(data);
				break;
			}
			super.onActivityResult(requestCode, resultCode, data);
		}
	}


5.實現startPhotoZoom(Uri uri)方法,調整圖片大小並且裁剪。

private void startPhotoZoom(Uri uri) {
		// TODO Auto-generated method stub
		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);

		// outputX,outputY 是剪裁圖片的寬高
		intent.putExtra("outputX", 300);
		intent.putExtra("outputY", 300);
		intent.putExtra("return-data", true);
		intent.putExtra("noFaceDetection", true);
		startActivityForResult(intent, PHOTO_REQUEST_CUT);
	}

6.實現setToImg(Intent data)方法

private void setToImg(Intent data) {
		// TODO Auto-generated method stub
		Bundle bundle = data.getExtras();
		ImageView img = (ImageView) findViewById(viewId);
		if (bundle != null) {
			Bitmap photo = bundle.getParcelable("data");
			if (photo == null) {

				img.setImageResource(R.drawable.ic_launcher);
			} else {
				img.setImageBitmap(photo);
				// 設置文本內容爲 圖片絕對路徑和名字
				// text.setText(tempFile.getAbsolutePath());
			}
		}
	}

二、不需要裁剪
1.定義相關常量以及照片的名稱和路徑

	private static final int REQUEST_CODE_PICK_IMAGE = 1;
	private static final int REQUEST_CODE_CAPTURE_CAMEIA = 2;

	private File tempFile = new File(Environment.getExternalStorageDirectory(),
			getPhotoFileName());

	// 使用系統當前日期加以調整作爲照片的名稱
	private String getPhotoFileName() {
		Date date = new Date(System.currentTimeMillis());
		SimpleDateFormat dateFormat = new SimpleDateFormat(
				"'IMG'_yyyyMMdd_HHmmss");
		return dateFormat.format(date) + ".jpg";
	}
2.從本地相冊獲取照片:

protected void getImageFromAlbum() {  
       Intent intent = new Intent(Intent.ACTION_PICK);
	intent.setType("image/*");// 相片類型
	startActivityForResult(intent, REQUEST_CODE_PICK_IMAGE);
   }  

3.從照相機獲取照片

protected void getImageFromCamera() { 
        String state = Environment.getExternalStorageState();
	if (state.equals(Environment.MEDIA_MOUNTED)) {
	Intent getImageByCamera = new Intent(
	MediaStore.ACTION_IMAGE_CAPTURE);
	getImageByCamera.putExtra(MediaStore.EXTRA_OUTPUT,
	Uri.fromFile(tempFile));
	startActivityForResult(getImageByCamera,
	REQUEST_CODE_CAPTURE_CAMEIA);
	} else {
	Toast.makeText(getApplicationContext(), "請確認已經插入SD卡",
	Toast.LENGTH_LONG).show();
	}
   }  



4.寫完這個方法後,一般我們還需要通過響應這個方法去獲取圖片

@Override  
   @Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		{
			Uri uri = null;
			Bitmap photo = null;
			ImageView img = null;
			switch (requestCode) {
			case REQUEST_CODE_PICK_IMAGE:// 當選擇從本地獲取圖片時
				// 做非空判斷,當我們覺得不滿意想重新剪裁的時候便不會報異常,下同
				if (data != null) {
					uri = data.getData();
					String[] proj = { MediaStore.Images.Media.DATA };
					Cursor actualimagecursor = managedQuery(uri, proj, null,
							null, null);
					int actual_image_column_index = actualimagecursor
							.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
					actualimagecursor.moveToFirst();
					String img_path = actualimagecursor
							.getString(actual_image_column_index);
					// File file = new File(img_path);
					photo = BitmapFactory.decodeFile(img_path);
					img = (ImageView) findViewById(viewId);
					if (photo == null) {
						img.setImageResource(R.drawable.ic_launcher);
					} else {
						img.setImageBitmap(photo);
					}
				}
				break;
			case REQUEST_CODE_CAPTURE_CAMEIA:// 當選擇拍照時調用
				photo = BitmapFactory.decodeFile(tempFile.getAbsolutePath());
				img = (ImageView) findViewById(viewId);
				if (photo == null) {
					img.setImageResource(R.drawable.ic_launcher);
				} else {
					img.setImageBitmap(photo);
				}
				break;

			}
			super.onActivityResult(requestCode, resultCode, data);

		}
	}



圖片傳遞 
//把位圖壓縮到輸出流中,然後把輸出流轉換成字節數組,然後再放入Intent中作爲數據傳遞

Bitmap photo = bundle.getParcelable("data");
ByteArrayOutputStream baos = null;
	try {
		baos = new ByteArrayOutputStream();
		photo.compress(Bitmap.CompressFormat.JPEG, 100, baos);
		byte[] photodata = baos.toByteArray();
		System.out.println(photodata.toString());
		Intent intent = new Intent();
		intent.setClass(RegisterActivity.this, ShowActivity.class);
		intent.putExtra("photo", photodata);
		startActivity(intent);
		finish();
		} catch (Exception e) {
			e.getStackTrace();
		} finally {
		if (baos != null) {
		try {
			baos.close();
		} catch (Exception e) {
		e.printStackTrace();
		}
		}
	}

但是,有時候我們會發現用相機拍攝獲取照片的時候,得到的 uri 是 null 的,這是因爲android把拍攝的圖片封裝到bundle中傳遞回來,但是根據不同的機器獲得相片的方式不太一樣,可能有的相機能夠通過  
inten.getData()獲取到uri
然後再根據uri獲取數據的路徑,在封裝成bitmap,但有時候有的相機獲取到的是null的,這時候我們該怎麼辦呢?
其實這時候我們就應該從bundle中獲取數據,通過
(Bitmap) bundle.get("data")
獲取到相機圖片的bitmap數據。
爲了能夠同時適應上述兩種情況,我們這時候就應該在獲取圖片時做判斷了。我們可以在響應的時候做一個判斷:

@Override  
   protected void onActivityResult(int requestCode, int resultCode, Intent data) {  
       if (requestCode == REQUEST_CODE_PICK_IMAGE) {             
               Uri uri = data.getData();  
               //to do find the path of pic by uri  
           
       } else if (requestCode == REQUEST_CODE_CAPTURE_CAMEIA ) {             
       Uri uri = data.getData();  
       if(uri == null){  
           //use bundle to get data  
           Bundle bundle = data.getExtras();    
               if (bundle != null) {                 
               Bitmap  photo = (Bitmap) bundle.get("data"); //get bitmap  
               //spath :生成圖片取個名字和路徑包含類型                              
               saveImage(Bitmap photo, String spath);  
               } else {           
                   Toast.makeText(getApplicationContext(), "err****", Toast.LENGTH_LONG).show();           
                return;        
                }    
       }else{  
                //to do find the path of pic by uri  
       }   
   }  
}  

後面的過程就需要通過bitmap轉化成相應的圖片文件了。不過得到最終的圖片是被壓縮了的。

public static void saveImage(Bitmap photo, String spath) {  
        try {  
            BufferedOutputStream bos = new BufferedOutputStream(  
                    new FileOutputStream(spath, false));  
            photo.compress(Bitmap.CompressFormat.JPEG, 100, bos);  
            bos.flush();  
            bos.close();  
        } catch (Exception e) {  
            e.printStackTrace(); 
        }  
    } 


這樣就能解決照相機取到的圖片uri爲空的狀態了。但是在獲取到uri爲null情況下,如果想得到沒有被壓縮過的照片,也就是說得到的是直接從相機拍攝到的照片怎麼做呢?
其實方式很簡單,在
Intent getImageByCamera = new Intent("android.media.action.IMAGE_CAPTURE");
之後我們直接講文件先保存到指定的路徑filepath,然後直接在
onActivityResult(int requestCode, int resultCode, Intent data)
中把filepath傳遞過去就行了。

private String capturePath = null;  

protected void getImageFromCamera() {  
        String state = Environment.getExternalStorageState();  
        if (state.equals(Environment.MEDIA_MOUNTED)) {  
            Intent getImageByCamera = new Intent("android.media.action.IMAGE_CAPTURE");  
            String out_file_path = Constant.SAVED_IMAGE_DIR_PATH;  
            File dir = new File(out_file_path);  
            if (!dir.exists()) {  
                dir.mkdirs();  
            }  
            capturePath = Constant.SAVED_IMAGE_DIR_PATH + System.currentTimeMillis() + ".jpg";  
            getImageByCamera.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(capturePath)));  
            getImageByCamera.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);  
            startActivityForResult(getImageByCamera, Constant.REQUEST_CODE_CAPTURE_CAMEIA);  
        }  
        else {  
            Toast.makeText(getApplicationContext(), "請確認已經插入SD卡", Toast.LENGTH_LONG).show();  
        }  
    }  

在onActivityResult(int requestCode, int resultCode, Intent data)中我們只要把路徑filepath定義爲全局的變量傳送過來就行了。
這樣得到的圖片是直接從相機中拍攝得到的照片,不會被壓縮了。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章