Crea un'app fotografica con GPUImage

Questo tutorial ti insegnerà come applicare filtri e effetti speciali di Instagram alle immagini con il potente progetto GPUImage. Lungo la strada, imparerai come costruire una semplice applicazione per fotocamera in grado di scattare nuove foto o accedere a immagini esistenti dall'album fotografico.


Demo del progetto

Quanto sopra è un collage di filtri immagine applicati con l'app questo tutorial ti insegnerà come costruire. L'immagine sorgente proviene da ep.Sos.de su Flickr.


Passaggio 1: avviare un nuovo progetto Xcode

Avvia Xcode e crea una nuova applicazione usando il modello Vista singola.

Per questo tutorial, utilizzeremo sia gli storyboard che il conteggio dei riferimenti automatici, quindi assicurati di selezionare entrambe le caselle. Assegna un nome al progetto "PhotoFX" e fornisci un identificatore aziendale univoco per il test del dispositivo.


Passaggio 2: creare l'interfaccia dell'applicazione

L'interfaccia dell'applicazione sarà composta da a UINavigationBar per il titolo dell'app sul UIView e salva il pulsante, a UIToolbar per i pulsanti dell'album, della fotocamera e del filtro, e una UIImageView impostata sul riempimento dell'aspetto per la visualizzazione e la modifica delle immagini selezionate.

Apri il MainStoryboard.storyboard file. Seleziona il UIView sullo schermo e quindi selezionare Editor> Incorpora in> Controller di navigazione.

Seleziona il UINavigationController e poi vai a Impostazioni Attributi nel pannello Utility. Imposta il menu a discesa "Barra superiore" su "Barra di navigazione nera" e "Barra di stato" su "Nessuno". Per finalizzare la rimozione della barra di stato, vai su PhotoFx-Info.plist file e aggiungi una nuova chiave con il testo "La barra di stato è inizialmente nascosta". Imposta il valore su "SÌ".

Perché abbiamo appena trasferito la nostra app in UINavigationController modello, dovresti andare ora ViewController.h e aggiungere la seguente dichiarazione di delegato:

 #importare  @interface ViewController: UIViewController  @fine

Ne avremo bisogno dopo.

Ora torna al file Storyboard e fai doppio clic sul titolo al centro del file UINavigationItem e sostituisci il testo predefinito con "PhotoFX".

Trascina a UIBarButtonItem dalla libreria degli oggetti sul UINavigationItem. Con il nuovo elemento selezionato, vai alla scheda Impostazioni Attributi del pannello Utilità e imposta la proprietà Identificatore del pulsante su "Salva". Successivamente, con il pulsante "Salva" ancora selezionato, deselezionare la casella di controllo "Abilitato" per questo pulsante. Ciò impedirà all'utente di cercare di salvare un'immagine prima di caricarne una dall'album fotografico o di scattare una foto con la fotocamera (la riattiveremo con il codice più tardi).

Tornare alla libreria degli oggetti e trascinare a UIToolbar sul principale UIView. Successivamente aggiungi un totale di tre UIBarButtonItem oggetti sulla barra degli strumenti. Cambia il testo del titolo del primo pulsante in "Album", imposta la proprietà Identifier per il secondo su "Camera" e imposta il testo del titolo del terzo pulsante su "Filtro". Il pulsante "Filtro" dovrebbe essere disabilitato di default, proprio come il pulsante "Salva" dall'alto.

Per lucidare il layout della barra degli strumenti, abbiamo bisogno di allineare a destra il filtro pulsante sulla barra degli strumenti. È possibile ottenere questo effetto utilizzando una voce di pulsante Barra spaziatrice flessibile, che è possibile trascinare semplicemente sulla barra degli strumenti dalla libreria degli oggetti.

Notare come abbagliante il bianco UIView è in contrasto con la barra di navigazione nera e lucida e la barra degli strumenti? Facciamo qualcosa al riguardo. Seleziona il UIView e imposta il colore di sfondo su "tungsteno".

L'unica sottoview rimasta da aggiungere è la principale UIImageView usato per mostrare l'immagine dell'utente. Trascina a UIImageView dalla libreria degli oggetti e centrarlo tra il UINavigationItem e il UIToolbar. Apri l'ispettore Attributi e seleziona "Adatta" come UIImageView modalità sotto la sottosezione "Visualizza" Ispettore.

