[iOS] J'ai essayé de créer une application de traitement de type insta avec Swift

J'ai créé une application de traitement avec Swift!

L'aperçu est le suivant. 加工アプリ.gif

  1. Définissez l'image

Tout d'abord, créez un projet, déplacez-le vers Main.storyboard, puis placez les boutons View, UIImageView et. Tout d'abord, vue vers le haut, droite, gauche 0, hauteur 200. Ensuite, je vais mettre l'UIImageView dans la vue, mais veuillez faire ce que vous voulez avec la mise en page. Les boutons ci-dessous sont juste placés dans une atmosphère, alors veuillez les personnaliser à votre guise. De plus, je mets l'image sur UIImageView dans une atmosphère, mais cela ressemble à un blanc à moins que je ne règle quelque chose, il est donc plus facile de comprendre si je définis quelque chose.

スクリーンショット 2020-11-03 10.19.18.jpg

Ensuite, connectez chaque pièce avec IBOutlet.

Viewcontroler.swift


import UIKit

class ViewController: UIViewController {
    
    @IBOutlet weak var photo: UIImageView!
    @IBOutlet weak var shareButton: UIButton!
    
    //Image sélectionnée
    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)
    }

}


Je souhaite connecter UIImageView à la photo et utiliser l'image sélectionnée.

Viewcontroller.swift


    //Image sélectionnée
    var selectedImage: UIImage?

Est défini comme. Après cela, la détection de tap est effectuée avec viewDidLoad et UIImagePickerController () est appelée. Ensuite, dans l'extension, l'image sélectionnée par didFinishPickingMediaWithInfo est stockée en photo. Consultez le code ici.

  1. Créer un écran de filtre

Lorsque vous pouvez définir une photo, nous créerons un écran pour sélectionner Filtre. Créez un nouveau contrôleur de vue et utilisez-le comme FilterViewController. Définissez ensuite Present Mordally de Viewcontroller sur FilterViewController. Veuillez définir "filter_segue" pour la séquence créée. Il sera utilisé lors de la transition ultérieure. Ensuite, placez les pièces dans FilterViewController. Comme le montre l'image, placez d'abord une nouvelle vue en haut, puis placez respectivement le bouton Annuler et le bouton Suivant sur cette vue. Placez ensuite l'UIImageView sous la vue ci-dessus. L'image sélectionnée dans le contrôleur de vue y est reflétée. Enfin, placez CollectionView sous UIImageView et gardez-le un peu plus loin. Également dans cette vue de collection Placez le UIImageView et sélectionnez l'image à traiter ici. Après l'avoir placé, regardez la vue de défilement de la vue de collection. ・ Afficher l'indicateur horizontal ・ Afficher l'indicateur vertical Veuillez décocher les deux. Avec cela, vous pouvez exprimer l'interface utilisateur de la diapositive horizontale qui est souvent utilisée dans le traitement des applications. スクリーンショット 2020-11-03 21.44.19.jpg

Après avoir placé les pièces nécessaires, définissez le délégué et la source de données individuellement. Et comme une nouvelle classe est requise pour la cellule de CollectionView, créez "FilterCollectionViewCell.swift" qui hérite à nouveau de UICollectionViewCell. スクリーンショット 2020-11-03 20.04.15.jpg

FilterCollectionViewCell.swift


import UIKit

class FilterCollectionViewCell: UICollectionViewCell {
    
    @IBOutlet weak var filterPhoto: UIImageView!
}

Ici, seul UICollectionView dans CollectionView convient.

  1. Créez une application de traitement![Capture d'écran 2020-11-03 20.38.24.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/848369/92166900- 05fa-13b4-e766-27ba042e6ad3.jpeg)

Je vais en fait le faire à partir d'ici, mais pour le moment, je vais mettre tout le code en premier, donc si vous le comprenez, vous pouvez tout copier, mais pour ceux qui ne comprennent pas, je vais vous expliquer dans l'ordre du haut.

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!)
        }

    }
}

Connexion de sortie du FilterViewController 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!)
}

Je l'ai laissé comme. CancelButton revient à l'écran précédent et NextButton reflète l'image sélectionnée dans la cellule ci-dessous vers le contrôleur de vue.

Ensuite, définissez les propriétés utilisées par FilterViewController.

FilterCollectionView.swift


    var selectedImage: UIImage!
    var CIFilterNames = [
        "CIPhotoEffectChrome",
        "CIPhotoEffectFade",
        "CIPhotoEffectInstant",
        "CIPhotoEffectNoir",
        "CIPhotoEffectProcess",
        "CIPhotoEffectTonal",
        "CIPhotoEffectTransfer",
        "CISepiaTone"
    ]

Vous n'avez plus besoin de dire selectedImage, mais CIFilterNames ci-dessous ne doit pas être confondu avec des minuscules ou des majuscules. Cette fois, je n'utiliserai que 8 types. Le CI ~ décrit ici est défini dans le guide de référence Apple Core Image Filter. Je veux les utiliser dans des cellules, je vais donc les mettre dans un tableau. Peu importe ce qui est écrit séparément, et 8 types ou plus conviennent. Veuillez ajouter chacun comme vous le souhaitez. Référence: Core Image Filter Reference

Après l'ajout, reflétez l'image sélectionnée dans le précédent (Contrôleur de vue) avec viewDidLoad afin que tout puisse être vu. Ensuite, créez une fonction de traitement à utiliser dans la cellule.

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 compte le nombre de CIFilterNames. Je compte 8 ici. Dans cellForItemAt, définissez lors de l'utilisation de FilterCollectionViewCell. Dans newImage, la taille est ajustée à l'aide de la fonction resizeImage définie ci-dessus et une nouvelle image de filtre est définie pour chaque cellule. Dans ciImage, l'image sélectionnée pour le filtrage est définie sur CIImage. Et ciImage est défini autant que CIFilterNames dans le filtre. Après cela, j'ai créé une nouvelle CGImage, en ai fait une UIImage et l'ai définie dans la cellule. didSelectItemAt est le même processus.

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!)
        }

    }
}

C'est presque terminé lorsque vous atteignez ce point, mais tel quel, l'image traitée et sélectionnée ne sera pas reflétée dans le contrôleur de vue. Par conséquent, je définirai un nouveau protocole.

FilterViewController.swift


protocol FilterViewControllerDelegate {
    func updatePhoto(image: UIImage)
}

Définissez les propriétés des délégués pour utiliser ce protocole.

FilterViewController.swift


var delegate: FilterViewControllerDelegate?

Je veux transmettre ce délégué au contrôleur de vue pour l'image sélectionnée après le traitement, cliquez donc sur le bouton Suivant pour le faire passer par le délégué.

FilterViewController.swift


@IBAction func nextBtn_TouchUpInside(_ sender: Any) {
        dismiss(animated: true, completion: nil)
        delegate?.updatePhoto(image: self.filterPhoto.image!)
}

Enfin, ajoutez le traitement suivant à ViewController.swift. Cela reflétera l'image sélectionnée.

ViewController.swift


extension ViewController: FilterViewControllerDelegate {
    func updatePhoto(image: UIImage) {
        self.photo.image = image
    }
}

  1. À la fin

Ceci est mon premier message posté. Le contenu de cette application de traitement a été créé à partir du cours Udemy suivant.

https://www.udemy.com/course/build-instagram-to-master-swift-and-firebase/

Les cours à l'étranger sont difficiles, mais la qualité est très élevée, donc je le recommande vivement. Personne n'a publié comment faire une demande de traitement, alors je l'ai présenté. Je pense que si vous le modifiez davantage, vous pouvez faire une application de niveau commercial. Vous devez savoir que ce n'est pas si difficile. J'espère que cela sera utile pour les débutants qui sont intéressés par la façon de faire une application de traitement.

Désormais, s'il y a du contenu que personne n'a encore publié, je le présenterai en même temps que la sortie à chaque fois. Merci.

Recommended Posts

[iOS] J'ai essayé de créer une application de traitement de type insta avec Swift
J'ai créé une application d'apprentissage automatique avec Dash (+ Docker) part3 ~ Practice ~
J'ai essayé de moderniser une application Java EE avec OpenShift.
J'ai essayé de créer une application Android avec MVC maintenant (Java)
J'ai essayé de créer une fonction de groupe (babillard) avec Rails
J'ai essayé de créer une simple application Android de reconnaissance faciale en utilisant OpenCV
J'ai essayé de créer une API Web qui se connecte à DB avec Quarkus
J'ai créé une application d'apprentissage automatique avec Dash (+ Docker) part2 ~ Façon basique d'écrire Dash ~
J'ai essayé de créer une application de conversation en Java à l'aide de l'IA «A3RT»
J'ai essayé de casser le bloc avec java (1)
J'ai essayé de créer une application d'apprentissage automatique avec Dash (+ Docker) part1 ~ Construction de l'environnement et vérification du fonctionnement ~
Une histoire où j'ai essayé de faire une vidéo en liant Traitement et Resolume
J'ai essayé de faire un jeu simple avec Javafx ① "Trouvons le jeu du bonheur" (inachevé)
[Android] J'ai créé un écran de liste de matériaux avec ListView + Bottom Sheet
J'ai essayé de cloner une application Web pleine de bugs avec Spring Boot
J'ai essayé de créer une fonction de connexion avec Java
J'ai essayé OCR de traiter un fichier PDF avec Java
J'ai essayé de faire un jeu simple avec Javafx ① "Trouvons le jeu du bonheur" (version inachevée ②)
[Swift] J'ai essayé d'implémenter une interface utilisateur semblable à un profil Instagram avec UICollectionView avec juste du code sans storyboard
[Azure] J'ai essayé de créer une application Java gratuitement ~ Se connecter avec FTP ~ [Débutant]
J'ai essayé de créer un environnement de développement java8 avec Chocolatey
J'ai essayé d'augmenter la vitesse de traitement avec l'ingénierie spirituelle
[Rails] J'ai essayé de créer une mini application avec FullCalendar
Je veux faire une liste avec kotlin et java!
Je veux créer une fonction avec kotlin et java!
[Rails] J'ai essayé d'implémenter le traitement par lots avec la tâche Rake
J'ai essayé d'implémenter une application web pleine de bugs avec Kotlin
J'ai créé un client RESAS-API en Java
J'ai essayé de créer un environnement de développement padrino avec Docker
J'ai essayé OCR de traiter un fichier PDF avec Java part2
J'ai essayé de résumer le support d'iOS 14
J'ai essayé de convertir l'exemple d'application en microservice selon l'idée du livre "Microservice Architecture".
J'ai essayé d'interagir avec Java
J'ai essayé d'implémenter le traitement Ajax de la fonction similaire dans Rails
Je veux créer un bouton avec un saut de ligne avec link_to [Note]
J'ai essayé d'exécuter une application d'échange de cartes de crédit avec Corda 1
J'ai essayé d'écrire du code comme une déclaration de type en Ruby
Faisons une application multiplateforme avec JRuby (génération de fichier jar)
[Unity] J'ai essayé de créer un plug-in natif UniNWPathMonitor en utilisant NWPathMonitor
J'ai essayé de créer une application simple en utilisant Dockder + Rails Scaffold
[Java] J'ai essayé de faire un labyrinthe par la méthode de creusage ♪
[Rails] Implémentation de la fonction de catégorie multicouche en utilisant l'ascendance "J'ai essayé de créer une fenêtre avec Bootstrap 3"
Je souhaite développer une application web!
Faisons une carte de Noël avec Processing!
J'ai essayé de migrer le traitement vers VS Code
J'ai essayé de démarrer avec Web Assembly
J'ai essayé de jouer un peu avec BottomNavigationView ①
J'ai essayé d'utiliser Selenium comme JQuery
J'ai essayé de créer une classe parent d'objet de valeur dans Ruby
J'ai essayé de faire une sauvegarde automatique avec plus agréable + PostgreSQL + SSL + docker
Un débutant Java a essayé de créer une application Web simple à l'aide de Spring Boot
J'ai créé un bot de transaction d'arbitrage de monnaie virtuelle et essayé de gagner de l'argent
J'ai essayé de créer un portefeuille avec AWS, Docker, CircleCI, Laravel [avec lien de référence]