Video : Coder une pièce historique de Dan Graham

"Opposing Mirrors and Video Monitors on Time Delay" est une pièce historique de 1974 de Dan Graham. Elle utilisait une longue bande magnétique en boucle, constamment enregistrée et lue, produisant un délai de 8 secondes.

A la fois conceptuelle et orientée sur une expérience sensorielle (voir sa proche image dans un passé immédiat), àla fois technologique et rudimentaire, cette pièce classé "vidéo-art" séduit par son aspect direct, ludique et ouvert dans son interprétation.

Dan Graham montre donc en permanence une image filmée 8 secondes plus tôt. Coder ceci avec Processing ne relève pas du défi insurmontable : il s’agit de produire un "buffer" (mémoire tampon) d’images : on affiche la dernière image stockée dans une variable tableau (array), et on stocke l’image provenant de la webcam àsa place. Le code nécessite évidemment un ordinateur muni d’une webcam, interne ou externe.
Après ça, il suffit d’acheter une dizaine de mètres carrés de miroirs et le tour est joué.

Voici la version pour Processing 3. Il est possible que la définition de l’image vidéo doive être revue àla baisse si les performances ne sont pas au rendez-vous.

/**
 * Hommage a Dan Graham
 * un délai de 8 seconde dans la capture et la lecture de la video
 */

// La webcam
import processing.video.*;
Capture cam;

int nb_frames=96; // buffer de 96 images

int largeur, hauteur;
int displayframe=0; // pointeur dans l'array
PGraphics[] frames=new PGraphics[nb_frames];

void setup() {
  fullScreen();

  String[] cameras = Capture.list();
  println("Caméras disponibles :");
  printArray(cameras);

  if (width > 1280) {
    largeur=1280;
    hauteur=720;
  } else {
    largeur=width;
    hauteur=height;
  }

  // 12 images par secondes pour 8 secondes, soit 96 images
  frameRate(12);
  
  // prendre la premiere camera disponible
  cam = new Capture(this, cameras[0]);

  // cree les images vides
  for (int i=0; i < nb_frames; i++) {
    frames[i] = createGraphics(largeur, hauteur);
    frames[i].beginDraw();
    frames[i].background(0);
    frames[i].fill(255);
    frames[i].textSize(16);
    frames[i].textAlign(CENTER, CENTER);
    frames[i].text("Recording "+i, largeur/2, hauteur/2);
    frames[i].endDraw();
  }

  cam.start();
  background(0);
}

void draw() {
  if (cam.available() == true) {
    // afficher la dernière image en date du buffer
    image(frames[displayframe], 0, 0, width,height);
    // stocker l'image capturée en lieu et place
    // de l'image qui vient d'être affichée
    cam.read();
    frames[displayframe].beginDraw();
    frames[displayframe].image(cam, 0, 0, largeur, hauteur);
    frames[displayframe].endDraw();

    // on avance le pointeur de l'array
    displayframe++;
    if (displayframe == nb_frames) {
      displayframe=0;
    }
  }
}

Version pour Processing 2.0

Pour mémoire, la vieille version du code
Le code ci après utilise la librairie fullscreen, qui permet d’afficher l’animation en plein écran. La librairie peut être téléchragée sur le site de superdumper. On peut aussi supprimer les 4 lignes de code qui activent la libraire, lire le code àce propos.

/**
 * Hommage a Dan Graham
 * un délai de 8 seconde dans la capture et la lecture de la video 
 */

// si on ne veut pas utiliser le full screen, 
// desactiver les deux lignes suivantes
import fullscreen.*; 
FullScreen fs;

// La webcam
import processing.video.*; 
Capture cam;

// ici la taille de la capture video et de l'animation
int largeur=640;
int hauteur=480;

int displayframe=0; // pointeur dans l'array
int nb_frames=96; // buffer de 96 images

PGraphics[] frames=new PGraphics[nb_frames];

void setup() {
  size(largeur, hauteur);

  // si on ne veut pas utiliser le full screen, 
  // desctiver les deux lignes suivantes
  fs = new FullScreen(this); 
  fs.enter();

  // 12 images par secondes pour 8 secondes, soit 96 images
  frameRate(12);
  cam = new Capture(this, largeur, hauteur);

  // cree les images vides
  for(int i=0;i < nb_frames;i++){
    frames[i] = createGraphics(largeur, hauteur, P2D);
  }
}

void draw() {
  if (cam.available() == true) {
    // afficher la dernière image en date du buffer
    image(frames[displayframe],0,0);

    // stocker l'image capturée en lieu et place
    // de l'image qui vient d'être affichée
    cam.read();
    frames[displayframe].beginDraw();
    frames[displayframe].image(cam,0,0,640,480);
    frames[displayframe].endDraw();

    // on avance le pointeur de l'array
    displayframe++;
    if(displayframe == nb_frames){
      displayframe=0;
    }

  }
}

Un code court et efficace comme on les aime.