Problème troublant avec CoreGraphics

psychoh13psychoh13 Mothership DeveloperMembre
20:21 modifié dans API AppKit #1
Bonjour à  tous,
Voilà  un problème qui a été exposé sur les forums de discussion d'Apple dans la section développement.
Voici son problème : dans une application de type Standard Tool (donc un truc de base), il  cherchait à  l'aide de CoreGraphics à  dessiner un carré coloré sur son écran. L'ennuie c'est qu'alors que son carré devait être de couleur rouge, il se retrouve de couleur cyan...
J'ai moi-même fait le test et j'ai les mêmes résultats, voici mon code (simplification de son code) :

/* main.c */<br />#import &lt;ApplicationServices/ApplicationServices.h&gt;<br /><br />int main (int argc, const char * argv&#91;])<br />{<br />&nbsp; &nbsp; CGContextRef ctx;<br />&nbsp; &nbsp; CGDirectDisplayID display = CGMainDisplayID();<br />&nbsp; &nbsp; CGDisplayCapture(display);<br />&nbsp; &nbsp; ctx = CGDisplayGetDrawingContext(display);<br /><br />&nbsp; &nbsp; CGContextSetRGBFillColor(ctx, 1, 0, 0, 1);<br />&nbsp; &nbsp; CGContextFillRect(ctx, CGRectMake(200, 200, 500, 500));<br />&nbsp; &nbsp; <br />&nbsp; &nbsp; while(1);<br />&nbsp; &nbsp; <br />&nbsp; &nbsp; return 0;<br />}


Le while(1); c'est pour avoir le temps de regarder l'écran, pour fermer l'application un cmd + option + esc suffit.

Alors, quelques petits tests me donnent les résultats suivant :
  • La composante alpha se comporte tout à  fait normalement
  • Le Bleu est toujours à  fond quoiqu'il arrive : [0, 0, 0, 1] devrait donner Noir, ça donne Bleu
  • Le Rouge se comporte comme du Vert : [1, 0, 1, 1] (ou [1, 0, 0, 1] ici puisque le Bleu est toujours à  fond) devrait donner Magenta mais donne Cyan
  • Le Vert se comporte comme du Rouge : [1, 0, 1, 1] (ou [1, 0, 0, 1] ici puisque le Bleu est toujours à  fond) devrait donner Cyan mais donne Magenta
  • Donc au final pour obtenir du blanc il suffit de mettre ces valeurs : [1, 1, 0, 1] ou bien encore [1, 1, 1, 1]


Quelqu'un saurait-il pourquoi CG se comporte comme ça ? Et quelqu'un aurait-il la solution ?
Merci

PS : Si on utilise la méthode CGContextSetCMYKFillColor() donc avec les composantes Cyan, Magenta, Jaune, Noir et Alpha, on retrouve le même problème, le Bleu est toujours à  fond...

