Icônes, Images, représentations d'images, ...

AntilogAntilog Membre
07:35 modifié dans API AppKit #1
Salut,

J'ai des problèmes avec les NSImage (ou NSImageRep)...
Voilà , je récupère l'image d'une icône standard de dossier:
NSImage * folderImage = [[[NSWorkspace sharedWorkspace] iconForFileType:NSFileTypeForHFSTypeCode(kGenericFolderIcon)] retain];<br />	[myImageView setImage:folderImage];<br />

J'obtiens une image avec 3 NSImageRep (4 avec Leopard), de tailles 16x16, 32x32, 128x128; par contre, à  l'affichage, il sélectionne par défaut 32x32.
Si je fais un
[folderImage setSize:NSMakeSize(128.0, 128.0)];<br />

par contre, l'image 128x128 est bien affichée

Question N° 1: Puisque l'affichage ne semble pas sélectionner la représentation la plus appropriée de l'image dans ce cas (tous les autres paramètres des différents imageReps sont identiques), est-ce qu'ils ne sont pas inutiles ici? Ca veut dire que je ne pourrais pas profiter du dessin de l'image optimisée à  la taille de mon imageView?

Je voudrais en fait badger cette image: j'utilise le code suivant:
NSImage * folderImage = [[[NSWorkspace sharedWorkspace] iconForFileType:NSFileTypeForHFSTypeCode(kGenericFolderIcon)] retain];<br />	[folderImage setSize:NSMakeSize(128.0, 128.0)];<br />	[folderImage lockFocus];<br />	NSBezierPath *bp = [NSBezierPath bezierPathWithRect:NSMakeRect(0,0,32,32)];<br />	[[NSColor blackColor] set];<br />	[bp fill];<br />	[folderImage unlockFocus];<br />	[myImageView setImage:folderImage];<br />

Ca ne fonctionne pas, le rectangle n'apparaà®t pas; par contre, si je fais:
NSImage * folderImage = [[NSImage alloc] initWithSize:NSMakeSize(128.0, 128.0)];<br />	[folderImage lockFocus];<br />	NSBezierPath *bp = [NSBezierPath bezierPathWithRect:NSMakeRect(0,0,32,32)];<br />	[[NSColor blackColor] set];<br />	[bp fill];<br />	[folderImage unlockFocus];<br />	[myImageView setImage:folderImage];<br />

