I made a processing app with Swift!
The overview is as follows.
First create a project, move to Main.storyboard, then place the View, UIImageView, and buttons. First, View up, right, left 0, height 200. Next, I will put the UIImageView inside the View, but please do whatever you like with the layout. The buttons below are just placed in an atmosphere, so please customize them as you like. Also, the image is pasted on the UIImageView in an atmosphere, but it looks like a blank unless you set something, so it is easier to understand if you set something.
Next, connect each part with IBOutlet.
Viewcontroler.swift
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var photo: UIImageView!
@IBOutlet weak var shareButton: UIButton!
//Selected image
var selectedImage: UIImage?
override func viewDidLoad() {
super.viewDidLoad()
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.handleSelectPhoto))
photo.addGestureRecognizer(tapGesture)
photo.isUserInteractionEnabled = true
}
@IBAction func shareButton_TouchUpInside(_ sender: Any) {
view.endEditing(true)
}
@objc func handleSelectPhoto() {
let pickerController = UIImagePickerController()
pickerController.delegate = self
pickerController.allowsEditing = true
present(pickerController, animated: true, completion: nil)
}
}
extension ViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
guard let image = info[.editedImage] as? UIImage else { return }
self.selectedImage = image
photo.layer.masksToBounds = true
photo.clipsToBounds = true
photo.image = image
dismiss(animated: true, completion: nil)
}
}
I want to connect UIImageView to photo and use the image when selected
Viewcontroller.swift
//Selected image
var selectedImage: UIImage?
Is defined as. After that, tap detection is performed with viewDidLoad and UIImagePickerController () is called. Then, in the extension, the image selected by didFinishPickingMediaWithInfo is saved as a photo. Check out the code around here.
When you can set a photo, we will create a screen to select Filter. Create a new view controller and use it as a FilterViewController. Then set Present Mordally from Viewcontroller to FilterViewController. Please define "filter_segue" for the created segue. It will be used when transitioning later. Next, put the parts in the FilterViewController. As shown in the picture, first place a new View on top, and then place the Cancel button and Next button on that View, respectively. Then place the UIImageView under the View above. The image selected in the view controller is reflected in this. Finally, put the CollectionView under the UIImageView and keep it a little further away. Also in this Collection View Place UIImageView and select the image to process here. After putting it, look at the Scroll View of the Collection View. ・ Show Horizontal Indicator ・ Show Vertical Indicator Please uncheck the two. This allows you to express the horizontal slide UI that is often used in processing apps.
After placing the necessary parts, set the delegate and datasource individually. And since a new class is required for the cell of CollectionView, create "FilterCollectionViewCell.swift" that inherits UICollectionViewCell again.
FilterCollectionViewCell.swift
import UIKit
class FilterCollectionViewCell: UICollectionViewCell {
@IBOutlet weak var filterPhoto: UIImageView!
}
Only the UICollectionView inside the CollectionView is fine here.
I will actually make it from here, but for the time being, I will put all the code first, so if you understand it, you can copy it all, but for those who do not understand, I will explain in order from the top.
FilterViewController.swift
import UIKit
protocol FilterViewControllerDelegate {
func updatePhoto(image: UIImage)
}
class FilterViewController: UIViewController {
@IBOutlet weak var collectionView: UICollectionView!
@IBOutlet weak var filterPhoto: UIImageView!
var delegate: FilterViewControllerDelegate?
var selectedImage: UIImage!
var CIFilterNames = [
"CIPhotoEffectChrome",
"CIPhotoEffectFade",
"CIPhotoEffectInstant",
"CIPhotoEffectNoir",
"CIPhotoEffectProcess",
"CIPhotoEffectTonal",
"CIPhotoEffectTransfer",
"CISepiaTone"
]
override func viewDidLoad() {
super.viewDidLoad()
filterPhoto.image = selectedImage
filterPhoto.contentMode = .scaleAspectFill
}
@IBAction func cancelBtn_TouchUpInside(_ sender: Any) {
dismiss(animated: true, completion: nil)
}
@IBAction func nextBtn_TouchUpInside(_ sender: Any) {
dismiss(animated: true, completion: nil)
delegate?.updatePhoto(image: self.filterPhoto.image!)
}
func resizeImage(image: UIImage, newWidth: CGFloat) -> UIImage {
let scale = newWidth / image.size.width
let newHeight = image.size.height * scale
UIGraphicsBeginImageContext(CGSize(width: newWidth, height: newHeight))
image.draw(in: CGRect(x: 0, y: 0, width: newWidth, height: newHeight))
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage!
}
}
extension FilterViewController: UICollectionViewDelegate, UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return CIFilterNames.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "FilterCollectionViewCell", for: indexPath) as! FilterCollectionViewCell
let context = CIContext(options: nil)
let newImage = resizeImage(image: selectedImage, newWidth: 150)
let ciImage = CIImage(image: newImage)
let filter = CIFilter(name: CIFilterNames[indexPath.item])
filter?.setValue(ciImage, forKey: kCIInputImageKey)
if let filteredImage = filter?.value(forKey: kCIOutputImageKey) as? CIImage {
let result = context.createCGImage(filteredImage, from: filteredImage.extent)
cell.filterPhoto.image = UIImage(cgImage: result!)
}
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let context = CIContext(options: nil)
let ciImage = CIImage(image: selectedImage)
let filter = CIFilter(name: CIFilterNames[indexPath.item])
filter?.setValue(ciImage, forKey: kCIInputImageKey)
if let filteredImage = filter?.value(forKey: kCIOutputImageKey) as? CIImage {
let result = context.createCGImage(filteredImage, from: filteredImage.extent)
self.filterPhoto.image = UIImage(cgImage: result!)
}
}
}
FilterViewController Outlet connection I
FilterCollectionView.swift
@IBOutlet weak var collectionView: UICollectionView!
@IBOutlet weak var filterPhoto: UIImageView!
@IBAction func cancelBtn_TouchUpInside(_ sender: Any) {
dismiss(animated: true, completion: nil)
}
@IBAction func nextBtn_TouchUpInside(_ sender: Any) {
dismiss(animated: true, completion: nil)
delegate?.updatePhoto(image: self.filterPhoto.image!)
}
I left it as. CancelButton returns to the previous screen, and NextButton reflects the image selected in the cell below to the view controller.
Next, define the properties used by the FilterViewController.
FilterCollectionView.swift
var selectedImage: UIImage!
var CIFilterNames = [
"CIPhotoEffectChrome",
"CIPhotoEffectFade",
"CIPhotoEffectInstant",
"CIPhotoEffectNoir",
"CIPhotoEffectProcess",
"CIPhotoEffectTonal",
"CIPhotoEffectTransfer",
"CISepiaTone"
]
You don't have to say selectedImage anymore, but CIFilterNames below should not be mistaken for any lowercase and uppercase letters. This time I will use only 8 types. The CI ~ described here is defined in Apple's Core Image Filter Reference guide. I want to use these in cells, so I'll put them in an array. It doesn't matter what is written separately, and 8 or more types are fine. Please add each as you like. Reference: Core Image Filter Reference
After adding, reflect the image selected in the previous (View Controller) with viewDidLoad so that all can be seen. Then, create a function for processing to be used in the cell.
FilterCollectionView.swift
override func viewDidLoad() {
super.viewDidLoad()
filterPhoto.image = selectedImage
filterPhoto.contentMode = .scaleAspectFill
}
func resizeImage(image: UIImage, newWidth: CGFloat) -> UIImage {
let scale = newWidth / image.size.width
let newHeight = image.size.height * scale
UIGraphicsBeginImageContext(CGSize(width: newWidth, height: newHeight))
image.draw(in: CGRect(x: 0, y: 0, width: newWidth, height: newHeight))
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage!
}
numberOfItemsInSection counts the number of CIFilterNames. I'm counting 8 here. In cellForItemAt, set while using FilterCollectionViewCell. In newImage, the size is adjusted using the resizeImage function defined above, and a new Filter image is set for each cell. In ciImage, the image selected for filtering is set to CIImage. And ciImage is set as many as CIFilterNames in filter. After that, I created a new CGImage, made it a UIImage, and set it in the cell. didSelectItemAt is the same process.
FilterCollectionView.swift
extension FilterViewController: UICollectionViewDelegate, UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return CIFilterNames.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "FilterCollectionViewCell", for: indexPath) as! FilterCollectionViewCell
let context = CIContext(options: nil)
let newImage = resizeImage(image: selectedImage, newWidth: 150)
let ciImage = CIImage(image: newImage)
let filter = CIFilter(name: CIFilterNames[indexPath.item])
filter?.setValue(ciImage, forKey: kCIInputImageKey)
if let filteredImage = filter?.value(forKey: kCIOutputImageKey) as? CIImage {
let result = context.createCGImage(filteredImage, from: filteredImage.extent)
cell.filterPhoto.image = UIImage(cgImage: result!)
}
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let context = CIContext(options: nil)
let ciImage = CIImage(image: selectedImage)
let filter = CIFilter(name: CIFilterNames[indexPath.item])
filter?.setValue(ciImage, forKey: kCIInputImageKey)
if let filteredImage = filter?.value(forKey: kCIOutputImageKey) as? CIImage {
let result = context.createCGImage(filteredImage, from: filteredImage.extent)
self.filterPhoto.image = UIImage(cgImage: result!)
}
}
}
It seems like it's over when you reach this point, but as it is, the image selected by processing will not be reflected in the view controller. Therefore, I will define a new protocol.
FilterViewController.swift
protocol FilterViewControllerDelegate {
func updatePhoto(image: UIImage)
}
Define delegate properties to use this protocol.
FilterViewController.swift
var delegate: FilterViewControllerDelegate?
Since I want to pass this delegate to the view controller for the selected image after processing, I will pass it through the delegate with the Next button.
FilterViewController.swift
@IBAction func nextBtn_TouchUpInside(_ sender: Any) {
dismiss(animated: true, completion: nil)
delegate?.updatePhoto(image: self.filterPhoto.image!)
}
Finally, add the following processing to ViewController.swift. This will reflect the selected image.
ViewController.swift
extension ViewController: FilterViewControllerDelegate {
func updatePhoto(image: UIImage) {
self.photo.image = image
}
}
This is my first post. The content of this processing app was created from the Udemy course below.
https://www.udemy.com/course/build-instagram-to-master-swift-and-firebase/
Overseas courses are difficult, but the quality is very high, so I highly recommend it. No one has posted how to make a processing application, so I introduced it. I think that if you modify it further, you can make a commercial level application. You should know that it's not that difficult. I hope it will be useful for beginners who are interested in how to make a processing application.
From now on, if there is content that no one has posted yet, I will introduce it at the same time as the output each time. Thank you.
Recommended Posts