Réponses

  • schlumschlum Membre
    20:21 modifié #2
    Ton code est à  peu de choses près celui qu'on peut trouver ici :
    http://developer.apple.com/documentation/GraphicsImaging/Conceptual/QuartzDisplayServicesConceptual/Articles/DisplayCapture.html
    (ils dessinent du texte et font les tests d'erreur, mais en gros, c'est la même chose)

    Et effectivement, si on essaie d'avoir du rouge, on obtient du cyan.

    À mon avis, c'est du au "ColorSpace" de l'écran qui doit être spécial, et c'est assez chaud de dessiner directement sur l'écran.

    Quand je veux faire du fullscreen, je fais ce qu'ils conseillent sur la note de cette page : une fenêtre borderless qui couvre tout l'écran, tout en capturant tous les displays ; ça fonctionne très bien et pas de problème de colorSpace  :)

    Ou alors... OpenGL
  • schlumschlum Membre
    octobre 2007 modifié #3
    *** À effacer, merci ***
  • schlumschlum Membre
    octobre 2007 modifié #4
    Le fin mot de l'histoire :
    http://fr.wikipedia.org/wiki/Pixel#Taille_m.C3.A9moire_d.27un_point

    Il n'y a pas d'alpha au niveau de l'écran... Les 8 derniers bits de chaque point ne sont pas utilisés !
    L'ordre, c'est :
    bits 1-8 -> bleu
    bits 9-16 -> vert
    bits 17-24 -> rouge
    bits 25-32 -> inutilisé


    Donc là , je dessine un carré rouge directement dans le buffer de l'écran :

    #import &lt;ApplicationServices/ApplicationServices.h&gt;<br /><br />int main (int argc, const char * argv&#91;])<br />{<br />	CGDirectDisplayID display = kCGDirectMainDisplay; // 1<br />	CGError err = CGDisplayCapture (display); // 2<br />	if (err == kCGErrorSuccess)<br />	{<br />		CGContextRef ctx = CGDisplayGetDrawingContext (display); // 3<br />		if (ctx != NULL)<br />		{<br />			int i,j;<br />			void *pix;<br />			char col[4] = {0,0,255,0};<br />			for(j=0;j&lt;255;++j) {<br />				for(i=0;i&lt;255;++i) {<br />					pix = CGDisplayAddressForPosition(display,100+i,100+j);<br />					memcpy(pix,col,4);<br />				}<br />			}<br />			sleep (1); // 5<br />		}<br />		CGDisplayRelease (display); // 6<br />	}<br />&nbsp; &nbsp; return 0;<br />}
    


    (et avec CGContextSetRGBFillColor on ne peut rien faire parce qu'il gère le alpha)
  • psychoh13psychoh13 Mothership Developer Membre
    20:21 modifié #5
    Oui je sais comment sont représentés les couleurs en mémoire, mais c'est quand même bizarre que les fonctions de gestion graphique d'Apple fournissent de mauvaises informations à  la carte graphique... Je veux bien croire que la composante alpha se fasse passer pour du bleu, mais quand on la met à  zéro aucune couleur ne s'affiche, je trouve ça tout de même bizarre...
  • schlumschlum Membre
    20:21 modifié #6
    CoreGraphics n'est apparemment pas fait pour travailler directement avec le contexte de l'écran. ??? Il est capable de fournir un buffer par contre...
  • Eddy58Eddy58 Membre
    20:21 modifié #7
    Et en forçant la création des couleurs avec CGColorSpace ?? :o

    /* main.c */<br />#import &lt;ApplicationServices/ApplicationServices.h&gt;<br /><br />int main (int argc, const char * argv&#91;])<br />{<br />&nbsp; &nbsp; CGContextRef ctx;<br />&nbsp; &nbsp; CGDirectDisplayID display = CGMainDisplayID();<br />&nbsp; &nbsp; CGDisplayCapture(display);<br />&nbsp; &nbsp; ctx = CGDisplayGetDrawingContext(display);<br /><br />&nbsp; &nbsp; // Et en forçant avec CGColorSpace ??<br />&nbsp; &nbsp; float opaqueRed[4]={1.0,0.0,0.0,1.0};<br />&nbsp; &nbsp; CGColorRef red=CGColorCreate(CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB),opaqueRed);<br />&nbsp; &nbsp; CGContextSetShouldAntialias(ctx,FALSE);<br />&nbsp; &nbsp; CGContextSetFillColorWithColor(ctx,red);<br /><br />&nbsp; &nbsp; CGContextFillRect(ctx, CGRectMake(200, 200, 500, 500));<br />&nbsp; &nbsp; <br />&nbsp; &nbsp; while(1);<br />&nbsp; &nbsp; <br />&nbsp; &nbsp; return 0;<br />}<br />
    

  • schlumschlum Membre
    octobre 2007 modifié #8
    Déjà  essayé tout ce qui a trait aux colorSpaces, ça ne change rien... L'écran c'est très particulier quand même  ???
  • schlumschlum Membre
    20:21 modifié #9
    Le pire c'est que c'est super-lent en plus  :P
    Si vous voulez simuler un KP bleu  :o

    #import &lt;ApplicationServices/ApplicationServices.h&gt;<br /><br />int main (int argc, const char * argv&#91;])<br />{<br />&nbsp; &nbsp; CGDirectDisplayID display = CGMainDisplayID();<br />&nbsp; &nbsp; CGDisplayCaptureWithOptions(display,kCGCaptureNoFill);<br />	CGDisplayHideCursor(display);<br />	<br />	CGContextRef ctx = CGDisplayGetDrawingContext(display);<br />	<br />	CGSize size = CGDisplayBounds(display).size;<br />	<br />	CGContextSetRGBFillColor(ctx, .5, .5, .5, .5);<br />&nbsp; &nbsp; CGContextFillRect(ctx, CGRectMake(0, 0, size.width, size.height));<br />	<br />	CGContextFlush(ctx);<br />	CGContextSynchronize(ctx);<br />&nbsp; &nbsp; <br />&nbsp; &nbsp; sleep(10);<br />	<br />	CGDisplayShowCursor(display);<br />	CGDisplayRelease(display);<br />&nbsp; &nbsp; <br />&nbsp; &nbsp; return 0;<br />}
    
  • psychoh13psychoh13 Mothership Developer Membre
    20:21 modifié #10
    Ouais, les color spaces j'avais déjà  essayé aussi, et ça change rien...
Connectez-vous ou Inscrivez-vous pour répondre.