#Task-11 照片編輯App - PhotoEditor (01 - 拍照&選擇照片)

這次的作業是要做一個可以編輯照片的 App,會分成 4 篇來介紹,第一篇是總覽 & 拍照、選擇照片

用 Storyboard 製作,使用到的功能或方法:

  • AutoLayout、Stack View 排版
  • PHPickerViewController、UIImagePickerController 拍照&選照片
  • Present、Dismiss 顯示&關閉 controller
  • CGAffineTransform 旋轉照片、縮放貼圖及尺寸框
  • UIColorPickerViewController 選文字顏色
  • UIPanGestureRecognizer、UIPinchGestureRecognizer 拖曳、縮放貼圖及尺寸框
  • ScrollView 縮放照片
  • PerformSegue、IBSegueAction、Unwind、Prepare 傳輸資料到下一頁、回傳資料到上一頁
  • CIFilter:CIColorControls 調整亮度、對比、飽和度的 filter
  • CIFilter:CIPhotoEffect- 照片濾鏡 filter
  • CAShapeLayer、UIBezierPath 繪製尺寸框
  • UIGraphicsImageRenderer 儲存圖片
  • UIActivityViewController 分享圖片
  • Delegate、Extension

作業一共用到 4 個 View Controller

⭐️ 呈現的畫面:

⭐️ 實現的功能:

  • 拍照&選照片
  • 旋轉圖片
  • 調整照片亮度、對比、飽和度
  • 濾鏡效果
  • 調整照片比例:正方形、16:9、5:4、7:5、4:3、5:3、3:2
  • 縮放圖片
  • 在照片上加上文字、貼圖
  • 儲存&分享照片

⭐️ 完整操作影片:

⭐️ 拍照功能(僅實機使用,模擬器不能拍照)UIImagePickerController

1. 遵從 UIImagePickerControllerDelegate、UINavigationControllerDelegate

  • 查詢 UIImagePickerController 的定義時可以看到裡面的 delegate 如下,所以兩個都要遵從才行
class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate{
}

2. 撰寫開啟相機的按鈕的 IBAction function

@IBAction func takePhoto(_ sender: Any) {
let controller = UIImagePickerController()
//sourceType設為.camera代表呼叫controller是用來開啟相機
controller.sourceType = .camera
controller.delegate = self
present(controller, animated: true, completion: nil)
}

3. 設定拍完照後執行的 function imagePickerController(_:didFinishPickingMediaWithInfo:)

//拍照後執行的function
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
//儲存點選的照片資訊的property,利用參數info的.originalImage取得圖片相關資料
let photo = info[.originalImage] as? UIImage
self.coverStackView.isHidden = true
//關閉拍照的controller
dismiss(animated: true) {
//photoImage是我用來儲存拍照或相簿選擇的照片的變數
self.photoImage = photo!
//selectedImageView是用來顯示照片的imageView
self.selectedImageView.image = self.photoImage

self.editButton.isHidden = false
}

}

4. 到 App 的 Info 頁面做隱私權限設定,開啟相機時才不會閃退哦!
點任一 + 號新增 key,選擇 Privacy- Camera Usage Description,然後在 Value 中新增提示語,就可以了!

UIImagePickerController 也可以用來從相簿選擇照片,只要在 sourceType 設定改為 .photoLibrary,不過因為後來出現了更強大的 PHPickerViewController,所以官方已經不建議再使用 UIImagePickerController 來選照片,未來 photoLibrary 也會移除

⭐️ 從相簿選擇照片 PHPickerViewController

1. 使用PHPickerViewController 需要 import PhotosUI

import PhotosUI

2. 遵從 PHPickerViewControllerDelegate

class ViewController: UIViewController, PHPickerViewControllerDelegate{
}

3. 撰寫開啟相簿的按鈕的 IBAction function

@IBAction func selectImage(_ sender: Any) {
var configuration = PHPickerConfiguration()
//PHPickerConfiguration可以設定選擇照片或影片,nil則兩種都可以選擇,我們只要選擇照片,所以設定 .images
configuration.filter = .images
let picker = PHPickerViewController(configuration: configuration)
picker.delegate = self
present(picker, animated: true, completion: nil)
}

註:PHPickerConfiguration 預設僅能選擇一張照片,因為我做的 App 一次只針對一張照片編輯,所以沒有額外做照片選擇張數的設定。如果要選擇多張照片,可以參考彼得潘的文章⬇︎

4. 設定選擇完照片後執行的 function picker(_:didFinishPicking:)

func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
//關閉controller
picker.dismiss(animated: true)
//從 PHPickerResult的itemProvider載入選擇的照片
let itemProviders = results.map(\.itemProvider)
//使用者有可能沒有選擇照片,所以用if let先檢查itemProviders.first裡面有沒有值
if let itemProvider = itemProviders.first, itemProvider.canLoadObject(ofClass: UIImage.self){
//previousImage用來儲存本來imageView顯示的照片,以判斷選擇照片時原本的照片是否還是同一張,如果是才將照片替換成選擇的照片
let previousImage = self.photoImage
self.coverStackView.isHidden = true
//載入照片
itemProvider.loadObject(ofClass: UIImage.self) { [weak self] (image, Error) in
DispatchQueue.main.async {

//判斷照片是否仍是同一張
guard let self = self, let image = image as? UIImage, self.photoImage == previousImage else { return }
//變數photoImage儲存選擇的照片
self.photoImage = image
//imageView顯示選擇的照片
self.selectedImageView.image = self.photoImage
self.editButton.isHidden = false
}
}
}
}

第一篇先介紹到這裡,後面待我繼續補上!最後一篇再寫關於這個作業的心得😭

💡 續集們

參考資料

使用的素材

Camera vector created by freepik — www.freepik.com

Planner vector created by freepik — www.freepik.com

Note design vector created by rawpixel.com — www.freepik.com

--

--