web-dev-qa-db-fra.com

Flou rapide sur iOS

J'ai des problèmes pour essayer de brouiller une partie de l'écran dans mon application iOS. Voir l'image pour une meilleure idée de ce que j'essaie de faire. 

BlurBox

Seul le contenu du "BlurBox" doit être flou, mais le reste peut être clair. Donc, si vous regardiez une vue sous forme de tableau, seul le contenu sous le BlurBox serait flou (même si vous faites défiler). Le reste semblerait clair. 

Ma première approche consistait à appeler UIGraphicsGetImageFromCurrentImageContext() tous les 0.01 pour que toutes les couches situées sous le BlurBox soient regroupées en une seule image. Puis brouillez cette image et affichez-la sur tout. 

Les méthodes que j'ai essayées pour le flou sont les suivantes:

https://github.com/tomsoft1/StackBluriOS

https://github.com/coryleach/UIImageAdjust

https://github.com/esilverberg/ios-image-filters

https://github.com/cmkilger/CKImageAdditions

[layer setRasterizationScale:0.25];
[layer setShouldRasterize:YES];

Ainsi que quelques tentatives personnalisées. J'ai également examiné le fichier GLImageProcessing d'Apple, mais je pense que c'est un peu exagéré pour ce que j'essaie de faire ici. 

Le problème est qu’ils sont tous to _ {lent. L'application ne va pas sur l'App Store, donc je suis ouvert à l'utilisation de tout cadre privé/non documenté. 

Une idée lointaine que j’avais était de remplacer la méthode drawRect de tous les composants que j’utilise (UITableViewCells, UITableView, etc.) et de les brouiller indépendamment à la volée. Toutefois, cela prendrait un certain temps. Cela vous semble-t-il une option viable? 


METTRE À JOUR:

J'ai essayé d'utiliser CIFilters comme suit:

CIImage *inputImage = [[CIImage alloc] initWithImage:[self screenshot]];

CIFilter *blurFilter = [CIFilter filterWithName:@"CIGaussianBlur"];
[blurFilter setDefaults];
[blurFilter setValue: inputImage forKey: @"inputImage"];
[blurFilter setValue: [NSNumber numberWithFloat:10.0f]
                           forKey:@"inputRadius"];


CIImage *outputImage = [blurFilter valueForKey: @"outputImage"];

CIContext *context = [CIContext contextWithOptions:nil];

self.bluredImageView.image = [UIImage imageWithCGImage:[context createCGImage:outputImage fromRect:outputImage.extent]];

Cela fonctionne, mais il est incroyablement lent. :(

Je constate que certaines implémentations ne seront floues que lorsque je transmettrai une image chargée à partir du disque. Si je passe dans un UIImage que j'ai créé en utilisant UIGraphicsGetImageFromCurrentImageContext(), cela ne fonctionnera pas. Des idées sur pourquoi cela serait?


METTRE À JOUR:

J'ai essayé la suggestion de patel comme suit:

CALayer *backgroundLayer = [CALayer layer];

CIFilter *blurFilter = [CIFilter filterWithName:@"CIGaussianBlur"];
[blurFilter setDefaults];
backgroundLayer.backgroundFilters = [NSArray arrayWithObject:blurFilter];

[[self.view layer] addSublayer:backgroundLayer];

Cependant, cela ne fonctionne pas :(


MISE À JOUR DEPUIS LA LIMITE AJOUTÉE: _

J'ai réussi à faire fonctionner correctement la BlurBox en utilisant stackblur de TomSoft1 depuis qu'il a ajouté la possibilité de normaliser une image au format RGBA (32 bits/pixel) à la volée. Cependant, c'est encore assez lent. 

J'ai une minuterie qui appelle une mise à jour toutes les 0,03 secondes pour saisir l'image de ce qui se trouve sous le BlurBox, flouter cette image et l'afficher à l'écran. J'ai besoin d'aide pour augmenter les "fps" sur le BlurBox. 

20
random

Je recommanderais Brad Larson 's GPUImage, qui est entièrement soutenu par le GPU pour une grande variété d’effets de traitement d’image. C’est très rapide, et même assez rapide, que dans son application de démonstration, il traite la vidéo en temps réel à partir de la caméra et la cadence de prise de vue est excellente.

https://github.com/BradLarson/GPUImage

Voici un extrait de code que j'ai écrit pour appliquer un fondu de zone flou qui brouille les tiers inférieur et supérieur de l'image tout en laissant le milieu de celle-ci non flou. Sa bibliothèque est extrêmement étendue et contient presque tous les types d’effet de filtre d’image imaginables.

GPUImagePicture *stillImageSource = [[GPUImagePicture alloc] initWithImage:[self screenshot]];

GPUImageTiltShiftFilter *boxBlur = [[GPUImageTiltShiftFilter alloc] init];
        boxBlur.blurSize = 0.5;

[stillImageSource addTarget:boxBlur];

[stillImageSource processImage];

UIImage *processedImage = [stillImageSource imageFromCurrentlyProcessedOutput];
41
brynbodayle

Bien que la réponse puisse être un peu tardive, vous pouvez utiliser les filtres Core Image. La raison pour laquelle il est si lent est cette ligne.

CIContext *context = [CIContext contextWithOptions:nil];

Dans les documents Apple, pour obtenir les meilleures performances dans Core Image, ils déclarent d’abord:

"Ne créez pas d'objet CIContext à chaque rendu . Les contextes stockent beaucoup d'informations d'état; il est plus efficace de les réutiliser."

Ma solution personnelle à cela est de créer un Singleton pour le contexte de l’image de base. Alors je n'en crée qu'un seul.

Mon code est dans ce projet de démonstration sur GitHub.

https://github.com/KyleLopez/DemoCoreImage

N'hésitez pas à l'utiliser ou à trouver une autre solution à votre goût. La partie la plus lente que j'ai trouvée dans CoreImage est le contexte. Le traitement des images est ensuite très rapide.

7
Kyle

Je n’ai pas testé cela, mais je me demande si vous pouvez placer une CALayer où vous voulez que la boîte soit floue, puis trouver une CIFilter utile que vous pouvez définir dans le CALayer'sbackgroundFilters. Juste une pensée.

Voir CALayer.backgroundFilters

1
epatel

Vous pouvez essayer les routines CIFilter (Apple Core Image Filter). Ils nécessitent iOS 5, de sorte que vous ne pourrez peut-être pas les utiliser. 

Je ne sais pas si c'est plus rapide que les méthodes que vous avez essayées, mais je l'ai déjà utilisé dans des projets précédents, et cela fonctionne vraiment bien. Si vous pouvez saisir la partie de l'écran que vous souhaitez rendre floue, placez-la dans une image, passez-la à travers un filtre, puis affichez-la de nouveau à l'endroit approprié sur l'écran, cela devrait fonctionner. 

J'ai utilisé les filtres pour changer les couleurs d'une image en temps réel, et cela a bien fonctionné.

http://developer.Apple.com/library/ios/#DOCUMENTATION/GraphicsImaging/Reference/QuartzCoreFramework/Classes/CIFilter_Class/Reference/Reference.html

0
PaulPerry

Avez-vous essayé cette bibliothèque:

https://github.com/gdawg/uiimage-dsp

Il utilise le framework vDSP/Accelerate et semble facile à utiliser.

BTW: 0.01s semble beaucoup trop rapide. 0,03 devrait faire aussi bien.

0
Codo