Je travaille sur une application qui donnera à l'utilisateur la possibilité de sélectionner une photo appliquer un filtre et l'enregistrer. Fondamentalement est une copie de la caméra de l'application instagram où l'utilisateur sélectionner une photo de la bibliothèque, appliquer un filtre, puis le poster.Swift CIfilter sélectionner à partir d'une collectionVoir
L'application fonctionne bien, mon seul problème est que lors du chargement de la collectionView avec les images filtrées, le processus est plutôt lent. J'ai lu un peu (je suis novice et c'est la première fois que j'ai travaillé avec l'image de base) et j'ai essayé d'appliquer tous les conseils que j'ai appris. Cependant, je crois que l'application est toujours lente.
Alors, voici ce que j'ai fait.
J'ai créé un modèle avec les filtres:
public protocol Filter {
// reference to the core image filter
var filter: CIFilter { get }
// output of the filter.
var outputImage: CIImage? { get }
}
// common to all filters.
extension Filter {
public var outputImage: CIImage? { return self.filter.outputImage }
}
//Bloom
public class Bloom: Filter {
public let filter: CIFilter
public init(inputImage: CIImage, inputRadius: CGFloat = 10.0,
inputIntensity: CGFloat = 1.0) {
let parameters:[String : Any] = [
"inputImage":inputImage,
"inputRadius":inputRadius,
"inputIntensity":inputIntensity ]
guard let filter = CIFilter(name:"CIBloom", withInputParameters: parameters) else { fatalError() }
self.filter = filter
}
}
// Box Blur
public class BoxBlur: Filter {
public let filter: CIFilter
public init(inputImage: CIImage, inputRadius: CGFloat = 10.0) {
let parameters:[String : Any] = [
"inputImage":inputImage,
"inputRadius":inputRadius ]
guard let filter = CIFilter(name:"CIBoxBlur", withInputParameters: parameters) else { fatalError() }
self.filter = filter
}
}
...........
et ainsi de suite pour tous les filtres dont j'ai besoin.
Que j'ai créé une classe pour créer un tableau UIImage avec toutes les images filtrées:
class filteredImages {
static var filterToApply: Filter!
static var filterNames = [
"Original","Sepia","Poster",....
]
static var filteredImages = [UIImage]()
static var filteredImage: UIImage!
static func createImageArray(inputImage: CIImage, onSuccess: @escaping() ->()) {
filteredImages.removeAll()
for filter in filterNames {
switch filter {
case "Original":
filteredImage = UIImage(ciImage:inputImage)
filteredImages.append(filteredImage)
case "Sepia":
filterToApply = SepiaTone(inputImage: inputImage, inputIntensity: 0.8)
filteredImage = UIImage(ciImage: filterToApply.outputImage!)
filteredImages.append(filteredImage)
............
}
onSuccess()
}
}
}
Et enfin dans mon contrôleur:
var filteredImagesArray = [UIImage]()
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)
let inputImage = CIImage(image: (originalImage.image?.resized(toWidth: 120))!)!
filteredImages.createImageArray(inputImage: inputImage) {
self.filteredImagesArray = filteredImages.filteredImages
}
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "FilterCell", for: indexPath) as! FilterCell
cell.filteredImage.image = filteredImagesArray[indexPath.row]
cell.filterName.text = filteredImages.filterNames[indexPath.row]
cell.layer.borderWidth = 0.7
cell.layer.borderColor = UIColor.white.cgColor
return cell
}
J'ai aussi une extension pour réduire la " original "image:
extension UIImage {
func resized(toWidth width: CGFloat) -> UIImage? {
let canvasSize = CGSize(width: width, height: CGFloat(ceil(width/size.width * size.height)))
UIGraphicsBeginImageContextWithOptions(canvasSize, false, scale)
defer { UIGraphicsEndImageContext() }
draw(in: CGRect(origin: .zero, size: canvasSize))
return UIGraphicsGetImageFromCurrentImageContext()
}
}
Y at-il un moyen que je puisse le rendre plus rapide? Ai-je raté quelque chose?
Merci.
----------- UNE MISE À JOUR PAR Ladislav DEMANDE
Voici le code que j'utilise pour obtenir des images de la bibliothèque:
enum Section: Int {
case allPhotos = 0
case smartAlbums
case userCollections
static let count = 3
}
var allPhotos: PHFetchResult<PHAsset>!
var allPhotosFromAlbum = PHFetchResult<PHAsset>()
var smartAlbums: [PHAssetCollection] = []
var userCollections: PHFetchResult<PHAssetCollection>!
let subtypes:[PHAssetCollectionSubtype] = [
.smartAlbumFavorites,
.smartAlbumPanoramas,
.smartAlbumScreenshots,
.smartAlbumSelfPortraits,
.smartAlbumVideos,
.smartAlbumRecentlyAdded,
.smartAlbumSelfPortraits
]
override func viewDidLoad() {
super.viewDidLoad()
// Create a PHFetchResult object for each section in the table view.
let allPhotosOptions = PHFetchOptions()
allPhotosOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
allPhotos = PHAsset.fetchAssets(with: allPhotosOptions)
let options = PHFetchOptions()
options.predicate = NSPredicate(format: "estimatedAssetCount > 0")
options.sortDescriptors = [NSSortDescriptor(key: "localizedTitle", ascending: false)]
smartAlbums = fetchSmartCollections(with: .smartAlbum, subtypes: subtypes)
userCollections = PHAssetCollection.fetchAssetCollections(with: .album, subtype: .albumRegular, options: options)
}
ici est la fonction i utiliser pour se PHAssetCollection avec Sous-types:
private func fetchSmartCollections(with: PHAssetCollectionType, subtypes: [PHAssetCollectionSubtype]) -> [PHAssetCollection] {
var collections:[PHAssetCollection] = []
let options = PHFetchOptions()
options.includeHiddenAssets = false
for subtype in subtypes {
if let collection = PHAssetCollection.fetchAssetCollections(with: with, subtype: subtype, options: options).firstObject, collection.photosCount > 0 {
collections.append(collection)
}
}
return collections
}
I afficher les résultats dans un tableView puis lors de la sélection je passe toutes les images de l'album à un autre contrôleur.
Voici le code du contrôleur (appelons-le mMainVC) où i afficher réellement les images pour sélectionner:
fileprivate let imageManager = PHCachingImageManager()
var fetchResult: PHFetchResult<PHAsset>!
var assetCollection: PHAssetCollection!
override func viewDidLoad() {
super.viewDidLoad()
if fetchResult == nil {
let allPhotosOptions = PHFetchOptions()
allPhotosOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
fetchResult = PHAsset.fetchAssets(with: allPhotosOptions)
}
}
et ici la fonction pour obtenir l'image du fetchResult:
func selectImageFromAssetAtIndex(index: Int) {
let asset = fetchResult.object(at: index)
let size = scrollViewImage.frame.size.width
PHImageManager.default().requestImage(for: asset, targetSize: CGSize(width: size, height: size), contentMode: .aspectFill, options: nil, resultHandler: { (image, info) in
DispatchQueue.main.async {
self.displayImageInScrollView(image: image!)
}
})
}
--------------------- ET VIDEO SCREENSHOT
est ici le lien pour la vidéo: https://drive.google.com/file/d/0B6U8olIA_ZS8U0tpN0hKOWdrVm8/view?usp=sharing
êtes-vous ge tation de photos depuis Camera roll? – Ladislav
@Ladislav oui j'obtiens la photo de la photothèque ... j'implémenterai plus tard la possibilité de filmer une photo puis d'appliquer le filtre – Marco
Pouvez-vous ajouter l'extrait de code comment vous obtenez actuellement les images de PhotoKit .. ? – Ladislav