[iOS] Ich habe versucht, mit Swift eine insta-ähnliche Verarbeitungsanwendung zu erstellen

Ich habe mit Swift eine Verarbeitungs-App erstellt!

Die Übersicht ist wie folgt. 加工アプリ.gif

  1. Stellen Sie das Bild ein

Erstellen Sie zunächst ein Projekt, verschieben Sie es in das Main.storyboard und platzieren Sie dann die Schaltflächen Ansicht, UIImageView und. Zuerst Ansicht nach oben, rechts, links 0, Höhe 200. Als nächstes werde ich die UIImageView in die Ansicht einfügen, aber bitte machen Sie mit dem Layout, was Sie wollen. Die folgenden Schaltflächen befinden sich nur in einer Atmosphäre. Passen Sie sie daher nach Ihren Wünschen an. Außerdem habe ich das Bild in einer Atmosphäre in UIImageView platziert. Wenn Sie jedoch nichts festlegen, sieht es wie ein Leerzeichen aus, sodass es leichter zu verstehen ist, wenn Sie etwas festlegen.

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

Verbinden Sie anschließend jedes Teil mit IBOutlet.

Viewcontroler.swift


import UIKit

class ViewController: UIViewController {
    
    @IBOutlet weak var photo: UIImageView!
    @IBOutlet weak var shareButton: UIButton!
    
    //Ausgewähltes Bild
    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)
    }

}


Ich möchte UIImageView mit dem Foto verbinden und das ausgewählte Bild verwenden.

Viewcontroller.swift


    //Ausgewähltes Bild
    var selectedImage: UIImage?

Ist definiert als. Danach wird die Tap-Erkennung mit viewDidLoad durchgeführt und UIImagePickerController () aufgerufen. In der Erweiterung wird dann das von didFinishPickingMediaWithInfo ausgewählte Bild im Foto gespeichert. Überprüfen Sie den Code hier.

  1. Erstellen Sie einen Filterbildschirm

Wenn Sie ein Foto festlegen können, erstellen wir einen Bildschirm zur Auswahl von Filter. Erstellen Sie einen neuen View Controller und verwenden Sie ihn als FilterViewController. Setzen Sie dann Present Mordally from Viewcontroller auf FilterViewController. Bitte definieren Sie "filter_segue" für den erstellten Abschnitt. Es wird beim späteren Übergang verwendet. Als nächstes legen Sie die Teile in den FilterViewController. Wie in der Abbildung gezeigt, platzieren Sie zuerst eine neue Ansicht oben und dann die Schaltflächen Abbrechen und Weiter in dieser Ansicht. Platzieren Sie dann die UIImageView unter der obigen Ansicht. Das im View Controller ausgewählte Bild spiegelt sich darin wider. Legen Sie zum Schluss die CollectionView unter die UIImageView und halten Sie sie etwas weiter entfernt. Auch in dieser Sammlungsansicht Platzieren Sie die UIImageView und wählen Sie das Bild aus, das hier verarbeitet werden soll. Sehen Sie sich nach dem Platzieren die Bildlaufansicht der Sammlungsansicht an. ・ Horizontale Anzeige anzeigen ・ Vertikale Anzeige anzeigen Bitte deaktivieren Sie die beiden. Auf diese Weise können Sie die horizontale Folien-Benutzeroberfläche ausdrücken, die häufig bei der Verarbeitung von Apps verwendet wird. スクリーンショット 2020-11-03 21.44.19.jpg

Stellen Sie nach dem Platzieren der erforderlichen Teile den Delegaten und die Datenquelle einzeln ein. Und da für die Zelle von CollectionView eine neue Klasse erforderlich ist, erstellen Sie "FilterCollectionViewCell.swift", das UICollectionViewCell erneut erbt. スクリーンショット 2020-11-03 20.04.15.jpg

FilterCollectionViewCell.swift


import UIKit

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

Nur die UICollectionView in der CollectionView ist hier in Ordnung.

  1. Erstellen Sie eine Verarbeitungs-App![Screenshot 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)

Ich werde es tatsächlich von hier aus schaffen, aber vorerst werde ich den gesamten Code an die erste Stelle setzen. Wenn Sie ihn verstehen, können Sie ihn kopieren, aber für diejenigen, die ihn nicht verstehen, werde ich ihn in der Reihenfolge von oben erklären.

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

    }
}

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

Ich habe es als belassen. CancelButton kehrt zum vorherigen Bildschirm zurück, und NextButton gibt das in der Zelle unten ausgewählte Bild an den Ansichtscontroller weiter.

