Créer/Affecter une CGImageRef
Philippe49
Membre
Quelqu'un a une idée ?
Je construit une CGImageRef
NSString * imagePath=[NSHomeDirectory() stringByAppendingString:@/Pictures/aquadavinci_ii.jpg];
NSData * imageData =[NSData dataWithContentsOfURL:[NSURL fileURLWithPath:imagePath]];
NSBitmapImageRep * bitmapImageRep=[NSBitmapImageRep imageRepWithData:imageData];
imageRef=[bitmapImageRep CGImage]; // déclarée : CGImageRef imageRef;
Je l'affecte à la property contents d'un CALayer dont la doc est :
@property(retain) id contents
Discussion
A layer can set this property to a CGImageRef to display the image as its contents. The default value is nil.
imageLayer.contents=imageRef;
Et il me jette à la figure un :
Warning : passing argument 1 of setContents from incompatible pointer type]
Question 2:
Il n'y a pas plus court pour créer une CGImageRef à partir d'un fichier jpg ?
Je construit une CGImageRef
NSString * imagePath=[NSHomeDirectory() stringByAppendingString:@/Pictures/aquadavinci_ii.jpg];
NSData * imageData =[NSData dataWithContentsOfURL:[NSURL fileURLWithPath:imagePath]];
NSBitmapImageRep * bitmapImageRep=[NSBitmapImageRep imageRepWithData:imageData];
imageRef=[bitmapImageRep CGImage]; // déclarée : CGImageRef imageRef;
Je l'affecte à la property contents d'un CALayer dont la doc est :
@property(retain) id contents
Discussion
A layer can set this property to a CGImageRef to display the image as its contents. The default value is nil.
imageLayer.contents=imageRef;
Et il me jette à la figure un :
Warning : passing argument 1 of setContents from incompatible pointer type]
Question 2:
Il n'y a pas plus court pour créer une CGImageRef à partir d'un fichier jpg ?
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Tous les types référence déclaré en C (CGImageRef, CGColorSpaceRef, etc.) sont capables de recevoir des messages Objective-C, ils correspondent à des id eux aussi.
Pour la question 2, tu peux te tourner du côté de la fonction : CGImageCreateWithJPEGDataProvider()
Le classique du genre :
Moins de lignes, plus rapide, mais pas forcément plus clair au sein du code Obj-C/cocoa.
.
Effectivement, le cast élimine le warning.
Mais avec cette précision, je ne comprends plus : toute sous-classe de NSObject n'est-elle pas compatible avec (id) ?
D'ailleurs pour pour CGImageRef, il faut importer <ApplicationServices/ApplicationServices.h>
ça m'étonne NS et CF accolés ; ça n'avait jamais été fait encore ça !
Merci
NSCFType est une classe cocoa (de Foundation) aussi vieille que...
Elle est une des pierres angulaire du tool-free bridging entre CoreFoundation et cocoa.
Cette classe (du moins ses instances) permet d'utiliser pleinement le runtime Obj-C sur des CFType.
Par exemple un [CFType release] sera transformé en CFRelease(CFType).
.
[Edit] Si, en fait ça apparaà®t dans le binaire de Foundation... Mais dans aucun des headers.
Par exemple, quand tu utilises la classe NSString, tu ne crées jamais d'instance de NSString directement, tout simplement parce que c'est une classe abstraite et qu'elle est incapable de stockée quoique ce soit. Par contre, les méthodes d'allocations vont créer des objets de type NSCFString qui est une sous-classe de NSString, et qui correspond exactement à une CFString.
Tout simplement parce que CGImageRef N'est PAS un objet Objective-C, il s'agit d'un pointeur sur une structure C :
typedef struct CGimage *CGImageRef;
Mais le C est très laxiste, tu peux facilement faire passer une structure pour un objet Objective-C, il suffit simplement que certains points correspondent...
Voilà comment tu peux procéder, par exemple je voudrais créer un type d'entier sous forme d'objet mais à la manière des CFType.
Pour refaire ce système, il faut une classe privée qui va représenter tous les objets, et tous le stypes que l'on veut faire passer pour des objets, voici un petit code amusant :
Voici le code de test :
Bon vous aurez plein de warning, mais ça fonctionnera et vous aurez comme résultat :
Je pensais que l'identification entre la structure C des types CF et l'objet NS correspondant suffisait pour le toll-free bridging.
Puisqu'en interne de toute façon, que ça soit structure, objet Obj-C ou objet C++, même combat.
(mais c'est vrai qu'il faut aussi que ça fonctionne dans l'autre sens : transformer les appels de méthodes en appels de fonctions C, sinon le pont est à sens unique).
(regarde mon message précédent je l'ai éditée pour ajouter une simulation de type C correspondant à une classe Objective-C.)
Les classes NSCF sont utiles pour le toll-free bridging de CoreFoundation vers cocoa.
Dans la plupart des cas, le toll-free bridging sert de cocoa vers CF (genre je créé un objet cocoa, je caste, puis je lui applique une fonction CF).
Les NSCF permettent exactement l'inverse : je créé un CFType (dans CF), puis je caste en id, enfin je l'utilise comme un objet cocoa (donc je lui envoie des messages).
.
ça permet notamment d'utiliser sans contraintes les messages retain/release/autorelease.
Oui, ça s'appelle le... toll-free bridging (Sens CF -> Cocoa ; voir message de Bru ci-dessus)
Non, le toll-free bridging permet seulement d'utiliser un CFString comme une NSString et vice-versa, ou bien un NSDictionary comme un CFDictionary. C'est-à -dire qu'à chaque méthode correspond exactement la même fonction qui peut s'utiliser sur les deux types d'objets.
Moi je parle de pouvoir utiliser certaines fonctionnalités disponible dans Cocoa sur n'importe quel type CF... CG... etc. Sans qu'il y ait pour autant une correspondance total avec une quelconque classe publique.
Exemple ?
J'ai du mal à suivre là ...
Les types NSCF correspondent exactement aux types "interchangeables"
http://developer.apple.com/documentation/Cocoa/Conceptual/CarbonCocoaDoc/Articles/InterchangeableDataTypes.html
J'ai l'impression que ce dont tu parles fait aussi partie du toll-free bridging.
Certains CFType n'ont pas d'équivalent cocoa, donc pas de toll-free bridging.
Mais pour pouvoir utiliser ces CFType sous cocoa, une pseudo-classe (NSCF) est alors implantée pour avoir à nouveau la possibilité de faire du tool-free bridging.
.
Sur n'importe quel CF*Ref via un cast (id) par exemple ?
J'ai déjà vu plus propre comme programmation quand même ???
Je serais curieux de lire ce que tu nommes "cadre du toll-free bridging".
Le pur toll-free bridging c'est ce qu'a dit Psycho, c'est d'avoir une "structure" qui passe pour un objet cocoa ou pour un CFtype indifféremment.
Les classes NSCF font parties du mécanisme toll-free bridging. Mais pour les CFTypes qui n'ont pas d'équivalent sous cocoa (par exemple NSBundle/CFBundle), une pseudo-classe NSCF est utilisée.
Ces pseudo-classes ne permettent pas de se substituer au CFtype sous-jacent (il sera toujours obligatoire d'utiliser les fonctions propres à ce type, car pas d'équivalent en méthode cocoa).
il y a des avantages à utiliser parfois les NSCF : par exemple c'est de pouvoir utiliser l'autoreleasepool sur ces CFType via leur déguisement en NSCF (il n'y a pas d'autoreleasepool dans CoreFoundation).
Enfin, "programmation propre" : c'est un vaste débat !
.
Alors que pour les CFTypes qui n'ont pas de correspondance en Objective-C, la seule chose qu'ils ont (à priori) c'est le champ de type Class permettant au runtime de les utiliser comme des objets.
Sinon, je parlerais pas de programmation propre mais plutôt de facilitation, les frameworks Apple sont conçus pour permettre une pleine et entière utilisation de la programmation orientée-objet dans le carde C/Objective-C.
La question que je me pose ci, c'est y a-t-il physiquement un objet créé en proxy pour la CGImageRef ? ou est-ce que c'est à l'adresse en dur que la référence est prise ?
Quand au warning quelle est sa raison d'être:
Oui, c'est exactement ça... C'est les équivalences données par la doc "InterchangeableDataTypes" (lien donné au dessus)
Je ne comprends pas très bien la question là . Regarde l'exemple que j'ai donné plus haut, c'est-à -dire comment créer un type C ...Ref à la manière d'Apple.
Quand tu utilises une classe Objective-C normale, le compilateur sait qu'il s'agit d'un type utilisable dans les messages, en revanche, quand tu utilises un CFType, le compilateur tout ce qu'il voit c'est qu'il s'agit d'un pointeur sur une structure, et pas d'une vraie classe... Il ne sait pas que derrière, l'implémenteur du type a placé un champ de type Class utilisable par le runtime Objective-C, donc dans le doute il met un avertissement "attention ce type peut ne pas être utilisé par le runtime".
-> NSURL NSCFType
Ceci-dit, s'il "crée" une pseudo-instance, comment l'utilisation de l'AutoReleasePool s'appliquerait-elle au type CF initial ? La pseudo instance gère les deux structures ?
Ce qui voudrait dire que ce code est correct :
(c'est ça que j'appelle du code pas très propre )
Non, le mécanisme du tool-free bridging ne fonctionne pas comme ça.
Disons que chaque structure C (opaque) CFType commence par un pointeur non-utilisé par les fonction CF, mais qui se nomme isa...
La structure C d'un objet Obj-C commence aussi par un pointeur isa...
Voilà le secret du bridging !
Bon c'est plus complexe que ça, mais la base est là : la même structure peut être utilisée par les 2 environnements CF et Obj-C...
.
Cela réponds à ma question 2
Maintenant, il me reste à lire/étudier le code de Psychoh qui m'a l'air particulièrement instructif
Dans le debugger, si je fais un "p bundle->isa", j'obtiens ça :"There is no member named isa".
C'est parce qu'il n'est pas capable d'aller le récupérer ? ???
[Edit]
Effectivement, même adresse pour les deux :
Bravo l'économie mémoire :P
J'ai simplifié mes explications pour la clarté du propos.
Chaque structure CFType commence par une structure CFRuntimeBase (c'est elle qui contient le "membre isa").
Je ne me souviens plus du nom de la structure dans CFType.
Et c'est hautement non documenté...
Faut fouiller dans les sources Darwin (où le framework CF est en open) pour en savoir plus.
.