Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> [Android] 拍照、截圖、保存並顯示在ImageView控件中

[Android] 拍照、截圖、保存並顯示在ImageView控件中

編輯:關於Android編程

最近在做Android的項目,其中部分涉及到圖像處理的內容.這裡先講述如何調用Camera應用程序進行拍照,並截圖和保存顯示在ImageView控件中以及遇到的困難和解決方法.
PS:作者購買了本《Android第一行代碼 著:郭霖》,參照裡面的內容完成(推薦該書,前面的布局及應用非常不錯).網上這類資料非常多,作者僅僅分享給初學者同時在線記錄些內容,希望對大家有所幫助.
首先,設置activity_main.xml為LinearLayout布局且 android:orientation=vertical

 

然後,在MainActivity.java文件中public class MainActivity extends Activity修改源代碼.添加自定義變量:

 

//自定義變量
public static final int TAKE_PHOTO = 1;
public static final int CROP_PHOTO = 2;
private Button takePhotoBn;
private ImageView showImage;
private Uri imageUri; //圖片路徑
private String filename; //圖片名稱
添加函數實現點擊拍照功能:

 

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    takePhotoBn = (Button) findViewById(R.id.button1);
    showImage = (ImageView) findViewById(R.id.imageView1);
    //點擊Photo Button按鈕照相
    takePhotoBn.setOnClickListener(new OnClickListener() {
    	@Override
    	public void onClick(View v) {
    		//圖片名稱 時間命名
    		SimpleDateFormat format = new SimpleDateFormat(yyyyMMddHHmmss);
            Date date = new Date(System.currentTimeMillis());
            filename = format.format(date);
    		//創建File對象用於存儲拍照的圖片 SD卡根目錄           
    		//File outputImage = new File(Environment.getExternalStorageDirectory(),test.jpg);
    		//存儲至DCIM文件夾
    		File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);  
    		File outputImage = new File(path,filename+.jpg);
    		try {
    			if(outputImage.exists()) {
     				outputImage.delete();
    			}
    			outputImage.createNewFile();
    		} catch(IOException e) {
    			e.printStackTrace();
    		}
    		//將File對象轉換為Uri並啟動照相程序
    		imageUri = Uri.fromFile(outputImage);
    		Intent intent = new Intent(android.media.action.IMAGE_CAPTURE); //照相
    		intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri); //指定圖片輸出地址
    		startActivityForResult(intent,TAKE_PHOTO); //啟動照相
    		//拍完照startActivityForResult() 結果返回onActivityResult()函數
    	}
    });

    if (savedInstanceState == null) {
        getFragmentManager().beginTransaction()
                .add(R.id.container, new PlaceholderFragment())
                .commit();
    }
}
通過startActivityForResult和onActivityResult方法實現拍照截圖和保存功能:

 

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
	super.onActivityResult(requestCode, resultCode, data);
	if (resultCode != RESULT_OK) { 
		Toast.makeText(MainActivity.this, ActivityResult resultCode error, Toast.LENGTH_SHORT).show();
		return; 
	}
	switch(requestCode) {
	case TAKE_PHOTO:
		Intent intent = new Intent(com.android.camera.action.CROP); //剪裁
		intent.setDataAndType(imageUri, image/*);
		intent.putExtra(scale, true);
		//設置寬高比例
		intent.putExtra(aspectX, 1);
        intent.putExtra(aspectY, 1);
        //設置裁剪圖片寬高
        intent.putExtra(outputX, 340);
	    intent.putExtra(outputY, 340);
		intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
		Toast.makeText(MainActivity.this, 剪裁圖片, Toast.LENGTH_SHORT).show();
		//廣播刷新相冊 
	    Intent intentBc = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
		intentBc.setData(imageUri);     
		this.sendBroadcast(intentBc);    
		startActivityForResult(intent, CROP_PHOTO); //設置裁剪參數顯示圖片至ImageView
		break;
	case CROP_PHOTO:
		try {	 
			//圖片解析成Bitmap對象
			Bitmap bitmap = BitmapFactory.decodeStream(
					getContentResolver().openInputStream(imageUri));
			Toast.makeText(MainActivity.this, imageUri.toString(), Toast.LENGTH_SHORT).show();
			showImage.setImageBitmap(bitmap); //將剪裁後照片顯示出來
		} catch(FileNotFoundException e) {
			e.printStackTrace();
		}
		break;
	default:
		break;
	}
}

由於涉及到SD卡中寫數據操作和Camera操作,需要在AndroidMainfest.xml文件中聲明權限:

 


 
運行結果如下圖所示:

 

 

data-cke-saved-src=https://www.android5.online/Android/UploadFiles_5356/201702/2017022316264125.png data-cke-saved-src=https://www.android5.online/Android/UploadFiles_5356/201702/2017022316264130.png

需要注意以下幾個問題:
1.拍照和截圖都涉及到startActivityForResult和onActivityResult的交互操作.

 

startActivityForResult(
	Intent intent,   //Intent對象
	int requestCode  //>=0 當Activity結束時requestCode將歸還在onActivityResult()中
)
onActivityResult(
	int requestCode,  //提供給onActivityResult,以確認返回的數據是從哪個Activity返回的
	int resultCode,   //由子Activity通過其setResult()方法返回 通常為RESULT_CANCELED或RESULT_OK
	Intent data       //一個Intent對象,帶有返回的數據
)

其中onActivityResult的requestCode和startActivityForResult中的requestCode相對應.同時結合Intent意圖實現拍照和截圖,核心代碼如下:(intent的參數設置省略)
Intent intent = new Intent(android.media.action.IMAGE_CAPTURE);
startActivityForResult(intent,TAKE_PHOTO);
Intent intent = new Intent(com.android.camera.action.CROP);
startActivityForResult(intent, CROP_PHOTO);
2.使用Android拍照保存在系統相冊,圖庫不能立刻顯示最新照片.解決方法是發送系統內置的廣播去刷新相冊實現顯示.代碼如下:

Intent intentBc = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
intentBc.setData(imageUri);     
this.sendBroadcast(intentBc);    

可能你會使用下面這條廣播掃描整個SD卡,但4.4已禁止這樣的操作:
sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse(...)))
參考資料 http://blog.csdn.net/xiaanming/article/details/8990627
3.當運行程序是可能會發現結果圖像顯示很小,當通過一個Intent意圖觸發時,Camera程序不會將全尺寸圖像返回給主調活動,這樣需要大量的內存,而移動設備內存會有一定限制.通常Camera將在返回的意圖中返回一幅很小的縮略圖,大圖可能會導致OOM問題.參考:《Android多媒體開發高級編程 著:Shawn Van Every》
針對大圖像Android提供BitmapFactory類,允許通過各種資源加載Bitmap圖像.調用BitmapFactory.Options類可以定義如何將Bitmap讀入內存,當加載圖像時,可設置BitmapFactory采樣大小.並指定inSampleSize參數表明加載時結果Bitmap圖像所占的比例.如inSampleSize=8表明產生一副大小為原始圖像1/8的圖像.參考下面代碼:

if(resultCode==RESULT_OK) {
	DisplayMetrics dm = new DisplayMetrics();
	getWindowManager().getDefaultDisplay().getMetrics(dm);
	int width = dm.widthPixels; //寬度
	int height = dm.heightPixels ; //高度
	//加載圖像尺寸而不是圖像本身
	BitmapFactory.Options bmpFactoryOptions = new BitmapFactory.Options();
	bmpFactoryOptions.inJustDecodeBounds = true; //bitmap為null 只是把圖片的寬高放在Options裡
	int heightRatio = (int)Math.ceil(bmpFactoryOptions.outHeight/(float)height);
	int widthRatio = (int)Math.ceil(bmpFactoryOptions.outWidth/(float)width);
	//設置圖片壓縮比例 如果兩個比例大於1 圖像一邊將大於屏幕
	if(heightRatio>1&&widthRatio>1) {
		if(heightRatio>widthRatio) {
			bmpFactoryOptions.inSampleSize = heightRatio;
		}
		else {
			bmpFactoryOptions.inSampleSize = widthRatio;
		}
	}
	//圖像真正解碼
	bmpFactoryOptions.inJustDecodeBounds = false;
	Bitmap bitmap = BitmapFactory.decodeFile(imageUri.toString(), bmpFactoryOptions);
	showImage.setImageBitmap(bitmap); //將剪裁後照片顯示出來	
}

4.使用nexus 4 剪裁圖片後不能setImageBitmap顯示在ImageView控件中,其中只有保存按鈕,沒有剪裁按鈕.測試發現沒有返回RESULT_OK.這個問題不能解決.Why?
參考:Unable to Save Photo Edits
最後希望文章對大家有所幫助,這是我學習Android圖像處理部分的基礎性文章與解決過程.

參考資料和推薦博文:(都是非常不錯的資料-.-)
《Android第一行代碼》著郭霖 參考8.3 調用攝像頭和相冊
android拍照圖片選取與圖片剪裁 By:Lee_Allen
Android_照相機Camera_調用系統照相機返回data為空 By:strawberry2013
Android圖片剪裁功能實心詳解 By:小馬
Android開發 拍照、圖片集保存照片技巧
Android 拍照並顯示在ImageView中(進階) By:leesa
android調動系統的照相機並把照片顯示在ImageView上
cameraintent data null in onActivityResult(int requestCode, int resultCode, Intentdata)
Android高效加載大圖、多圖解決方案,有效避免程序OOM By:guolin
Android相機、相冊獲取圖片顯示並保存到SD卡 By:唐韌_Ryan
android、獲取本地圖片|直接獲取照相圖片 By:zcljy0318

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved