RSKImageCropperの使い方とカスタマイズ

# はじめに
こんにちは。
[RSKImageCropper](https://github.com/ruslanskorb/RSKImageCropper)という画像トリミングのObjective-C製のライブラリがあり、今回は**SNSのプロフィール画像の設定**のような実装を**Swift**で行いたかったので書いてみました。
至らぬ点など、コメントなど頂けたら幸いです。

<img src="https://qiita-image-store.s3.amazonaws.com/0/128250/b13f1e6d-dc63-fd86-790b-376063187c6e.gif" width="250">

# 導入について
実行環境は**Swift3.1**/**Xcode8.3.3**で、CocoaPodsを利用しました。

```rb
use_frameworks!

pod 'RSKImageCropper'
```

# サンプルコード
```MainViewController.swift
import UIKit
import RSKImageCropper

class MainViewController: UIViewController {
    
    @IBOutlet weak var imageView: UIImageView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    @IBAction func buttonAction(_ sender: Any) {
        let image = UIImage(named: "img")!
        let imageCropVC = RSKImageCropViewController(image: image, cropMode: .circle)
        imageCropVC.moveAndScaleLabel.text = "切り取り範囲を選択"
        imageCropVC.cancelButton.setTitle("キャンセル", for: .normal)
        imageCropVC.chooseButton.setTitle("完了", for: .normal)
        imageCropVC.delegate = self
        present(imageCropVC, animated: true)
    }
}

extension MainViewController: RSKImageCropViewControllerDelegate {
    //キャンセルを押した時の処理
    func imageCropViewControllerDidCancelCrop(_ controller: RSKImageCropViewController) {
        dismiss(animated: true, completion: nil)
    }
    //完了を押した後の処理
    func imageCropViewController(_ controller: RSKImageCropViewController, didCropImage croppedImage: UIImage, usingCropRect cropRect: CGRect, rotationAngle: CGFloat) {
        dismiss(animated: true)
        imageView.image = croppedImage
    }
}
```

# ライブラリのクラスについて
## 切り取り範囲を操作する(**RSKImageCropViewController**)
以下はRSKImageCropViewControllerのプロパティです。

<img width="250" alt="screen.png" src="https://qiita-image-store.s3.amazonaws.com/0/128250/ef7b08e6-5962-85e2-ddb5-3f5807056d40.png">

|名前|説明|
|:-:|:-:|
|moveAndScaleLabel|上側の説明文になる**(UILabel)**|
|cancelButton|左側のキャンセルとなるボタン**(UIButton)**|
|chooseButton|右側の選択完了となるボタン**(UIButton)**|

## **RSKImageCropViewControllerDelegate**について
```MainViewController.swift
//キャンセルを押した時の処理
func imageCropViewControllerDidCancelCrop(_ controller: RSKImageCropViewController) {

}
//完了を押した瞬間の処理
func imageCropViewController(_ controller: RSKImageCropViewController, willCropImage originalImage: UIImage) {

}
//完了を押した後の処理
func imageCropViewController(_ controller: RSKImageCropViewController, didCropImage croppedImage: UIImage, usingCropRect cropRect: CGRect) { 

}
//完了を押した後に切り取られた矩形や角度を利用する場合の処理
func imageCropViewController(_ controller: RSKImageCropViewController, didCropImage croppedImage: UIImage, usingCropRect cropRect: CGRect, rotationAngle: CGFloat) {

}
```

## 切り取りのモードについて
- RSKImageCropViewControllerのプロパティの`cropMode`で指定します。
- `isRotationEnabled`で回転するかどうかを指定します。

<img width="500" alt="mode.png" src="https://qiita-image-store.s3.amazonaws.com/0/128250/011c24af-58a4-70e8-a8f7-e716814486b6.png">

:warning: `cropMode = .circle`に指定した場合、**実際に切り取られる画像は四角形**になるようで、

- **ただ画像を表示させたいという場合**
> **表示させるView**に対して`layer.cornerRadius`を指定して丸くするなどで対応できるかと思います。

- **画像として円形状のものが欲しい場合**
>  delegateの`usingCropRect`や`croppedImage`などを利用して自分で作成する必要がある?(更に、**rotate**した場合は画像が**四角形かつ不透明な余白**になってしまうため)

<img width="200" alt="none.png" src="https://qiita-image-store.s3.amazonaws.com/0/128250/ad1aeb6c-34c9-fff4-c807-8726a1ffff31.png"> <img width="200" alt="AlphaImage.png" src="https://qiita-image-store.s3.amazonaws.com/0/128250/c3c7b0a7-f263-5061-cecb-408c2f6c2fe5.png"> 

```swift
//完了を押した後の処理
func imageCropViewController(_ controller: RSKImageCropViewController, didCropImage croppedImage: UIImage, usingCropRect cropRect: CGRect) {
    //もし円形で画像を切り取りし、その画像自体を加工などで利用したい場合
    if controller.cropMode == .circle {
        UIGraphicsBeginImageContext(croppedImage.size)
        let layerView = UIImageView(image: croppedImage)
        layerView.frame.size = croppedImage.size
        layerView.layer.cornerRadius = layerView.frame.size.width * 0.5
        layerView.clipsToBounds = true
        let context = UIGraphicsGetCurrentContext()!
        layerView.layer.render(in: context)
        let capturedImage = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()
        let pngData = UIImagePNGRepresentation(capturedImage)!
        //このImageは円形で余白は透過です。
        let png = UIImage(data: pngData)!
    }
}
```

# おわりに
円形での画像の切り取りは、**画像が四角形で返されてしまう事**や、**切り取り範囲が対象の画像よりも大きく切り出した時に、楕円形になってしまい正確には切り出せない事**があるため、もし表示するUIが角丸でも四角形での画像切り取りにしてしまったほうが使いやすいのかもしれません。
また、cropModeにはもう一つのモード**.custom**があり、こちらは`RSKImageCropViewController`を細かく制御できるようなのですが、元画像やズーム率、回転角などを自ら計算する必要があるようで、少し扱いにくいと感じました。ただ、画像切り取りをUIで行えるのはとても良いと思いました。

# 参考にさせていただいた記事
- [【swift】RSKImageCropperを使って画像のトリミング とりあえずphpとか](http://kimagureneet.hatenablog.com/entry/2015/08/19/010120)
- [RSKImageCropper GitHub](https://github.com/ruslanskorb/RSKImageCropper)

見て頂いてありがとうございます。