1. 程式人生 > >Android拍照及裁剪實現

Android拍照及裁剪實現

一.概述

拍照以及裁剪功能在有些專案中還是經常能遇到的,一般而言,使用拍照和裁剪功能基本上都是使用系統自帶的Intent來實現,看起來很簡單,但是其中還是有一些問題需要注意的。
這裡我們要實現一個功能,點選Button啟動系統相機,拍照後將照片顯示到按鈕下方的ImageView中。

二.基本知識講解

先看看拍照和裁剪對應的動作;
拍照:
MediaStore.ACTION_IMAGE_CAPTURE
裁剪:
com.android.camera.action.CROP

下面看一下裁剪時用的一些引數:

這裡寫圖片描述

這些引數是選擇性的使用的,可以根據你的需求來選擇,這些引數裡面,
我重點講一下return-data,MediaStore.EXTRA_OUTPUT這兩個引數。
return-data:這裡我會將這個引數一直設定為false,因為如果設定為true,就無法將得到的圖片設定給我們的ImageView了,所以我們使用Uri來輸出。

1.僅拍照

首先因為我們要使用sd卡路徑,所以先新增許可權:

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/

然後構建一個圖片地址的Uri:

imageuri = Uri.fromFile(createImageFile(".jpg"));

下面是建立Uri的方法的程式碼:

  private File createImageFile(String prefix) {
        File image = null;
        String timeStamp = new
SimpleDateFormat("yyyy_MM_dd_hh_MM_ss") .format(new Date()); String imageName = prefix+"_JPEG_" + timeStamp + "_"; File imageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES); try { image = File.createTempFile(imageName, ".jpg", imageDir); } catch
(IOException e) { image = null; e.printStackTrace(); } return image; }

然後通過Intent來啟動照相機,設定引數:

Intent intent = null;  
intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);  
intent.putExtra("return-data", false);  
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);  
intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());  
intent.putExtra("noFaceDetection", true);  
startActivityForResult(intent, ACTION_TAKE);

大家可能對return-data和MediaStore.EXTRA_OUTPUT的作用有些迷糊;

return-data:是將結果儲存在data中返回,在onActivityResult中,直接呼叫intent.getdata()就可以獲取值了,這裡設為fase,就是不讓它儲存在data中,

MediaStore.EXTRA_OUTPUT:由於我們不讓它儲存在Intent的data域中,但我們總要有地方來儲存我們的圖片啊,這個引數就是轉移儲存地址的,對應Value中儲存的URI就是指定的儲存地址。

在onActivityResult()中接收:

  @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if(resultCode!= Activity.RESULT_OK){
            Toast.makeText(this, "失敗", Toast.LENGTH_SHORT).show();
            return;
        }
        switch (requestCode){
            case ACTION_TAKE:
               Bitmap bitmap =   BitmapFactory.decodeStream(getContentResolver().openInputStream(bitmap));
                    imageView.setImageBitmap(bitmap);
                break;
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                }
                break;
        }

我們接收到Bitmap以後設定給ImageView,但是在有的手機上並不會顯示出來,我們去看目錄下的檔案的確實產生了,那為什麼會不顯示呢,因為圖片太大了,超出ImageView的顯示範圍。所以一般如果要顯示的話,需要裁剪一下。

2。拍照並裁剪

首先宣告兩個Uri,一個儲存拍照的結果,一個儲存裁剪的結果:

 imageuri = Uri.fromFile(createImageFile("jpg"));
        cropuri = Uri.fromFile(createImageFile("temp"));

點選按鈕時僅調起拍照Intent,將結果存在imageUri中

Intent intent = null;  
intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);  
intent.putExtra("return-data", false);  
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);  
intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());  
intent.putExtra("noFaceDetection", true);  
startActivityForResult(intent, ACTION_TAKE);

在接收到返回的訊息後,調起裁剪Intent:

   @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if(resultCode!= Activity.RESULT_OK){
            Toast.makeText(this, "失敗", Toast.LENGTH_SHORT).show();
            return;
        }
        switch (requestCode){
            case ACTION_TAKE:
                cropImage(imageuri);
                break;
        }
    }
  public void cropImage(Uri uri){
        Intent intent = new Intent("com.android.camera.action.CROP");
        intent.setDataAndType(uri, "image/*");
        intent.putExtra("crop", "true");
        intent.putExtra("aspectX", 1);
        intent.putExtra("aspectY", 1);
        intent.putExtra("outputX", 700);
        intent.putExtra("outputY", 700);
        intent.putExtra("return-data", false);
        intent.putExtra(MediaStore.EXTRA_OUTPUT, cropuri);
        intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
        intent.putExtra("noFaceDetection", true);
        startActivityForResult(intent, ACTION_CROP);
    }

將傳進去的uri做為源資料,即被裁剪的資料,將結果儲存在imageCropUri中,最後在onActivityResult中接受:

  @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if(resultCode!= Activity.RESULT_OK){
            Toast.makeText(this, "失敗", Toast.LENGTH_SHORT).show();
            return;
        }
        switch (requestCode){
            case ACTION_TAKE:
                cropImage(imageuri);
                break;
            case ACTION_CROP:
                try {
                  Bitmap bitmap =   BitmapFactory.decodeStream(getContentResolver().openInputStream(cropuri));
                    imageView.setImageBitmap(bitmap);
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                }
                break;
        }
    }

這樣就可以正常將結果顯示到ImageView了