Definieren Sie als Nächstes die von FilterViewController verwendeten Eigenschaften.

FilterCollectionView.swift


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

Sie müssen nicht mehr selectedImage sagen, aber die folgenden CIFilterNames sollten nicht mit Klein- oder Großbuchstaben verwechselt werden. Dieses Mal werde ich nur 8 Typen verwenden. Das hier beschriebene CI ~ ist im Apple Core Image Filter-Referenzhandbuch definiert. Ich möchte diese in Zellen verwenden, also werde ich sie in ein Array einfügen. Es spielt keine Rolle, ob es nicht separat geschrieben wurde oder 8 oder mehr Typen in Ordnung sind. Bitte fügen Sie jedes hinzu, wie Sie möchten. Referenz: Core Image Filter Reference

Reflektieren Sie nach dem Hinzufügen das im vorherigen (View Controller) ausgewählte Bild mit viewDidLoad, damit alle sichtbar sind. Erstellen Sie dann eine Funktion für die Verarbeitung, die in der Zelle verwendet werden soll.

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 zählt die Anzahl der CIFilterNames. Ich zähle hier 8. Legen Sie in cellForItemAt fest, während Sie FilterCollectionViewCell verwenden. In newImage wird die Größe mithilfe der oben definierten Funktion resizeImage angepasst und für jede Zelle ein neues Filterbild festgelegt. In ciImage wird das zum Filtern ausgewählte Bild auf CIImage gesetzt. Und ciImage setzt im Filter so viele wie CIFilterNames. Danach habe ich ein neues CGImage erstellt, es zu einem UIImage gemacht und es in der Zelle festgelegt. didSelectItemAt ist der gleiche Prozess.

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

    }
}

Es scheint, als wäre es vorbei, wenn Sie diesen Punkt erreichen, aber so wie es ist, wird das verarbeitete und ausgewählte Bild nicht im Ansichts-Controller wiedergegeben. Daher werde ich ein neues Protokoll definieren.

FilterViewController.swift


protocol FilterViewControllerDelegate {
    func updatePhoto(image: UIImage)
}

Definieren Sie Delegateigenschaften, um dieses Protokoll zu verwenden.

FilterViewController.swift


var delegate: FilterViewControllerDelegate?

Ich möchte diesen Delegaten nach der Verarbeitung an den Ansichtscontroller für das ausgewählte Bild übergeben. Klicken Sie daher auf die Schaltfläche Weiter, um es an den Delegaten weiterzuleiten.

FilterViewController.swift


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

Fügen Sie abschließend die folgende Verarbeitung zu ViewController.swift hinzu. Dies spiegelt das ausgewählte Bild wider.

ViewController.swift


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

  1. Am Ende

Dies ist mein erster Beitrag. Der Inhalt dieser Verarbeitungs-App wurde aus dem folgenden Udemy-Kurs erstellt.

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

Überseekurse sind schwierig, aber die Qualität ist sehr hoch, daher kann ich es nur empfehlen. Niemand hat geschrieben, wie man einen Verarbeitungsantrag stellt, deshalb habe ich ihn vorgestellt. Ich denke, wenn Sie es weiter modifizieren, können Sie eine Anwendung auf kommerzieller Ebene erstellen. Sie sollten wissen, dass es nicht so schwierig ist. Ich hoffe, es ist nützlich für Anfänger, die daran interessiert sind, einen Bearbeitungsantrag zu stellen.

Wenn es von nun an Inhalte gibt, die noch niemand gepostet hat, werde ich sie jedes Mal zur gleichen Zeit wie die Ausgabe einführen. Vielen Dank.

Recommended Posts