Tutti i componenti principali dell'interfaccia ora sono sul posto! Il prossimo passo è collegare questi elementi dallo Storyboard al ViewController classe.

Apri il ViewController.m file. Aggiungi il seguente IBOutlet proprietà e IBAction metodi nel ViewController estensione di classe:

 @interface ViewController () @property (nonatomic, weak) IBOutlet UIImageView * selectedImageView; @property (nonatomic, weak) IBOutlet UIBarButtonItem * filterButton; @property (nonatomic, weak) IBOutlet UIBarButtonItem * saveButton; - (IBAction) photoFromAlbum; - (IBAction) fotoFromCamera; - (IBAction) applyImageFilter: (id) mittente; - (IBAction) saveImageToAlbum; @fine

Quindi, perché creare IBOutlet proprietà per la vista immagine, il pulsante filtro e il pulsante Salva, ma non gli altri componenti di Interface Builder? La risposta è che questi sono gli unici oggetti di cui avremo bisogno per accedere a livello di programmazione. Si accederà alla vista dell'immagine per impostare le immagini selezionate dall'utente mentre si accederà al filtro e ai pulsanti di salvataggio per passare dallo stato disabilitato a abilitato dopo che l'utente seleziona un'immagine o scatta una foto.

Il IBAction i metodi dovrebbero essere per lo più auto-esplicativi e si connetteranno direttamente al UIBarButtonItem selettore implicito da ciascun nome.

Dopo aver creato il IBOutlet proprietà, dovresti sintetizzarle aggiungendo la seguente riga di codice alla classe @implementazione:

 @implementation ViewController @synthesize selectedImageView, filterButton, saveButton;

Per completare la configurazione di Interface Builder, mappare ciascuno dei precedenti IBOutlet oggetti e IBAction metodi dichiarati ai componenti di Interface Builder appropriati (serve aiuto per fare questo? Lascia una domanda nella sezione commenti qui sotto). Assicurati di salvare le modifiche prima di proseguire.

Con l'interfaccia dell'applicazione creata, siamo pronti per iniziare a codificare la funzionalità!


Passaggio 3: selezione delle foto dall'album

Questo tutorial utilizzerà il UIImagePickerController classe per accedere direttamente alle immagini all'interno dell'album fotografico dell'utente. L'utilizzo di questa classe si sovrapporrà ad un browser di galleria di visualizzazione modale sulla nostra interfaccia esistente. Quando un utente seleziona l'immagine che desidera, il selezionatore utilizzerà la delega per notificare il nostro ViewController classe che una selezione è stata fatta. Se sei nuovo nello sviluppo di iOS, non preoccuparti, è molto più semplice di quanto possa sembrare.

Nel ViewController.m file, aggiungere la seguente implementazione per photoFromAlbum metodo:

 @synthesize selectedImageView, filterButton, saveButton; - (IBAction) photoFromAlbum UIImagePickerController * photoPicker = [[UIImagePickerController alloc] init]; photoPicker.delegate = self; photoPicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary; [Auto PresentViewController: photoPicker animato: SÌ completamento: NULL]; 

Semplice, vero? Ora abbiamo solo bisogno di implementare il UIImagePickerController delegare il protocollo per rispondere alle selezioni di immagini. Lo farai al punto 5 di questo tutorial.


Passaggio 4: scattare foto con la fotocamera

Esistono due approcci principali per scattare foto con la fotocamera del dispositivo. Puoi usare il UIImagePickerController per accedere all'implementazione della fotocamera predefinita di Apple, oppure puoi creare un'esperienza completamente personalizzata con il framework AVFoundation. GPUImage si basa in realtà sulla funzionalità fornita da AVFoundation per fornire una classe specifica per questo scopo. Tuttavia, per questo tutorial, lo useremo UIImagePickerController per la selezione di foto in esclusiva. In un futuro tutorial su GPUImage (che probabilmente verrà pubblicato nelle prossime 1-3 settimane), ti mostrerò come utilizzare le classi più avanzate di GPUImage per raggiungere questo obiettivo.

Il codice per scattare foto in questo tutorial è il seguente:

 - (IBAction) photoFromCamera UIImagePickerController * photoPicker = [[UIImagePickerController alloc] init]; photoPicker.delegate = self; photoPicker.sourceType = UIImagePickerControllerSourceTypeCamera; [Auto PresentViewController: photoPicker animato: SÌ completamento: NULL]; 

