[Android] 拍照、截圖、儲存並顯示在ImageView控制項中

來源:互聯網
上載者:User

標籤:android   照相   intent   imageview   onactivityresult   

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

<Button        android:id="@+id/button1"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:text="TakePhoto Button" />   <ImageView        android:id="@+id/imageView1"            android:layout_width="wrap_content"          android:layout_height="wrap_content"        android:layout_gravity="center_horizontal" />

   然後,在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; //圖片名稱
   添加函數實現點擊拍照功能:

@Overrideprotected 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); //設定裁剪參數顯示圖片至ImageViewbreak;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檔案中聲明許可權:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.CAMERA" /> 
     運行結果如所示:

       

    需要注意以下幾個問題:
    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_OKIntent 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

(By:Eastmount 2014-10-23 晚10點
http://blog.csdn.net/eastmount/)

[Android] 拍照、、儲存並顯示在ImageView控制項中

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.