如何剪輯照片

如何剪輯照片

情境

這次要借助這個剪輯照片的第三方,
如何透過ImagePicker(createChooser)取得本地端的照片這篇文章透過Intent去選取照片,
回來的照片我們再進行剪輯。

程式碼說明

布局

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.givemepass.cropimagedemo.MainActivity">

    <Button
        android:id="@+id/pick_photo"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Picker" />
    <ImageView
        android:layout_below="@id/pick_photo"
        android:id="@+id/image"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</RelativeLayout>

一開始先跟使用者要權限

int readPermission = ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE);
int writePermission = ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (readPermission != PackageManager.PERMISSION_GRANTED || writePermission != PackageManager.PERMISSION_GRANTED) {
    //未取得權限,向使用者要求允許權限
    ActivityCompat.requestPermissions(this,
            new String[] {Manifest.permission.READ_EXTERNAL_STORAGE,
                    Manifest.permission.WRITE_EXTERNAL_STORAGE},
            REQUEST_EXTERNAL_STORAGE);
} else{
    getPermissionAccess();
}
//處理回來的權限決定
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
   switch (requestCode) {
       case REQUEST_EXTERNAL_STORAGE: {
           if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
               getPermissionAccess();
           } else {
               finish();
           }
           return;
       }
   }
}



當我們要到權限以後, 就可以透過如何透過ImagePicker(createChooser)取得本地端的照片的例子去取得手機上的照片。

//已有權限,可進行檔案存取
private void getPermissionAccess(){
    picker = (Button) findViewById(R.id.pick_photo);
    imageView = (ImageView) findViewById(R.id.image);
    picker.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Intent picker = new Intent(Intent.ACTION_GET_CONTENT);
            picker.setType("image/*");
            picker.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
            Intent destIntent = Intent.createChooser(picker, null);
            startActivityForResult(destIntent, PICKER);
        }
    });
}

當手機照片路徑傳回來了以後, 就可以透過第三方所提供的類別進行剪輯

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == PICKER) {
        if (resultCode == Activity.RESULT_OK) {
            Uri uri = data.getData();
            String path = getPath(MainActivity.this, uri);
            CropDialog mCropDialog = new CropDialog(MainActivity.this, path);
            mCropDialog.setOnCropFinishListener(new CropDialog.OnCropFinishListener() {
                @Override
                public void onCrop(String path) {
                    Bitmap bmp = BitmapFactory.decodeFile(path);
                    imageView.setImageBitmap(bmp);
                }
            });
            mCropDialog.show();
        }
    }
}

我們可以看到有新增一個CropDialog專門來處理剪輯照片。


在使用CropImageView上其實非常簡單, 只需要在xml上宣告這個view

<com.example.givemepass.cropimagedemo.CropImageView
    android:id="@+id/crop_img"
    android:layout_below="@id/pick_image_top_bar"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

一開始先透過setDrawable設定大小 設定為300*300

private void init(){
    mCropImage = (CropImageView) findViewById(R.id.crop_img);
    mBack = (ImageView) findViewById(R.id.pick_image_back);
    mCropCheck = (ImageView) findViewById(R.id.pick_image_select_check);
    mCropImage.setDrawable(mPath, 300, 300);
    setListener();
}

可以縮小


可以放大

接著當切割完畢以後, 就可以按下確定的按鈕
縮小


進行照片的儲存, 並且關閉這個Dialog。

mCropCheck.setOnClickListener(new View.OnClickListener(){
    @Override
    public void onClick(View v) {
        Executors.newSingleThreadExecutor().submit(new Runnable() {
            @Override
            public void run() {
                final String path = mContext.getExternalFilesDir(Environment.DIRECTORY_PICTURES) + "/crop.png";
                FileUtil.writeImage(mCropImage.getCropImage(), path, 100);
                ((Activity)mContext).runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        if(mOnCropFinishListener != null){
                            mOnCropFinishListener.onCrop(path);
                        }
                        dismiss();
                    }
                });
            }
        });
    }
});

回到我們剛剛呼叫Dialog的地方,
有寫一個Listener用來回傳處理完圖片的路徑。

CropDialog mCropDialog = new CropDialog(MainActivity.this, path);
mCropDialog.setOnCropFinishListener(new CropDialog.OnCropFinishListener() {
    @Override
    public void onCrop(String path) {
        Bitmap bmp = BitmapFactory.decodeFile(path);
        imageView.setImageBitmap(bmp);
    }
});

這樣一來就可以看到被剪輯過後的照片。
縮小

github