Se si confronta il metodo sopra con il photoFromAlbum metodo dal passaggio 3, vedrai che l'unica differenza è se sourceType è impostato per UIImagePickerControllerSourceTypePhotoLibrary o UIImagePickerControllerSourceTypeCamera. Per questo motivo, è possibile combinare facilmente questi due metodi in uno solo. Tuttavia, ho deciso di andarmene photoFromCamera come metodo separato, come lo rifatterò per usarlo AVFoundation in un futuro tutorial e la logica dovrà essere separata.


Passaggio 5: codifica il delegato di prelievo foto

L'utente può ora navigare nella libreria del dispositivo o utilizzare la fotocamera del dispositivo per selezionare un'immagine con UIImagePickerController. Indipendentemente dal modo in cui l'utente seleziona un'immagine, il passo successivo consiste nell'implementare il metodo delegato che sarà responsabile del posizionamento dell'immagine sullo schermo.

Per prima cosa vai a ViewController.h e dichiara che questa classe si conformerà a UIImagePickerControllerDelegate:

 #importare  @interface ViewController: UIViewController  @fine

Adesso vai a ViewController.m e implementare il imagePickerController: didFinishPickingMediaWithInfo: metodo delegato chiamato dal photo picker alla selezione:

 - (void) imagePickerController: (UIImagePickerController *) photoPicker didFinishPickingMediaWithInfo: (NSDictionary *) informazioni self.saveButton.enabled = YES; self.filterButton.enabled = YES; UIImage * selectedImage = [info valueForKey: UIImagePickerControllerOriginalImage]; [self.selectedImageView setImage: selectedImage]; [photoPicker dismissModalViewControllerAnimated: YES]; 

Nelle righe 3-4 sopra, i pulsanti di salvataggio e filtro sono abilitati perché ora abbiamo un'immagine su cui è possibile eseguire tali azioni.

La riga 6 crea a UIImage oggetto con la foto selezionata dall'utente, e la riga 8 imposta la proprietà dell'immagine del UIImageViewController all'immagine scelta che la visualizzerà sullo schermo.

Infine, la riga 10 disattiva la vista modale utilizzata per selezionare la foto.

Il codice sopra dovrebbe funzionare bene, ma c'è bisogno di un miglioramento. Piuttosto che semplicemente memorizzare l'immagine selezionata nel selectedImageView, dovremmo anche conservare una copia in un interno UIImage membro dei dati. Ciò consentirà all'applicazione di applicare ciascun filtro selezionato direttamente all'immagine originale anziché stratificare iterativamente gli effetti. Permetterà inoltre all'utente di tornare facilmente all'immagine originale da una prospettiva filtrata. Per fare questo, prima aggiungi un UIImage oggetto all'estensione di classe nella parte superiore di ViewController.m:

 #import "ViewController.h" #import "GPUImage.h" @interface ViewController () UIImage * originalImage;  @property (nonatomic, weak) IBOutlet UIImageView * selectedImageView; @property (nonatomic, weak) IBOutlet UIBarButtonItem * filterButton;

Quindi modifica il imagePickerController: didFinishPickingMediaWithInfo: metodo come segue:

 - (void) imagePickerController: (UIImagePickerController *) photoPicker didFinishPickingMediaWithInfo: (NSDictionary *) informazioni self.saveButton.enabled = YES; self.filterButton.enabled = YES; originalImage = [info valueForKey: UIImagePickerControllerOriginalImage]; [self.selectedImageView setImage: originalImage]; [photoPicker dismissModalViewControllerAnimated: YES]; 

Se ora crei ed esegui il progetto, dovresti riuscire a selezionare le foto direttamente dall'album del dispositivo!


Passaggio 6: Salvataggio dell'immagine scelta

L'ultima cosa che dobbiamo fare prima di affrontare GPUImage è consentire agli utenti di salvare le foto scattate con la fotocamera del dispositivo. Puoi farlo con una singola riga di codice all'interno di saveImageToAlbum metodo:

 - (IBAction) saveImageToAlbum UIImageWriteToSavedPhotosAlbum (self.selectedImageView.image, self, @selector (image: didFinishSavingWithError: contextInfo :), nil); 

La riga di codice sopra tenterà di salvare l'immagine nell'album fotografico, ma dovrai implementare il selettore specificato per rispondere in caso di successo o fallimento:

 - (void) image: (UIImage *) image didFinishSavingWithError: (NSError *) error contextInfo: (void *) contextInfo NSString * alertTitle; NSString * alertMessage; if (! error) alertTitle = @ "Immagine salvata"; alertMessage = @ "Immagine salvata nell'album fotografico con successo.";  else alertTitle = @ "Errore"; alertMessage = @ "Impossibile salvare nell'album fotografico.";  UIAlertView * alert = [[UIAlertView alloc] initWithTitle: alertTitle message: alertMessage delegate: self cancelButtonTitle: @ "Okay" otherButtonTitles: nil]; [avviso spettacolo]; 

Le linee di codice di cui sopra sono piuttosto semplici e mostrano semplicemente a UIAlertView messaggio che notifica all'utente se l'immagine è stata salvata o meno correttamente.


Passaggio 7: Aggiungi GPUImage al tuo progetto

L'aggiunta di GPUImage al tuo progetto è un po 'più complicata di quanto potresti aspettarti, ma seguendo questo passaggio ci vorranno solo pochi minuti per essere attivo e funzionante.

Innanzitutto, è necessario scaricare una copia di GPUImage dal progetto ufficiale GitHub. Annullare l'archiviazione del file scaricato e aprire la cartella "framework". Questi sono i file essenziali necessari per importare GPUImage nel tuo progetto. Piuttosto che copiare tutti questi nel tuo progetto direttamente, usa Finder per andare nella posizione in cui hai salvato il tuo progetto Xcode al punto 1 (per me è ~ / Desktop / PhotoFX). Crea una nuova cartella chiamata "Submodules" con una cartella figlio chiamata "GPUImage". Ora copia la cartella "framework" scaricata da GitHub e incollala nella cartella "GPUImage". Quindi, aprire la cartella "framework" e selezionare il file GPUImage.xcodeproj. Lo schermo dovrebbe apparire in questo modo:

Ora trascina il file GPUImage.xcodeproj in Xcode Project Navigator. Se l'operazione è andata a buon fine, dovresti vedere qualcosa del tipo:

Con il progetto aggiunto con successo, dovrai aggiungere GPUImage come dipendenza dalle impostazioni di costruzione della tua app. Seleziona "PhotoFX" dal navigatore del progetto, seleziona il target "PhotoFX", quindi vai alla scheda "Fasi di creazione". Espandi il menu a tendina "Dipendenze obiettivo" e poi fai clic sull'icona "+". Seleziona "GPUImage" dall'elenco che appare. Dai un'occhiata alla seguente immagine per avere un'idea di come è fatto:

Ora è necessario trascinare il file libGPUImage.a (trovato all'interno di Project Navigator di Xcode all'indirizzo GPUImage.xcodeproj> Prodotti) al menu a discesa "Collega binari con librerie". Completato questo, dovresti vedere qualcosa di simile al seguente:

Mentre sei concentrato sul menu a discesa "Collega binari con librerie", procedi e aggiungi i seguenti framework richiesti facendo clic sul pulsante "+" nell'angolo in basso a sinistra:

  • CoreMedia
  • CoreVideo
  • OpenGLES
  • AVFoundation
  • QuartzCore

Quasi fatto! Il prossimo passo è selezionare il progetto PhotoFX e andare su "Impostazioni Build". Cerca "Percorsi di ricerca intestazione" (potrebbe essere necessario selezionare il pulsante "Tutti" anziché "Base" per visualizzare questa opzione), quindi fare doppio clic per aggiungere Moduli / GPUImage / quadro nella finestra di popup che apparirà. Fare clic sulla casella accanto alla voce per indicare che questo percorso deve essere ricercato in modo ricorsivo. Se l'hai fatto correttamente, dovresti guardare qualcosa come il seguente:

L'ultimo passo è tornare a ViewController.m e aggiungi la seguente riga in alto:

 #import "ViewController.h" #import "GPUImage.h"

Ora dovresti essere in grado di compilare ed eseguire il progetto senza problemi. Avere problemi? Lascia un commento qui sotto.


Passaggio 8: Visualizza un elenco di filtri

GPUImage è dotato di un numero impressionante di filtri da utilizzare all'interno delle tue applicazioni. Per questo tutorial, ho selezionato il seguente esempio per bagnare i piedi:

  • GPUImageGrayscaleFilter
  • GPUImageSepiaFilter
  • GPUImageSketchFilter
  • GPUImagePixellateFilter
  • GPUImageColorInvertFilter
  • GPUImageToonFilter
  • GPUImagePinchDistortionFilter

Per creare il tuo elenco o semplicemente vedere tutti i filtri che GPUImage ha da offrire, consulta la documentazione ufficiale su GitHub.

Per presentare all'utente l'elenco di filtri sopra riportato, useremo un semplice UIActionSheet. Implementare il applyImageFilter: metodo come segue:

 - (IBAction) applyImageFilter: (id) sender UIActionSheet * filterActionSheet = [[UIActionSheet alloc] initWithTitle: @ "Seleziona filtro" delegato: self cancelButtonTitle: @ "Annulla" distructiveButtonTitle: nil otherButtonTitles: @ "Grayscale", @ "Sepia", @ "Schizzo", @ "Pixellate", @ "Inverti colore", @ "Toon", @ "Pinch Distort", @ "None", nil]; [filterActionSheet showFromBarButtonItem: sender animated: YES]; 

Passaggio 9: Implementazione della selezione del filtro

Per rispondere alla selezione del filtro, dovremo implementare il UIActionSheetDelegate. Vai a ViewController.h e dichiara che la classe si conformerà a questo delegato come segue:

 #importare  @interface ViewController: UIViewController  @fine

Ora torna a ViewController.m e aggiungere il seguente metodo:

 - (void) actionSheet: (UIActionSheet *) actionSheet clickkedButtonAtIndex: (NSInteger) buttonIndex GPUImageFilter * selectedFilter; switch (buttonIndex) caso 0: selectedFilter = [[GPUImageGrayscaleFilter alloc] init]; rompere; caso 1: selectedFilter = [[GPUImageSepiaFilter alloc] init]; rompere; caso 2: selectedFilter = [[GPUImageSketchFilter alloc] init]; rompere; case 3: selectedFilter = [[GPUImagePixellateFilter alloc] init]; rompere; case 4: selectedFilter = [[GPUImageColorInvertFilter alloc] init]; rompere; case 5: selectedFilter = [[GPUImageToonFilter alloc] init]; rompere; case 6: selectedFilter = [[GPUImagePinchDistortionFilter alloc] init]; rompere; caso 7: selectedFilter = [[GPUImageFilter alloc] init]; rompere; default: break;  UIImage * filteredImage = [selectedFilter imageByFilteringImage: originalImage]; [self.selectedImageView setImage: filteredImage]; 

Bam! L'app dovrebbe ora funzionare come desiderato. Come puoi vedere da quanto sopra, l'applicazione di filtri a un'immagine esistente con GPUImage non potrebbe essere più semplice. Hai semplicemente bisogno di istanziare a GPUImageFilter e quindi chiama il imageByFilteringImage: originalImage metodo.


Passaggio 10: aggiungere un'icona di app

Questa app ha solo bisogno di un'ultima cosa: una buona icona del dock. Grazie al nostro sito amico Psdtuts +, sono riuscito a trovare quello che stavo cercando:


Quanto sopra è semplicemente un ritaglio di pixel 57x57 (non retina) e 114x114 (retina) dall'effetto finale insegnato in Come disegnare una fotocamera Leica in Photoshop di Mohammad Jeprie.

Per ottenere questi nella tua app, devi solo trascinarli in Xcode Project Navigator.


Incartare

Questo tutorial ha appena scalfito la superficie di ciò che è possibile con GPUImage. Se ti è piaciuto questo tutorial o pensi di beneficiare della potenza di GPUImage in futuro, trova @bradlarson e ringrazia lui per aver creato un progetto open source così straordinario.


Più contenuti GPUImage?

Vuoi vedere più contenuti su GPUImage e l'elaborazione delle immagini? Se è così, fammi sapere! Puoi lasciare il tuo feedback nella sezione commenti qui sotto (preferito) o semplicemente inviarmi un messaggio su Twitter (@markhammonds).

AGGIORNARE: Ho pubblicato un secondo tutorial che spiega come utilizzare la fotocamera GPUImage e visualizzare le foto in una galleria.
Miglioramento di un'applicazione fotografica con GPUImage e iCarousel.