[iOS] Ich habe versucht, mit Swift eine insta-ähnliche Verarbeitungsanwendung zu erstellen
Ich habe eine App für maschinelles Lernen mit Dash (+ Docker) Teil 3 ~ Übung ~ erstellt
Ich habe versucht, eine Java EE-Anwendung mit OpenShift zu modernisieren.
Ich habe versucht, eine Android-Anwendung mit MVC zu erstellen (Java)
Ich habe versucht, mit Rails eine Gruppenfunktion (Bulletin Board) zu erstellen
Ich habe versucht, eine einfache Gesichtserkennungs-Android-Anwendung mit OpenCV zu erstellen
Ich habe versucht, eine Web-API zu erstellen, die mit Quarkus eine Verbindung zur Datenbank herstellt
Ich habe eine App für maschinelles Lernen mit Dash (+ Docker) Teil 2 ~ Grundlegende Schreibweise für Dash ~ erstellt
Ich habe versucht, mit AI "A3RT" eine Talk-App in Java zu erstellen.
Ich habe versucht, den Block mit Java zu brechen (1)
Ich habe versucht, eine Anwendung für maschinelles Lernen mit Dash (+ Docker) Teil 1 ~ Umgebungskonstruktion und Funktionsprüfung ~ zu erstellen
Eine Geschichte, als ich versuchte, ein Video zu erstellen, indem ich Processing und Resolume verknüpfte
Ich habe versucht, mit Javafx ein einfaches Spiel zu machen ① "Lass uns Glücksspiel finden" (unvollendet)
[Android] Ich habe mit ListView + Bottom Sheet einen Materiallistenbildschirm erstellt
Ich habe versucht, eine Webanwendung voller Fehler mit Spring Boot zu klonen
Ich habe versucht, eine Anmeldefunktion mit Java zu erstellen
Ich habe versucht, mit OCR eine PDF-Datei mit Java zu verarbeiten
Ich habe versucht, ein einfaches Spiel mit Javafx zu machen ① "Lass uns Glücksspiel finden" (unvollendete Version ②)
[Swift] Ich habe versucht, mit UICollectionView eine Instagram-ähnliche Benutzeroberfläche mit nur Code ohne Storyboard zu implementieren
[Azure] Ich habe versucht, eine kostenlose Java-App zu erstellen ~ Mit FTP verbinden ~ [Anfänger]
Ich habe versucht, mit Chocolatey eine Java8-Entwicklungsumgebung zu erstellen
Ich habe versucht, die Verarbeitungsgeschwindigkeit mit spiritueller Technik zu erhöhen
[Rails] Ich habe versucht, eine Mini-App mit FullCalendar zu erstellen
Ich möchte eine Liste mit Kotlin und Java erstellen!
Ich möchte eine Funktion mit Kotlin und Java erstellen!
[Rails] Ich habe versucht, die Stapelverarbeitung mit der Rake-Task zu implementieren
Ich habe versucht, eine Webanwendung voller Fehler mit Kotlin zu implementieren
Ich habe einen RESAS-API-Client in Java erstellt
Ich habe versucht, mit Docker eine Padrino-Entwicklungsumgebung zu erstellen
Ich habe versucht, eine PDF-Datei mit Java part2 zu verarbeiten
Ich habe versucht, die Unterstützung für iOS 14 zusammenzufassen
Ich habe versucht, die Beispielanwendung gemäß der Idee des Buches "Micro Service Architecture" in einen Mikrodienst zu verwandeln.
Ich habe versucht, mit Java zu interagieren
Ich habe versucht, die Ajax-Verarbeitung der ähnlichen Funktion in Rails zu implementieren
Ich möchte mit link_to [Hinweis] eine Schaltfläche mit einem Zeilenumbruch erstellen.
Ich habe versucht, eine Kreditkartenhandelsanwendung mit Corda 1 auszuführen
Ich habe versucht, Code wie eine Typdeklaration in Ruby zu schreiben
Versuchen Sie, mit JRuby eine plattformübergreifende Anwendung zu erstellen (Generierung von JAR-Dateien).
[Unity] Ich habe mit NWPathMonitor ein natives Plug-In UniNWPathMonitor erstellt
Ich habe versucht, eine einfache Anwendung mit Dockder + Rails Scaffold zu erstellen
[Java] Ich habe versucht, mit der Grabmethode ein Labyrinth zu erstellen ♪
[Rails] Implementierung einer mehrschichtigen Kategoriefunktion unter Verwendung der Abstammung "Ich habe versucht, ein Fenster mit Bootstrap 3 zu erstellen"
Ich möchte eine Webanwendung entwickeln!
Machen wir eine Weihnachtskarte mit Verarbeitung!
Ich habe versucht, Processing auf VS Code zu migrieren
Ich habe versucht, mit Web Assembly zu beginnen
Ich habe versucht, ein wenig mit BottomNavigationView zu spielen ①
Ich habe versucht, Selen wie JQuery zu verwenden
Ich habe versucht, ein übergeordnetes Wertklasseobjekt in Ruby zu erstellen
Ich habe versucht, ein automatisches Backup mit angenehmem + PostgreSQL + SSL + Docker zu erstellen
Java-Anfänger haben versucht, mit Spring Boot eine einfache Webanwendung zu erstellen
Ich habe einen Arbitrage-Transaktionsbot für virtuelle Währungen erstellt und versucht, Geld zu verdienen
Ich habe versucht, ein Portfolio mit AWS, Docker, CircleCI, Laravel [mit Referenzlink] zu erstellen.