Creați o aplicație Photo cu GPUImage

Acest tutorial vă va învăța cum să aplicați filtre asemănătoare cu Instagram și efecte speciale în imagini cu proiectul GPUImage incredibil de puternic. Pe parcurs, veți învăța cum să construiți o aplicație simplă de cameră, capabilă să facă fie fotografii noi, fie să acceseze imagini existente din albumul foto.


Demo demo

Cele de mai sus este un colaj de filtre imagine aplicat cu aplicația acest tutorial vă va învăța cum să construiți. Imaginea sursă este de la ep.Sos.de pe Flickr.


Pasul 1: Începeți un nou proiect Xcode

Lansați Xcode și creați o nouă aplicație folosind șablonul Single View.

Pentru acest tutorial, vom folosi atât Storyboards, cât și numărarea automată a referințelor, deci asigurați-vă că ați selectat ambele casete. Denumiți proiectul "PhotoFX" și furnizați un identificator unic al companiei pentru testarea dispozitivelor.


Pasul 2: Creați interfața de aplicație

Interfața aplicației va consta din: a UINavigationBar pentru titlul aplicației pe UIView și butonul de salvare, a UIToolbar pentru butoanele albumului, camerei foto și a filtrului de utilitate și un UIImageView setat pentru a umple aspectul pentru vizualizarea și modificarea imaginilor selectate.

Deschide MainStoryboard.storyboard fişier. Selectează UIView pe ecran și apoi selectați Editor> Încorporați în> Controller de navigare.

Selectează UINavigationController și apoi accesați Inspectorul de atribute din panoul Utilitar. Setați meniul derulant "Top Bar" până la "Bară neagră de navigare" și "Bara de stare" în "Nici unul". Pentru a finaliza eliminarea barei de stare, accesați PhotoFX-Info.plist fișier și adăugați o nouă cheie cu textul "Bara de stare este inițial ascunsă". Setați valoarea la "YES".

Pentru că tocmai ne-am transferat aplicația în a UINavigationController șablon, ar trebui să mergi acum la ViewController.h și adăugați următoarea declarație a delegatului:

 #import  @ interfață ViewController: UIViewController  @Sfârșit

O să avem nevoie mai târziu.

Acum du-te înapoi la fișier Storyboard și faceți dublu-clic pe titlul din centrul UINavigationItem și înlocuiți textul implicit cu "PhotoFX".

Trageți a UIBarButtonItem din Biblioteca de obiecte pe UINavigationItem. Cu noul element de buton selectat, accesați fila Inspector atribute din panoul Utilities și setați proprietatea Identifier al butonului la "Save". Apoi, cu butonul "Salvare" încă selectat, debifați caseta de selectare "Enabled" pentru acest buton. Acest lucru va împiedica utilizatorul să încerce să salveze o imagine înainte de a încărca unul din albumul foto sau de a face o fotografie cu camera (o vom activa din nou cu codul mai târziu).

Reveniți la biblioteca de obiecte și trageți a UIToolbar pe main UIView. Apoi adăugați un total de trei UIBarButtonItem obiecte de pe bara de instrumente. Modificați textul titlului pentru primul buton la "Album", setați proprietatea Identificator pentru cel de-al doilea în "Camera" și setați textul titlului celui de-al treilea buton la "Filtrare". Butonul "Filtru" trebuie dezactivat în mod prestabilit, la fel ca și butonul "Salvare" de mai sus.

Pentru a lustrui aspectul barei de instrumente, trebuie să aliniem dreapta filtru pe bara de instrumente. Puteți obține acest efect utilizând un element Flexible Space Bar Button, pe care îl puteți trage pur și simplu în bara de instrumente din biblioteca de obiecte.

Observați cum strălucește albul UIView este în contrast cu bara de navigare negru, strălucitoare și bara de instrumente? Să facem ceva în legătură cu asta. Selectează UIView și setați culoarea de fundal la "tungsten".

Singurul subview pe care trebuie să-l adăugați este principalul UIImageView folosit pentru a arăta imaginea utilizatorului. Trageți a UIImageView din Biblioteca de obiecte și centralizați-o între UINavigationItem si UIToolbar. Trageți în sus Inspectorul de atribute și selectați "Aspect Fit" ca UIImageView modul de sub subsecțiunea "Vizualizare" Inspector.

Toate componentele principale ale interfeței sunt acum în vigoare! Următorul pas este să conectezi aceste elemente din Storyboard la ViewController clasă.

Deschide ViewController.m fişier. Adăugați următoarele IBOutlet proprietăți și IBAction metode în ViewController extensie de clasă:

 @ interfață ViewController () @property (nonatomic, slab) IBOutlet UIImageView * selectedImageView; @property (nonatomic, slab) IBOutlet UIBarButtonItem * filterButton; @property (nonatomic, slab) IBOutlet UIBarButtonItem * saveButton; - (IBAction) photoFromAlbum; - (IBAction) photoFromCamera; - (IBAction) applyImageFilter: (id) expeditor; - (IBAction) saveImageToAlbum; @Sfârșit

Deci, de ce creați IBOutlet proprietăți pentru vizualizarea imaginii, butonul de filtrare și butonul de salvare, dar nu și celelalte componente ale interfeței Builder? Răspunsul este că acestea sunt singurele obiecte de care avem nevoie pentru a accesa programatic. Vizualizarea imaginii va fi accesată pentru a seta imaginile selectate de utilizator în timp ce butoanele de filtrare și de salvare vor fi accesate pentru a comuta starea de la dezactivat la activ după ce utilizatorul selectează o imagine sau face o fotografie.

IBAction metodele ar trebui să fie în mare parte explicite și se vor conecta direct la UIBarButtonItem selectator implicit de fiecare nume.

După crearea fișierului IBOutlet proprietăți, ar trebui să le sintetizezi adăugând următoarea linie de cod în clasă @implementation:

 @implementation ViewController @synthesize selectedImageView, filterButton, saveButton;

Pentru a finaliza configurarea Interface Builder, hartă fiecare dintre cele de mai sus IBOutlet obiecte și IBAction metode declarate componentelor corespunzătoare Interface Builder (Aveți nevoie de ajutor în acest sens? Lăsați o întrebare în secțiunea de comentarii de mai jos). Asigurați-vă că salvați modificările înainte de a vă deplasa.

Cu interfața aplicației create, suntem gata să începem să codificăm funcționalitatea!


Pasul 3: Selectarea fotografiilor din album

Acest tutorial va folosi UIImagePickerController pentru acces direct la imaginile din albumul foto al utilizatorului. Utilizarea acestei clase va suprapune un browser de galerie de vizualizare modală în partea de sus a interfeței noastre existente. Când un utilizator selectează imaginea dorită, selectorul va utiliza delegarea pentru a ne notifica ViewController clasa pe care o selecție a fost făcută. Dacă sunteți nou în dezvoltarea iOS, nu vă faceți griji, este mult mai ușor decât s-ar părea.

În ViewController.m fișier, adăugați următoarea implementare pentru photoFromAlbum metodă:

 @synthesize selectedImageView, filterButton, saveButton; - (IBAction) photoFromAlbum UIImagePickerController * photoPicker = [[UIImagePickerController alloc]]; photoPicker.delegate = auto; photoPicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary; [self presentViewController: photoPicker animat: DA finalizare: NULL]; 

Simplu, nu? Acum trebuie doar să punem în aplicare UIImagePickerController delegați protocolul pentru a răspunde la selecțiile de imagini. Veți face acest lucru în pasul 5 din acest tutorial.


Pasul 4: Fotografierea cu camera

Există două abordări principale pentru a face fotografii cu camera aparatului. Puteți folosi fie UIImagePickerController pentru a accesa implementarea implicită a camerei de la Apple sau puteți crea o experiență complet personalizată cu cadrul AVFoundation. GPUImage se bazează de fapt pe funcționalitatea oferită de AVFoundation pentru a oferi o clasă specifică acestui scop în minte. Cu toate acestea, pentru acest tutorial, vom folosi UIImagePickerController exclusiv pentru selecția fotografiei. Într-un tutorial viitoare despre GPUImage (probabil să fie publicat în următoarele 1-3 săptămâni), vă vom arăta cum să utilizați cele mai avansate clase GPUImage pentru a realiza acest lucru.

Codul de fotografiere din acest tutorial este următorul:

 - (IBAction) photoFromCamera UIImagePickerController * photoPicker = [[UIImagePickerController alloc]]; photoPicker.delegate = auto; photoPicker.sourceType = UIImagePickerControllerSourceTypeCamera; [self presentViewController: photoPicker animat: DA finalizare: NULL]; 

Dacă comparați metoda de mai sus cu photoFromAlbum din pasul 3, veți vedea că singura diferență este dacă sourceType este setat sa UIImagePickerControllerSourceTypePhotoLibrary sau UIImagePickerControllerSourceTypeCamera. Din această cauză, puteți combina cu ușurință aceste două metode într-una singură. Cu toate acestea, am decis să plec photoFromCamera ca o metodă separată, așa cum o voi refactoriza să o folosească platformei AV Foundation într-un tutorial viitor și logica va trebui să fie separată.


Pasul 5: Codificați delegatul de selecție a fotografiilor

Utilizatorul poate naviga acum în biblioteca dispozitivului sau poate folosi camera aparatului pentru a selecta o imagine cu UIImagePickerController. Indiferent de modul în care utilizatorul selectează o imagine, următorul pas este implementarea metodei delegate care va fi responsabilă pentru plasarea imaginii pe ecran.

Mai întâi, du-te la ViewController.h și să declare că această clasă se va conforma UIImagePickerControllerDelegate:

 #import  @ interfață ViewController: UIViewController  @Sfârșit

Acum flip la ViewController.m și să pună în aplicare imagePickerController: didFinishPickingMediaWithInfo: metoda delegată numită de selectorul de fotografii după selecție:

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

Pe liniile 3-4 de mai sus, butoanele de salvare și filtrare sunt activate deoarece avem acum o imagine asupra căreia pot fi luate aceste acțiuni.

Linia 6 creează o UIImage obiect cu fotografia selectată de utilizator și rândul 8 stabilește proprietatea imaginii UIImageViewController la imaginea selectată care o va afișa pe ecran.

În cele din urmă, linia 10 respinge modul vizual utilizat pentru a selecta fotografia.

Codul de mai sus ar trebui să funcționeze bine, dar este necesară o îmbunătățire. Mai degrabă decât pur și simplu stocarea imaginii selectate în selectedImageView, ar trebui să păstrăm și o copie într-o copie internă UIImage membru de date. Acest lucru va permite aplicației să aplice fiecare filtru selectat direct imaginii originale, mai degrabă decât stratificarea iterativă a efectelor. De asemenea, permite utilizatorului să revină cu ușurință la imaginea originală dintr-o perspectivă filtrată. Pentru aceasta, mai întâi adăugați a UIImage obiecte la extensia de clasă din partea de sus a ViewController.m:

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

Apoi modificați imagePickerController: didFinishPickingMediaWithInfo: după cum urmează:

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

Dacă construiți și rulați proiectul acum, ar trebui să puteți selecta fotografii direct din albumul dispozitivului!


Pasul 6: Salvarea imaginii selectate

Ultimul lucru pe care trebuie să-l facem înainte de a aborda GPUImage este să permitem utilizatorilor să salveze fotografiile pe care le fac cu aparatul foto. Puteți face acest lucru cu o singură linie de cod în cadrul saveImageToAlbum metodă:

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

Linia de cod de mai sus va încerca să salveze imaginea în albumul foto, dar va trebui să implementați selectorul specificat pentru a răspunde succesului sau eșecului:

 - (void) imagine: (UIImage *) imagine didFinishSavingWithError: (NSError *) contextul de eroareInfo: (void *) contextInfo NSString * alertTitle; NSString * alertMessage; dacă (! eroare) alertTitle = @ "Image Saved"; alertMessage = @ "Imaginea salvată în album foto cu succes";  altceva alertTitle = @ "Eroare"; alertMessage = @ "Imposibil de salvat în album foto.";  UIAlertView * alert = [[UIAlertView alocare] initWithTitle: alertTitle mesaj: alertMessage delegate: self cancelButtonTitle: @ "Ok" altButtonTitles: nil]; [alertă spectacol]; 

Liniile de mai sus ale codului sunt destul de simple și se afișează a UIAlertView mesaj care notifică utilizatorului dacă imaginea a fost sau nu salvată cu succes.


Pasul 7: Adăugați GPUImage la proiectul dvs.

Adăugarea GPUImage la proiectul dvs. este puțin mai complicată decât s-ar putea să vă așteptați, dar urmând acest pas ar trebui să dureze doar câteva minute pentru ca dvs. să fiți pregătit.

În primul rând, trebuie să descărcați o copie a GPUImage din proiectul oficial GitHub. Arhivați fișierul descărcat și deschideți directorul "cadru". Acestea sunt fișierele esențiale necesare pentru a importa GPUImage în proiectul dvs. Mai degrabă decât să copiați toate acestea în proiectul dvs. direct, utilizați Finder pentru a merge la locația pe care ați salvat proiectul dvs. Xcode în Pasul 1 (pentru mine, care este ~ / Desktop / PhotoFX). Creați un nou folder numit "Submodule" cu un folder copil numit "GPUImage". Acum, copiați dosarul "cadru" descărcat de la GitHub și inserați-l în folderul "GPUImage". Apoi, deschideți directorul "cadru" și selectați fișierul GPUImage.xcodeproj. Ecranul dvs. ar trebui să arate astfel:

Trageți acum fișierul GPUImage.xcodeproj în Xcode Project Navigator. Dacă ați făcut acest lucru cu succes, ar trebui să vedeți ceva de genul:

Cu ajutorul proiectului adăugat cu succes, va trebui să adăugați GPUImage ca dependență de setările de dezvoltare ale aplicației. Selectați "PhotoFX" din navigatorul de proiect, selectați țintă "PhotoFX", apoi mergeți la fila "Construiți faze". Extindeți meniul derulant "Destinații țintă" și apoi faceți clic pe pictograma "+". Selectați "GPUImage" din lista care apare. Uitați-vă la următoarea imagine pentru a vă simți cum se face acest lucru:

Acum trebuie să trageți fișierul libGPUImage.a (găsit în Xcode's Project Navigator la GPUImage.xcodeproj> Produse) la meniul "Link Binary with Libraries". Cu aceasta ați terminat, ar trebui să vedeți ceva de genul:

În timp ce vă concentrați asupra meniului derulant "Link Binary With Libraries", continuați și adăugați următoarele cadre necesare făcând clic pe butonul "+" din colțul din stânga jos:

  • CoreMedia
  • CoreVideo
  • OpenGLES
  • platformei AV Foundation
  • QuartzCore

Aproape gata! Următorul pas este să selectați proiectul PhotoFX și să accesați "Build Settings". Căutați "Căi de căutare antet" (poate fi necesar să selectați butonul "Toate" în loc de "Basic" pentru ca această opțiune să apară), apoi faceți dublu clic pentru a adăuga Submodule / GPUImage / cadru în dialogul pop-up care va apărea. Faceți clic pe caseta de selectare de lângă înregistrare pentru a indica că această cale trebuie căutată recursiv. Dacă ați făcut acest lucru corect, ar trebui să vă uitați la ceva de genul:

Ultimul pas este de a reveni la ViewController.m și adăugați următoarea linie în partea de sus:

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

Acum ar trebui să puteți compila și executa proiectul fără probleme. A avea probleme? Lasă un comentariu mai jos.


Pasul 8: Afișați o listă de filtre

GPUImage vine cu un număr impresionant de filtre pentru a fi utilizate în aplicațiile dvs. Pentru acest tutorial, am selectat următorul eșantion pentru a obține picioarele ude:

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

Pentru a vă crea propria listă sau pentru a vedea pur și simplu toate filtrele GPUImage, consultați documentația oficială despre GitHub.

Pentru a prezenta utilizatorilor lista de filtre de mai sus, vom folosi o simplă UIActionSheet. Implementați applyImageFilter: după cum urmează:

 - (IBAction) applyImageFilter: (id) expeditor UIActionSheet * filterActionSheet = [[UIActionSheet alocare] initWithTitle: @ Delegat "Select Filter": self cancelButtonTitle: @ "Cancel" destructiveButtonTitle: nil otherButtonTitles: @ "Grayscale" @ "Sketch", @ "Pixellate", @ "Color Invert", @ "Toon", @ "Pinch Distort", @ "None", nul]; [filterActionSheet showFromBarButtonItem: expeditor animat: DA]; 

Pasul 9: Implementați selecția filtrului

Pentru a răspunde la selecția de filtre, va trebui să implementăm UIActionSheetDelegate. Mergi la ViewController.h și să declare că clasa va fi conformă cu acest delegat după cum urmează:

 #import  @ interfață ViewController: UIViewController  @Sfârșit

Acum săriți înapoi ViewController.m și adăugați următoarea metodă:

 - (void) actionSheet: (UIActionSheet *) acțiuneSheet clickedButtonAtIndex: (NSInteger) buttonIndex GPUImageFilter * selectedFilter; comutator (butonIndex) caz 0: selectFilter = [[GPUImageGrayscaleFilter alocare] init]; pauză; cazul 1: selectFilter = [[GPUImageSepiaFilter alloc] init]; pauză; cazul 2: selectFilter = [[GPUImageSketchFilter alloc] init]; pauză; cazul 3: selectFilter = [[GPUImagePixellateFilter alloc] init]; pauză; cazul 4: selectFilter = [[GPUImageColorInvertFilter alocare] init]; pauză; cazul 5: selectedFilter = [[GPUImageToonFilter alloc] init]; pauză; cazul 6: selectFilter = [[GPUImagePinchDistortionFilter alloc]]; pauză; cazul 7: selectFilter = [[GPUImageFilter alloc] init]; pauză; prestabilit: pauză;  UIImage * filteredImage = [selectatFilter imageByFilteringImage: originalImage]; [auto.selectedImageView setImage: filteredImage]; 

Bam! Aplicația dvs. ar trebui să funcționeze acum după cum doriți. După cum puteți vedea din cele de mai sus, aplicarea filtrelor pentru o imagine existentă cu GPUImage nu ar putea fi mai simplă. Trebuie doar să instanțiați a GPUImageFilter și apoi apelați imageByFilteringImage: originalImage metodă.


Pasul 10: Adăugați o pictogramă de aplicație

Această aplicație are nevoie doar de un ultim lucru: o pictogramă de andocare bună. Datorită site-ului nostru de soră Psdtuts +, am putut găsi exact ceea ce căutam:


Cele de mai sus sunt pur și simplu o recoltă de 57x57 (non-retină) și 114x114 (retină) pixel din efectul final predat în Cum să desenezi o cameră Leica în Photoshop de Mohammad Jeprie.

Pentru a le introduce în aplicația dvs., trebuie doar să le trageți în Xcode Project Navigator.


Învelire

Acest tutorial abia a zgâriat suprafața a ceea ce este posibil cu GPUImage. Dacă v-ați bucurat de acest tutorial sau credeți că veți beneficia de puterea GPUImage în viitor, găsiți @bradlarson și îi mulțumiți pentru crearea unui astfel de proiect minunat de open source.


Mai mult conținut GPUImage?

Doriți să vedeți mai mult conținut în GPUImage și prelucrarea imaginilor? Dacă da, dați-mi voie să știu! Vă puteți lăsa feedback-ul în secțiunea de comentarii de mai jos (preferată) sau pur și simplu trimiteți-mi un mesaj pe Twitter (@markhammonds).

ACTUALIZAȚI: Am postat un al doilea tutorial care detaliază modul de utilizare a camerei GPUImage și afișarea fotografiilor într-o galerie.
Îmbunătățirea unui App Photo cu GPUImage și iCarousel.

Cod