作業#49 照片編輯App
Published in
Jan 10, 2022
目的:練習製作出照片編輯App以及利用UIGraphicsImageRenderer取得編輯後的照片
這次練習模仿手機版LINE的個人主頁,可以點選要編輯變更背景圖片或大頭照然後變更個性簽名,最後可以將自己的個人主頁的畫面截圖並分享出去,本篇文章主要分享主要功能,完整程式碼歡迎點擊最下方GitHub連結~
功能主要運用
- 利用UIImagePickerViewController使用拍照功能以及PHPickerViewController使用相簿選圖的功能
- 利用CGAffineTransform將圖片鏡像或旋轉
- 利用CIFilter讓圖片有濾鏡效果
- 利用UIGraphicsImageRenderer截下編輯後的圖片
- 利用UIActivityViewController將畫面分享出去
App架構
從個人主頁點選背景圖片或大頭貼,切換到圖片預覽然後點選要拍照或是從相簿內選擇照片,最後進行圖片編輯再用unwindSegue回傳到個人主頁顯示,另外可以點選個性簽名編輯想要的文字或emoji,並一樣回傳顯示到主頁上
選圖功能-UIImagePickerViewController、PHPickerViewController
actionSheet
點選編輯圖片的Button後,會先跳出actionSheet讓使用者選擇拍照還是使用相簿中的照片
UIImagePickerViewController
- 先檢查裝置中有沒有相機功能才執行生成UIImagePickerViewController
- didFinishPickingMediaWithInfo中設定使用者拍下圖片後做什麼事
- 從info[.originalImage]取得拍下圖片並轉型成UIImage,並給previewImage這個變數是要用來傳遞到下一個畫面的變數
- 使用圖片後把UIImagePickerViewController關掉並切換到下一頁
- 但也有可能最後並沒有使用拍到的圖片,那就關掉UIImagePickerViewController
PHPickerViewController
- 設定PHPickerConfiguration,filter設定只選取圖片,然後用設定好的Configuration去初始化一個PHPickerViewController並Present出來
- 使用delegate的function,didFinishPicking處理使用者選擇到的圖片,先檢查使用者是否有選擇圖片,然後讀取UIImage型別的東西,因為loadObject是在背後運作,所以要讓獲取image的工作在main thread執行,並且dismiss掉PHPickerViewController,切換到編輯圖片頁面
- 有可能使用者點開編輯但沒有選擇任何圖片就關掉,因此在判斷是否有選擇到圖片的if let加一個else然後dismiss掉PHPickerViewController
圖片編輯功能-切換比例、旋轉、鏡像、濾鏡效果
view堆疊
- 希望最後能將編輯後的圖片區域整個截圖下來,最下層放一個Draw View負責截下包含他裡面的整個畫面,所以需要將其他的view都放進去成為他的subview
- 負責旋轉以及鏡像功能的view(RotateView&MirrorView),兩個功能各用一個View,不然會無法同時進行
- 最後一個BackView裝負責縮放的scrollView以及ImageView
切換比例
- 用segmentedControl讓使用者選擇比例,所以function的參數裡帶入index以及要變化的view
- defaultLength在負責編輯圖片功能的類別裡已經先設定好了,然後根據不同的比例去變更寬跟高
- 然後將變更後的寬跟高給要變化的view,然後因為要變更比例的view會是最大的draw裡的subview所以代表座標的xy要看的在DrawView裡的位子,那整個View是正方形,所以center剛好是原本寬高的一半,固定center是為了在變更比例後還是停留在中間
旋轉、鏡像
- 旋轉設定一個旋轉次數,每次旋轉都+=1這樣才會一直旋轉下去
- 鏡像圖片這是設定一個負責鏡像的變數1,讓他每次都*=1在1跟-1切換,來預設跟鏡像的切換
濾鏡
濾鏡功能
- function接受兩個參數,傳入要變更的圖片以及濾鏡代表的tag,因為會用button去讓使用者去選擇要替換的濾鏡,這邊就用tag來區分使用者所選擇的濾鏡
- 因為傳入的參數是UIImage?,所以先用guard let去取得,然後將它轉換成CIImage
- 用switch去判斷使用者選擇的濾鏡名稱去初始化一個CIFilter
- 將傳入的圖片變成有濾鏡效果,接著在outputImage可以獲得轉換後的圖片,但這時候獲得的是CIImage,在CIImage轉換回UIImage時會有圖片轉向的問題,所以我們要判斷原圖的方向並把圖片轉向回去,方法下方會分享Peter的文章,對詳細有興趣的歡迎點擊
- 然後轉換回UIImage並回傳
使用濾鏡
- 在controller上使用的function,帶入button的tag作為參數並回傳UIImage?
- 這個function也是在編輯圖片功能的類別裡,這個類別有一個image負責在接受要編輯的圖片作為原圖
- 根據使用者選擇的button去變更濾鏡
截圖-UIGraphicsImageRenderer
- 這個function因為個人主頁也會用到因此我把它寫在extension內
- 傳入要截圖的view,回傳UIImage
- 先告訴UIGraphicsImageRenderer要截圖的位子跟大小,然後用.drawHierarchy去做截圖,然後回傳截下來的UIImage
分享畫面-UIActivityViewController
- 先將整個個人主頁截圖下來
- 初始化UIActivityViewController並讓他分享的是截下來的圖片
- 使用completionWithItemHandler,獲得是否分享成功並跳出alert提醒使用者
操作畫面
濾鏡變更跟利用scrollView縮放圖片,在實機操作沒問題但不知道為什麼模擬機上無法動作🥲
分享到line上
練習心得:
整個作業做完花了四天,中間卡了有點久差點崩潰,還好問了一下Peter後很多問題就解開了,最困難的部分我覺得是調整圖片比例的部分,搞了很久我認為主要對View的操作還不夠熟悉,其實最後發現真的沒有這麼難就是觀念的問題要再多多練習
文章參考連結:
GitHub連結: