[Résolu] Peut-on écrire son kernel CIFilter sous iOS?
Bonjour,
J'ai essayé d'adapter à iOS mes classes de création personnelle de filtres CIFilter. Je ne trouve pas les bonnes méthodes.
Est-ce possible aujourd'hui d'écrire ses propres filtres CIFilter (ce qui, d'après certaines forums était impossible avant), ou est-ce que je fais fausse route?
Si c'est possible, quel code permet d'utiliser le .kernel avec le filtre? Comment écrit-on le constructeur, et la méthode "outputImage" en clair? (Le compilateur rejette mon code MacOS)
Apparemment, je fais fausse route, mais sait-on jamais? Merci par avance pour vos posts.
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
D'après ce que je vois, CIKernel existe depuis iOS 8. Ce qui correspond à mon souvenir: dans le temps, ce n'était pas possible, mais dans les versions récentes d'iOS, ça l'est.
Voir la rubrique "Creating Custom Filters" de Core Image Programming Guide.
Merci Céroce.
Mais les méthodes suivantes posent problème (voir commentaires):
Celle-ci est rejetée tout simplement :
le compilateur refuse "apply".
Qu'utilisez-vous pour :
- bien faire prendre en compte votre kernel par le CIFilter?
- en sortir l'image traitée?
Merci par avance.
Pour le premier warning, il faut juste utiliser la méthode de NSString qui va bien (par ex. +stringWithContentsOfFile:encoding:error).
Alors, du coup j'ai cherché... et la doc concerne OS X, sans avoir été mise à jour pour iOS, on dirait.
C'est expliqué dans la session 515 de la WWDC 2014.
La transcription:
http://asciiwwdc.com/2014/sessions/515
Les diapos:
http://devstreaming.apple.com/videos/wwdc/2014/515xxv01d9tcg3o/515/515_developing_core_image_filters_for_ios.pdf
Sur une des diapos, on a cet extrait de code: (dans une sous-classe de CIFilter)
Merci Céroce pour tes posts toujours hyper bien informés!
J'ai un problème pour le CIKernel : je préfèrerais utiliser un fichier .cikernel comme d'habitude.
En plus, lorsque je copie mon .cikernel dans la méthode "kernelWithString:", le compilateur "croit" que la string s'arrête à la première accolade (après la parenthèse contenant les paramètres), et ignore donc le code (le code cesse d'être écrit en rouge après l'accolade). En fait, il rejette l'ensemble par conséquent.
Je progresse mais n'y suis pas encore...
Bon, le compilateur met un warning pour "NSString stringWithContentOfFile" ou "initWithContentOfFile", mais cela a l'air de marcher quand même...
Par contre, le filtre ne marche pas. j'ai ceci dans la console (le code n'est pas exécuté) :
or la méthode sans roiCallback est inconnue du compilateur.
ma méthode :
Je ne sais pas ce que veut dire cet accent circonflexe devant les arguments de "CIKernelROICallback". Le savez-vous? (encore une subtilité du C que j'ignore sans doute...)
Ben c'est une closure (un "block"), quoi. C'est normal, c'est une callback, le code sera exécuté plus tard.
Oui, j'ai lu la doc, mais ne l'ai que moyennement comprise... Du coup j'oubliais de recopier les "dispatch_once_t", que j'ai fini par recopier bêtement, je l'avoue.
Mon filtre marche :
Par rapport à MacOS, on simplifie beaucoup. On ne garde que deux méthodes, celle du CIKernel, et celle de imageOutput. Bon, on va pouvoir s'amuser!!
Merci infiniment Céroce!
(Comment met-on "résolu" dans le titre du sujet déjà ?)
Entre nous soit dit, le pps/pdf Apple mis en lien par Céroce est passionnant, je vous le conseille vivement. Je le conserve dans mes docs perso.
Je suis en train de faire une routine de type valeurs rgb > hsb car je travaille à partir du hsb.
Deux questions :
- je n'ai pas vu dans la doc OpenGL de méthode de conversion automatique. Y en t-il une?
- sinon, est-il possible d'utiliser à chaque fois le même fichier .cikernel dans différents filtres, en chaà®nant par exemple : kernelRgbToHsb > kernelMonEffet > kernel HsbToRgb dans un CIFilter, ou bien en appelant des CIFilter "conversion" dans un CIFilter?? Cela me semble être hasardeux... Sans doute vaut-il mieux recopier le code d'un .cikernel à l'autre?
PS : la doc précitée m'apporte un début de réponse avec l'exemple du kaléidoscope. Ceci dit, il me faudrait les valeurs hsb de l'image entrante et de une ou deux CIColors avant l'effet...
Le code que tu mets dans ton fichier .cikernel " qui est un simple fichier texte " est compilé à la volée.
Tu peux:
- créer une nouvelle instance de CIKernel avec le même code
- sans doute partager l'instance de CIKernel (ce qui évite de compiler à nouveau)
Dans l'univers GLSL, certains vont jusqu'à assembler plusieurs fichiers texte pour créer le shader final. ça évite le code conditionnel " les conditions rendent le code GPU très lent.
Effectivement, la conversion suppose de multiples comparaisons. La doc CIKernel explique que les if, etc. peuvent ne pas être pris en compte :
J'ai l'impression que si je veux travailler en hsb, j'ai intérêt à passer par CGImage, en utilisant par exemple ton cours "BitmapEffets" et en le complétant... Comme cela, on code en C, ce qui sera peut-être aussi bien.
Je porte sous iOS mon soft MacOS "Harmony of Colors", qui utilisait NSBitmapImageRep et les valeurs hsb de NSColor. Je gagnerai du temps en restant en C je pense... (même si j'aime beaucoup les filtres CoreImage).
Code source de conversion, ou plutôt formules à employer ici :
http://www.rapidtables.com/convert/color/rgb-to-hsv.htm
On ne peut donc pas lire ou écrire directement dans la bitmap en HSL, et tu devais sans doute déjà travailler en RVB. On peut créer une UIColor avec des composants HSL, comme pour NSColor.
Core Image a ses défauts:
- ne peut pas travailler sur un thread secondaire (à cause d'OpenGL).
- lent.
Mais il a deux grandes qualités:
- relativement facile à mettre en oe“uvre
- les effets de base sont de qualité
- GLSL est mieux adapté au traitement d'image que le C.
Si tu ne fais que des effets à l'écran, qui ne sont pas trop lourds, alors Core Image s'impose.
Tu édites ton premier post avec l'éditeur complet et çà te permet de modifier le titre...
Je suis finalement en train de bosser à partir de CGImage. Je n'ai pas testé, mais vu le code de hsb2rgb qui utilise un switch, j'ai préféré renoncer pour ce projet à CIFilter. Les premiers tests sont corrects, il y a peu de traitement d'images à appliquer, juste une modification des couleurs, et le résultat est immédiat.
Je garde mon test CIImage par contre, il me servira je n'en doute pas. Merci beaucoup en tous les cas.
Un code C "qui marche" pour rgb > et l'inverse (en C++) :
http://stackoverflow.com/questions/3018313/algorithm-to-convert-rgb-to-hsv-and-hsv-to-rgb-in-range-0-255-for-both
if it can help...
Merci à tous.
On trouve du code tout fait:
http://lolengine.net/blog/2013/07/27/rgb-to-hsv-in-glsl
Justement sans branchement.
Pour ceux que ça intéresse en dehors de moi, jetez un oe“il sur ce que certains parviennent à faire avec seulement des fragment shaders:
https://www.shadertoy.com
(il n'y a pas de polygones envoyés à la GPU, et tous les calculs sont effectués par la GPU).
Je ne cherche pas à te convaincre que c'est la bonne solution dans ton cas, seulement qu'il y a un univers entier à explorer !