Rendu hors écran de QuartzComposer, récupération des pixels

ChachaChacha Membre
Salut,

Comme ce post me l'a rappelé, je voulais vous faire part d'un bout de code diablement pratique que j'ai fait, inspiré de http://developer.apple.com/samplecode/QuartzComposerOffline/, permettant de récupérer les buffers RGB d'une séquence QuartzComposer.

Le principe est le suivant :
Un objet OffscreenQCRenderer est créé, initialisé avec une composition QuartzComposer (.qtz). Comme cet objet encapsule un QCRenderer auquel on a accès, on peut générer les images à  l'envi avec renderImageAtTime.
Par contre, une méthode de OffscreenQCRenderer permet, lors du rendu, de mettre à  jour puis de récupérer le pixelBuffer OpenGL sous forme de tableau C contenant les valeurs RGBA en float.

Notez que la composition QuartzComposer peut être aussi simple qu'un simple ImageWithMovie pour récupérer les frames d'un film QuickTime...

Le code est fourni en pièce jointe, et en voici un exemple d'utilisation :
<br />&nbsp; &nbsp; OffscreenQCRenderer* renderer = ...<br /><br />&nbsp; &nbsp; [renderer renderAtTime:0 arguments:nil flush:YES];<br />&nbsp; &nbsp; unsigned int width&nbsp; &nbsp; &nbsp;  = 0;<br />&nbsp; &nbsp; unsigned int height&nbsp; &nbsp; &nbsp; = 0;<br />&nbsp; &nbsp; unsigned int bytesPerRow = 0;<br />&nbsp; &nbsp; float*&nbsp; &nbsp; &nbsp;  buffer&nbsp; &nbsp; &nbsp; = [renderer getPBufferWidth:&amp;width height:&amp;height bytesPerRow:&amp;bytesPerRow];<br /><br />&nbsp; ...<br /><br />&nbsp; //for each pixel of the image..<br />&nbsp; for(unsigned int r = 0 ; r &lt; height ; ++r)<br />&nbsp; {<br />&nbsp; &nbsp; const float* row = reinterpret_cast&lt;const float*&gt;(reinterpret_cast&lt;const char*&gt;(buffer)+r*bytesPerRow);<br />&nbsp; &nbsp; for(unsigned int c = 0 ; c &lt; width ; ++c)<br />&nbsp; &nbsp; {<br />&nbsp; &nbsp; &nbsp; const float* pixel = row+4*c;<br />&nbsp; &nbsp; &nbsp; ... // utiliser pixel[0], pixel[1], pixel[2] et pixel[3] pour les valeurs RGBA<br />


+
Chacha

[Fichier joint supprimé par l'administrateur]

Réponses

  • AliGatorAliGator Membre, Modérateur
    janvier 2007 modifié #2
    Plutôt que ton double reintrepret_cast<>, qui finalement ne sert qu'à  "operator+" pour ajouter des offsets en "octets" et non en "nombre de floats", pourquoi ne pas simplement diviser bytesPerRow ar sizeof(float) ?
    int floatsPerRow = bytesPerRow / sizeof(float); // à  faire hors de  la boucle for bien sûr<br />// ... et dans la boucle for remplacer la ligne adéquate par :<br />const float* row = buffer+r*floatsPerRow;
    

    Car finalement le reinterpret_cast<const char*> ne fait que réinterpréter le buffer en tant que buffer de 'char', pour lui ajouter un offet de r*bytesPerRow octets, pour ensuite que tu le re-réinterprètes comme float*. Alors que là  j'applique un offset qui sera exprimé en "nombre de 'floats' de décalage" au lieu de "nombre de 'char' (donc d'octets) de décalage) : donc il suffit de diviser par la taille d'un float (4 octets normalement) pour retomber sur ses pas.

    Avec l'avantage d'éviter les 2 reinterpret_cast l'un après l'autre à  chaque itération de la boucle, ce qui en plus d'être plus rapide est je trouve plus clair...
  • ChachaChacha Membre
    05:44 modifié #3
    dans 1168707994:

    Plutôt que ton double reintrepret_cast<>, (...) pourquoi ne pas simplement diviser bytesPerRow ar sizeof(float) ?



    Avec l'avantage d'éviter les 2 reinterpret_cast l'un après l'autre à  chaque itération de la boucle, ce qui en plus d'être plus rapide est je trouve plus clair...


    Je ne pense pas que ça change quoi que ce soit à   la vitesse, et pour moi c'est plus clair comme je l'ai écrit. Après, tu as raison de souligner qu'on peut faire autrement, chacun sa sensibilité.
    D'autant plus que le reinterpret_cast, c'est du C++, et tout le monde ne connaà®t pas...

    Merci pour l'ajout !

    +
    Chacha
  • AliGatorAliGator Membre, Modérateur
    05:44 modifié #4
    Ah oui tiens suis tellement habitué que j'avais même pas tilté sur cet aspect là ... Pour ceux qui font de l'Obj-C et non de l'Obj-C++ ça risque de poser souci  ;)
Connectez-vous ou Inscrivez-vous pour répondre.