Rendu hors écran de QuartzComposer, récupération des pixels
Chacha
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 :
+
Chacha
[Fichier joint supprimé par l'administrateur]
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 /> OffscreenQCRenderer* renderer = ...<br /><br /> [renderer renderAtTime:0 arguments:nil flush:YES];<br /> unsigned int width = 0;<br /> unsigned int height = 0;<br /> unsigned int bytesPerRow = 0;<br /> float* buffer = [renderer getPBufferWidth:&width height:&height bytesPerRow:&bytesPerRow];<br /><br /> ...<br /><br /> //for each pixel of the image..<br /> for(unsigned int r = 0 ; r < height ; ++r)<br /> {<br /> const float* row = reinterpret_cast<const float*>(reinterpret_cast<const char*>(buffer)+r*bytesPerRow);<br /> for(unsigned int c = 0 ; c < width ; ++c)<br /> {<br /> const float* pixel = row+4*c;<br /> ... // utiliser pixel[0], pixel[1], pixel[2] et pixel[3] pour les valeurs RGBA<br />
+
Chacha
[Fichier joint supprimé par l'administrateur]
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
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...
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