[RESOLU] CGImage à  partir d'un pasteboard

Philippe49Philippe49 Membre
janvier 2008 modifié dans API AppKit #1
J'ai de nouveau un problème avec les CGImage :

-(IBAction)paste:(id) sender<br />{<br />	// On récupère le general pasteboard<br />	NSPasteboard *pb = [NSPasteboard generalPasteboard];<br />	NSString * type=[pb availableTypeFromArray:[NSImage imageUnfilteredPasteboardTypes]];<br /><br />	<br />	if(type==nil) { <br />		return;<br />	} else {<br />		fprintf(stderr,&quot;%s&#092;n&quot;, [type UTF8String]);<br />	}	<br /><br />	// on récupère le data<br />	NSData *&nbsp; data=[pb dataForType:type];<br />	CFDataRef dataRef=(CFDataRef) data;<br />	if(dataRef){<br />		fprintf(stderr,&quot;Length of data : %d&#092;n&quot;,CFDataGetLength(dataRef));<br />	} else {<br />		fprintf(stderr,&quot;dataRef not created&#092;n&quot;);<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return;<br />	}<br /><br /><br />	// on en fait une image source<br />	CGImageSourceRef imageSourceRef=CGImageSourceCreateWithData(dataRef, NULL);<br />	if(imageSourceRef){<br />		fprintf(stderr,&quot;status of imageSourceRef : %d&nbsp; (kCGImageStatusComplete=0) &#092;n&quot;,CGImageSourceGetStatus(imageSourceRef));<br />		NSLog(@&quot;%@&quot;,(NSDictionary*) CGImageSourceCopyProperties(imageSourceRef,NULL));<br />	}<br />	<br />	// on en fait une image<br />	CGImageRef imageRef=CGImageSourceCreateImageAtIndex(imageSourceRef, 0, NULL); <br />	if(imageRef){<br />		fprintf(stderr,&quot;%d&#092;n&quot;,CGImageGetWidth(imageRef));		<br />	} else { <br />		fprintf(stderr,&quot;imageRef not created&quot;);<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return;<br />	}<br />	<br />	// utilisation<br />	CFRelease(imageSourceRef);<br />	rootLayer.contents = (id) imageRef;<br />	CGImageRelease(imageRef);<br />}


Résultat
Tout a l'air de fonctionner jusqu'à  la création de la CGImage

Apple PICT pasteboard type
Length of data : 334364
status of imageSourceRef : 0  (kCGImageStatusComplete=0)
2008-01-05 09:59:35.655 Drag_Drop01[493:10b] {
    FileSize = 334364;
}
imageRef not created



Le passage par CGImageSource est recommandé par Apple et il a fonctionné jusqu'à  maintenant. (voir par exemple le dragging destination)


On peut faire ainsi ;
// NSImage * image=[[NSImage alloc] initWithPasteboard:pb] ;
// NSBitmapImageRep * bitmapImageRep=(id)[image bestRepresentationForDevice:nil];
// CGImageRef imageRef=[bitmapImageRep CGImage] ;
// rootLayer.contents = (id)imageRef;
// [image release];
// CGImageRelease(imageRef);

mais le [image release] crée un problème mémoire (la CGImage se sert sans doute de la NSImage comme imageSource (dataProvider dans l'ancien modèle))

Réponses

  • janvier 2008 modifié #2
    Tu avais une image PICT dans le presse-papier plutôt qu'une gif/tiff/jpeg ? Je dis peut être des conneries mais en regardant la doc de NSImage on remarque que le type PICT à  une représentation de classe différente donc il est reconnu par NSImage mais ne peut l'être par CIImage. D'où l'absence de méthode -CIImage.

    Quand tu dis "recommandé par Apple", est-ce que tu peux citer tes sources ?

    dans 1199523855:

    On peut faire ainsi ;
    // NSImage * image=[[NSImage alloc] initWithPasteboard:pb] ;
    // NSBitmapImageRep * bitmapImageRep=(id)[image bestRepresentationForDevice:nil];
    // CGImageRef imageRef=[bitmapImageRep CGImage] ;
    // rootLayer.contents = (id)imageRef;
    // [image release];
    // CGImageRelease(imageRef);

    mais le [image release] crée un problème mémoire (la CGImage se sert sans doute de la NSImage comme imageSource (dataProvider dans l'ancien modèle))


    Pourquoi CGImageRelease(imageRef); ?
    Tu ne dois faire un release que sur un object que tu as créé or ici, imageRef vient de [bitmapImageRep CGImage] qui est autoreleasé.
  • Philippe49Philippe49 Membre
    janvier 2008 modifié #3
    dans 1199525695:

    Tu avais une image PICT dans le presse-papier plutôt qu'une gif/tiff/jpeg ? Je dis peut être des conneries mais en regardant la doc de NSImage ou remarque pour le type PICT à  une représentation de classe différent donc peut être que reconnu par NSImage mais pas par CIImage. Il n'y a pas de méthode -CIImage sur NSPICTImageRep.


    C'est le résultat d'un "copy" dans "aperçu"

    Ah. C'est une piste. Pour moi, NSImage ne devrait pas être plus élaboré que CGImage qui est de plus bas niveau ?


    dans 1199525695:

    Quand tu dis "recommandé par Apple", est-ce que tu peux citer tes sources ?
    The CGDataProvider opaque type abstracts the data-access task and eliminates the need for an application to manage data through a raw memory buffer. You can use data provider objects to obtain image or PDF data, and all, except for CGDataProviderCreateWithCFData, are available in Mac OS X v10.0 or later.

    Dans la doc CGDataProvider reference (overview), on lit

    If your application runs in Mac OS X v10.4 or later, you should use CGImageSource objects rather than data providers. See CGImageSource Reference.

    dans 1199525695:

    Pourquoi CGImageRelease(imageRef); ??

    Autant pour moi, un copier-coller mécanique : effectivement, ici [bitmapImageRep CGImage]  renvoie en autorelease.
    Cela marche en le retirant, sans fuite mémoire.


    Je vais le prendre ainsi, mais je suis déçu que cela ne marche pas avec le CGImageSource : Je m'étais inspiré d'un exemple distribué par Apple (GeekGameBoard).


  • Philippe49Philippe49 Membre
    20:38 modifié #4
    Ah oui, voilà  pourquoi j'avais abandonné la version NSImage

    Lors d'un copier-coller sur une grande portion d'image (valeur de 2-3 Mo qui dans le moniteur d'activités passe à  20 Mo, mémoire réelle) , cela plante, alors que mon code via le data lui résiste bien.
  • Philippe49Philippe49 Membre
    20:38 modifié #5
    Cela plante si on fait [image release], mais ne plante plus sans ce [image release], mais alors on passe à  73Mo dans le moniteur d'activité.
  • Philippe49Philippe49 Membre
    20:38 modifié #6

    Résolu : il suffit de boucler sur tous les types proposés par le general pasteboard
  • 20:38 modifié #7
    Bein non, ce n'est pas possible, il y a obligatoirement quelque chose d'autre...
  • Philippe49Philippe49 Membre
    20:38 modifié #8
    Ben, pourquoi non ?

    Le general pasteboard propose 4 ou 5 types, le premier étant "public.tiff" et cela passe en l'état.

    ceci dit c'est pas beau je te l'accorde ... (de guitare)
  • psychoh13psychoh13 Mothership Developer Membre
    20:38 modifié #9
    Tu sais que NSPasteBoard propose la méthode :
    - (NSString *)availableTypeFromArray:(NSArray *)types
    


    Qui retourne le premier type de NSArray qu'il trouve dans tous les types proposés par le pasteboard ?

    Il te suffit donc de faire un NSArray avec un seul élément qui sera la NSString de ton type et si le retour de la fonction n'est pas nul c'est qu'il a été trouvé. Ensuite tu utilises la méthode
    - (NSData *)dataForType:(NSString *)dataType
    
    avec la même NSString que t'as passé à  ton NSArray pour récupérer les bonnes données.
  • Philippe49Philippe49 Membre
    janvier 2008 modifié #10
    Oui, c'est ce que je faisais au départ, mais il renvoie alors un format PICT que CGImage ne sait pas initialiser

    remontes un peu dans le post

    Le code utilisé est ici.

    à  moins que CGimage ne fournisse  les types qu'il est susceptible de gérer ?
  • Philippe49Philippe49 Membre
    janvier 2008 modifié #11
    Comme

    CGImageSourceCopyTypeIdentifiers
    Returns an array of uniform type identifiers (UTIs) that are supported for image sources.

    CFArrayRef CGImageSourceCopyTypeIdentifiers (
       void
    );
    Return Value
    Returns an array of the UTIs that are supported for image sources.


    NSLog(@%@",(NSArray*) CGImageSourceCopyTypeIdentifiers());

    2008-01-05 20:34:19.993 Drag_Drop01[2318:10b] (
        "public.png",
        "public.jpeg",
        "com.compuserve.gif",
        "public.jpeg-2000",
        "com.nikon.raw-image",
        "com.leafamerica.raw-image",
        "com.hasselblad.fff-raw-image",
        "com.hasselblad.3fr-raw-image",
        "com.pentax.raw-image",
        "com.sony.arw-raw-image",
        "com.adobe.raw-image",
        "public.tiff",
        "com.apple.icns",
        "com.canon.crw-raw-image",
        "com.canon.cr2-raw-image",
        "com.canon.tif-raw-image",
        "com.sony.raw-image",
        "com.olympus.raw-image",
        "com.konicaminolta.raw-image",
        "com.panasonic.raw-image",
        "com.fuji.raw-image",
        "com.adobe.photoshop-image",
        "com.adobe.pdf",
        "com.adobe.illustrator.ai-image",
        "com.microsoft.ico",
        "com.microsoft.bmp",
        "public.xbitmap-image",
        "com.microsoft.cur",
        "com.apple.pict",
        "com.truevision.tga-image",
        "com.sgi.sgi-image",
        "com.apple.quicktime-image",
        "com.kodak.flashpix-image",
        "com.apple.macpaint-image",
        "com.ilm.openexr-image",
        "public.radiance"
    )

  • Philippe49Philippe49 Membre
    janvier 2008 modifié #12
    <3 <3 <3 <3 <3 <3 <3 <3 <3 <3 <3 <br /> ::) ::) ::) ::) ::) :o Fectivement, cela marche ainsi, et c'est tout beau  :o ::) ::)  ::) ::) ::)
    :kicking: :kicking: :kicking: :kicking: :kicking: :kicking: :kicking: :kicking: :kicking: :kicking: :kicking: :kicking: :kicking: :kicking: :kicking: :kicking: :kicking: :kicking:
  • psychoh13psychoh13 Mothership Developer Membre
    20:38 modifié #13
    Tous ces types... ça en devient presque indécent. :D
Connectez-vous ou Inscrivez-vous pour répondre.