Le rectangle apparaà®t bien!!! (mais sans l'image, bien sûr) Comment est-ce possible? Je dois faire une erreur idiote, mais je ne vois vraiment pas...

Question subsidiaire: si je badge l'icône, sur quelle représentation ça s'applique? celle qui est "sélectionnée" par le setSize? Celle que le système a choisi par défaut (32x32)? Toutes?

Je nage un peu, j'avoue



Réponses

  • schlumschlum Membre
    07:35 modifié #2
    - (void)lockFocusOnRepresentation:(NSImageRep *)imageRepresentation
    


    Mais il me semble que ça pose plein de problèmes, certaines représentations ne veulent pas qu'on dessine dessus.
  • fouffouf Membre
    novembre 2008 modifié #3
    Tu as essayé en créant une image vierge, puis en dessinant successivement l'icone et le badge ?

    [size=5pt][edit] bouh, la faute d'orthographe[/size]
  • AntilogAntilog Membre
    07:35 modifié #4
    Merci de ta réponse, Schlum!
    J'ai essayé d'utiliser lockFocusOnRepresentation (même sur toutes les représentations de l'image) sans résultat, mon "badge" n'apparaà®t toujours pas.
    Fou de rage, j'ai supprimé toutes les représentations sauf celle à  128x128 avec:
    NSArray * imageReps = [[folderImage representations] copy];<br />	int i;<br />	for (i = 1; i&lt;[imageReps count]; i++)<br />	{<br />		NSImageRep *ir =[imageReps objectAtIndex:i];<br />		[folderImage removeRepresentation:ir];<br />	}<br />
    

    même (absence de) résultat.

    En fait, pour y parvenir, j'ai dû créer une autre image comme ceci:
    NSImage * newFolderImage = [[NSImage alloc] initWithSize:NSMakeSize(128.0,128.0)];<br />	[newFolderImage lockFocus];<br />	[folderImage drawAtPoint:NSMakePoint(0, 0)<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fromRect:NSMakeRect(0, 0, 128.0, 128.0) <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; operation:NSCompositeCopy<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fraction:1.0f];<br />	NSBezierPath *bp = [NSBezierPath bezierPathWithRect:NSMakeRect(0.0,0.0,32.0,32.0)];<br />	[[NSColor blackColor] set];<br />	[bp fill];<br />	[newFolderImage unlockFocus];<br />
    

    Cette fois-ci, l'affichage de newFolderImage dans mon imageView est correcte.

    La seule explication que je vois, c'est comme tu dis que la représentation du départ n'accepte pas que l'on gribouille par dessus le beau dessin d'Apple.
    L'image originale est comme ceci:
    [tt] po folderImage
    NSImage 0x3563f0 Size={512, 512} Reps=(
        NSBitmapImageRep 0x357a10 Size={128, 128} ColorSpace=NSDeviceRGBColorSpace BPS=8 BPP=32 Pixels=128x128 Alpha=YES Planar=NO Format=0,
        NSBitmapImageRep 0x357de0 Size={32, 32} ColorSpace=NSDeviceRGBColorSpace BPS=8 BPP=32 Pixels=32x32 Alpha=YES Planar=NO Format=0,
        NSBitmapImageRep 0x358180 Size={16, 16} ColorSpace=NSDeviceRGBColorSpace BPS=8 BPP=32 Pixels=16x16 Alpha=YES Planar=NO Format=0
    )
    [/tt]
    l'image finale qui s'affiche correctement est comme cela:
    [tt]po newFolderImage
    NSImage 0x357850 Size={128, 128} Reps=(
        NSCachedImageRep 0x356410 Size={128, 128} ColorSpace=NSCalibratedRGBColorSpace BPS=8 Pixels=128x128 Alpha=YES
    )
    [/tt]


  • AntilogAntilog Membre
    07:35 modifié #5
    Merci Fouf,

    j'écrivais la réponse pendant que tu postais, en effet, en redessinant l'icône, puis le badge, ça fonctionne!

    Mais ça ne m'aide pas vraiment à  comprendre  :(
  • schlumschlum Membre
    07:35 modifié #6
    Oui, c'est ce que je disais... quand on essaie de dessiner sur une NSBitmapImageRep déjà  existante, il crée une NSCachedImageRep.
    J'avais eu le problème et trouvé une solution, mais je ne sais plus où c'est et si c'est ici ou sur Macbidouille.  :-\\
  • NoNo Membre
    07:35 modifié #7
    Dans la doc Apple, il est écrit que NSImage et ses NSImageRep doivent être considérés comme immutable.

    Schlum a raison, modifier une image ne fait que modifier son NSCachedImageRep, sorte de cache d'image bitmap utilisé par Cocoa pour accélérer l'affichage.

    Lorsque que tu charges l'image, mais qu'elle n'a pas encore été manipulée graphiquement (cà d affichée), il est possible que le cache soit vide ou n'existe pas encore.
    Ce qui explique pourquoi quand tu dessines dedans, seul le bezierPath apparait, si le cache est utilisé à  ce moment pour l'affichage (ce qui n'est pas garanti puisque le système peut utiliser une autre représentation, et donc détruire le cache avec ton bezier pour créer le nouveau).

    Le mélange d'image (ce que tu fais en voulant dessiner sur une image existante) doit se faire comme Fouf le dit : par l'intermédiaire d'une nouvelle image. Cela est aussi écrit dans la doc.
  • schlumschlum Membre
    07:35 modifié #8
    Tiens, j'ai retrouvé ça dans mes exemples perso de code...
    Pas garanti que ça fonctionne, mais c'est une piste !

    NSGraphicsContext *gc = [NSGraphicsContext graphicsContextWithBitmapImageRep:imRep];<br />	[NSGraphicsContext saveGraphicsState];<br />	[NSGraphicsContext setCurrentContext:gc];<br />	// Dessin...<br />	[NSGraphicsContext restoreGraphicsState];
    
  • AntilogAntilog Membre
    07:35 modifié #9
    Merci à  tous pour vos réponses  o:)

    @schlum: Dans mon cas, ça ne donne rien de plus.

    Je vais donc m'en tenir  à  ce que me disent Fouf et No (et merci de l'explication, No), et donc recréer une nouvelle image et ré-écrire dedans!
  • NoNo Membre
    07:35 modifié #10
    dans 1225646820:

    Tiens, j'ai retrouvé ça dans mes exemples perso de code...
    Pas garanti que ça fonctionne, mais c'est une piste !
    NSGraphicsContext *gc = [NSGraphicsContext graphicsContextWithBitmapImageRep:imRep];<br />	[NSGraphicsContext saveGraphicsState];<br />	[NSGraphicsContext setCurrentContext:gc];<br />	// Dessin...<br />	[NSGraphicsContext restoreGraphicsState];
    



    Schlum, ce code est surtout utile pour 2 raisons :
    - lorsqu'aucun contexte graphique n'est ouvert,
    - si les caractéristiques de l'image divergent de celles du contexte courant (par exemple modification du ppp, qui par défaut est celui de l'écran, soit 72).

    Mais je ne vois pas en quoi il pourrait permettre de modifier une imageRep déjà  existante (et non cachée).
  • schlumschlum Membre
    07:35 modifié #11
    Effectivement, ça devait être un exemple pour autre chose...
    Ceci fonctionne par contre :
    NSBitmapImageRep *imRep = [NSBitmapImageRep imageRepWithData:[NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForImageResource:@&quot;image.tiff&quot;]]];<br />	NSImage *im = [[NSImage alloc] init];<br />	[im addRepresentation:imRep];<br />	[im lockFocusOnRepresentation:imRep];<br />	[[NSColor redColor] set];<br />	[NSBezierPath fillRect:NSMakeRect(20.,20.,50.,50.)];<br />	[im unlockFocus];
    
  • AntilogAntilog Membre
    07:35 modifié #12
    Au fait, j'avais trouvé la solution, mais j'ai omis de poster  >:)

    Pour génèrer la NSCachedImageRep dès le chargement de l'image, sans avoir besoin de l'afficher dans une vue, il suffit de faire:
    [myImage lockFocus];<br />		[myImage unlockFocus];<br />
    

    C'est 100 % efficace  (et c'était même noté dans un coin obscur de la doc Apple...)
Connectez-vous ou Inscrivez-vous pour répondre.