introduction

a l’occasion de ce projet, j’ai décidé de questionner la nature des images que je produit dans ma pratique photographique digitale. Après quelque recherches sur le fonctionnement des capteurs ainsi que sur les différents formats d’images que l’on peut rencontrer, j’ai acté ma recherche autour des valeurs RVB* ;

*RVB, valeurs rouge, vert, bleu allant de 0 a 255 pour chacun des pixels d’une image. La combinaison de ces valeurs permet théoriquement l’affichage de 16777216 couleurs différentes, soit un nombre grandement supérieur a ce que l’oeil humain est capable de voir.

Je me pose donc la question suivante:

→ Comment modifier des images en agissant directement sur le code RVB de celles-ci.


Processing

Une fois ma recherche formulée, je me mis a l’apprentissage d’un logiciel pertinent. Je me suis dirigé vers Processing en java.

J’apprends les bases avec les tutos disponibles sur leur site : https://hello.processing.org/editor/

Voici le code que je produit

void setup() {
  size(400, 500);
background(255);
stroke(122);
fill(122);
rect(10,10,380,480);

}

void draw() {
  stroke(40);
fill(40);
ellipse(mouseY, mouseX, 10, 40);

stroke(255);
fill(128);
circle(mouseX, mouseY, mouseY/2-mouseX);

stroke(0);
fill(255,0,0);
if (mousePressed) {
   circle(mouseX, mouseY, mouseY/2-mouseX);
  }else {
    stroke(0,0,255);
fill(0,0,255);
    ellipse(250, 200, 100, 100);
    ellipse(mouseY, mouseX, 50, 200);
    }
}


Une fois les bases comprises je dirige mes apprentissages vers la photo, j’apprivoise notamment les codes proposés sur ce site : https://happycoding.io/tutorials/processing/images#getting-pixels Et m’aide de chat gpt pour avancer. A mon sens chat gpt est un super outil mais il code mal. L’utilisation pertinente que j’ai pu en avoir se restreint a la suivante. Lancer des idées pour voir quel code est utilisé avant d’aller apprendre comment s’en servir → page reference processing: https://processing.org/reference/int.html corriger des erreurs de syntaxe rapidement demander des explications sur des codes.

Cette méthode me permet de réaliser les codes suivants

V1

PImage img;

vd setup() {
  size(2000, 1328);
  img = loadImage("ton image.jpg");
  img.resize(width, height);
}

void draw() {
  loadPixels();

  for (int i = 0; i < img.width; i++) {
    for (int j = 0; j < img.height; j++) {
      int index = i + j * img.width;
      color c = img.pixels[index];

      float r = red(c);
      float g = green(c);
      float b = blue(c);

      int différence = (int)(max(r, g, b) - min(r, g, b));

      // Ajuste les valeurs de r, g, et b en fonction de la valeur de différence
      r = map(différence, 0, 90, 0, 255);
      g = map(différence, 0, 90, 0, 255);
      b = map(différence, 0, 90, 0, 255);

      // Limiter les valeurs entre 0 et 255
      r = constrain(r, 0, 255);
      g = constrain(g, 0, 255);
      b = constrain(b, 0, 255);

      // Mise à jour du pixel avec les nouvelles composantes RVB
      img.pixels[index] = color(r, g, b);
    }
  }

  updatePixels();
  image(img, 0, 0);

  saveFrame("ton image modifiée.tif");
  noLoop();
}

Detection des pixels ayant toute leurs valeurs RVB pair (ex 244,12,100) Qui copie la couleur des pixels se trouvant a 5 pixels a leur droite tout en soustrayant 40 a chacune des valeurs rvb

PImage img;

void setup() {
  size(800,800);
  img = loadImage("image2.jpg");
  img.loadPixels();
}

void draw() {
  background(255);

  int offset = 5;  // Valeur de décalage, ajustez selon vos besoins

  for (int y = 0; y < img.height; y++) {
    for (int x = 0; x < img.width - offset; x++) {
      // Récupérer la couleur du pixel à droite (avec décalage)
      color rightPixelColor = img.pixels[(x + offset) + y * img.width];

      // Extraire les composantes de couleur (rouge, vert, bleu)
      int redValue = int(red(rightPixelColor));
      int greenValue = int(green(rightPixelColor));
      int blueValue = int(blue(rightPixelColor));

      // Vérifier si toutes les composantes sont des nombres pairs
      if (redValue % 2 == 0 && greenValue % 2 == 0 && blueValue % 2 == 0) {
        // Diminuer les valeurs RVB de 40
        redValue = max(0, redValue - 40);
        greenValue = max(0, greenValue - 40);
        blueValue = max(0, blueValue - 40);

        // Affecter la nouvelle couleur au pixel actuel
        img.pixels[x + y * img.width] = color(redValue, greenValue, blueValue);
      }
    }
  }

  img.updatePixels();
  image(img, 0, 0);

  // Enregistrer l'image au format BMP (non compressé)
  saveFrame("result_image16.bmp");

  // Arrêter le dessin après avoir appliqué la transformation
  noLoop();
}

Detection roue quand tt les valeurs rvb sont pair = rue si nn blanc

PImage img;

void setup() {
  size(1920, 1080);
  img = loadImage("elden-ring-key-art.jpg");
  img.loadPixels();
}

void draw() {
  background(255);

  int offset = 5;  // Valeur de décalage, ajustez selon vos besoins

  for (int y = 0; y < img.height; y++) {
    for (int x = 0; x < img.width - offset; x++) {
      // Récupérer la couleur du pixel à droite (avec décalage)
      color rightPixelColor = img.pixels[(x + offset) + y * img.width];

      // Extraire les composantes de couleur (rouge, vert, bleu)
      int redValue = int(red(rightPixelColor));
      int greenValue = int(green(rightPixelColor));
      int blueValue = int(blue(rightPixelColor));

      // Vérifier si toutes les composantes sont des nombres pairs
      if (redValue % 2 == 0 && greenValue % 2 == 0 && blueValue % 2 == 0) {
        // Affecter la couleur rouge au pixel actuel
        img.pixels[x + y * img.width] = color(255, 0, 0);
      } else {
        // Affecter la couleur blanche au pixel actuel
        img.pixels[x + y * img.width] = color(255);
      }
    }
  }

  img.updatePixels();
  image(img, 0, 0);

  // Enregistrer l'image au format BMP (non compressé)
  saveFrame("result_image17.bmp");

  // Arrêter le dessin après avoir appliqué la transformation
  noLoop();
}

Les 4 couleurs noir rouge vert bleu en fonction du nombre de valeur rvb pair/impaire

PImage img;

void setup() {
  size(600, 400);
  img = loadImage("Flower-Photography-Tip-2.png");
  img.loadPixels();
}

void draw() {
  background(255);

  int offset = 5;  // Valeur de décalage, ajustez selon vos besoins

  for (int y = 0; y < img.height; y++) {
    for (int x = 0; x < img.width - offset; x++) {
      // Récupérer la couleur du pixel à droite (avec décalage)
      color rightPixelColor = img.pixels[(x + offset) + y * img.width];

      // Extraire les composantes de couleur (rouge, vert, bleu)
      int redValue = int(red(rightPixelColor));
      int greenValue = int(green(rightPixelColor));
      int blueValue = int(blue(rightPixelColor));

      // Compter le nombre de composantes RVB impaires
      int oddCount = 0;
      if (redValue % 2 != 0) oddCount++;
      if (greenValue % 2 != 0) oddCount++;
      if (blueValue % 2 != 0) oddCount++;

      // Affecter la couleur appropriée au pixel actuel
      if (oddCount == 2) {
        // Deux valeurs RVB impaires, affecter la couleur verte
        img.pixels[x + y * img.width] = color(0, 255, 0);
      } else if (redValue % 2 == 0 && greenValue % 2 == 0 && blueValue % 2 == 0) {
        // Trois valeurs RVB paires, affecter la couleur rouge
        img.pixels[x + y * img.width] = color(255, 0, 0);
      } else if (redValue % 2 != 0 && greenValue % 2 != 0 && blueValue % 2 != 0) {
        // Trois valeurs RVB impaires, affecter la couleur bleue
        img.pixels[x + y * img.width] = color(0, 0, 255);        
      }
    }
  }

  img.updatePixels();
  image(img, 0, 0);

  // Enregistrer l'image au format BMP (non compressé)
  saveFrame("result_image20.bmp");

  // Arrêter le dessin après avoir appliqué la transformation
  noLoop();
}

ces différents codes me permettent de modifier mes images en parcourant les valeurs rvb de chacun des pixels de celles-ci afin d'en modifier la valeur. voici quelque images test produites avec ceux-ci;

les résultats ne me plaisaient pas, je voulais sortir de l'esthétique du bug mais je ne savais comment

projet final

je me lance alors sur ma dernière idée je veux créer deux codes, l'un pour cacher une image bitmap dans une autre a travers les valeurs RVB de celle-ci et un second pour en extraire le contenu.

afin de réaliser des texts rapidement, je code ceci :

PImage img;

void setup() {
  size(4, 2); 
  img = createImage(width, height, RGB); 
  img.loadPixels(); 
  
  int[] pixelsValues = {
    color(255, 255, 255),
    color(0, 0, 0),
    color(140, 25, 25),
    color(121, 25, 25),
    color(255, 255, 255),
    color(0, 0, 0),
    color(140, 25, 25),
    color(121, 25, 25)
  };
  
  for (int i = 0; i < img.width * img.height; i++) {
    img.pixels[i] = pixelsValues[i];
  }
  
  img.updatePixels(); 
  image(img, 0, 0); 

  saveFrame("screen-0017.png");

}

afin d'avoir une image pure non compressée et extrêmement facile a traiter

avec cet outil et sur base de mes codes précédents, je réalise donc le projet sans trop d'encombre

encodage

PImage img1;
PImage img2;

void setup() {
  size(1992, 1328);
  
  img1 = loadImage("Quadruple.jpg");
  img1.resize(width, height);
  
  img2 = loadImage("ingod.png");
  img2.resize(width, height);
  
  loadPixels(); 
}

void draw() {
  for (int i = 0; i < img1.width; i++) {
    for (int j = 0; j < img1.height; j++) {
      int index1 = i + j * img1.width;
      color c1 = img1.pixels[index1];
      float r1 = red(c1);
      
      
      int x2 = i % img2.width;
      int y2 = j % img2.height;
      int index2 = x2 + y2 * img2.width;
      color c2 = img2.pixels[index2];
      float r2 = red(c2);
      
      float add = r1 + r2; 
      
      if (add % 2 != 0) { 
        
        if (r1 < 255) {
          r1 = constrain(r1 + 1, 0, 255);
        } else {
          r1 = constrain(r1 - 1, 0, 255);
        }
        img1.pixels[index1] = color(r1, green(c1), blue(c1));
      }
    }
  }

  updatePixels();
  image(img1, 0, 0);
  
  saveFrame("screen-0016.png");
  noLoop();
}

photos de base

photo modifiée contenant les deux photos sans ajout de data

décodage

PImage img1;

void setup() {
  size(1992,1328);
  img1 = loadImage("screen-0016.png");
  img1.resize(width, height);
}

void draw() {
  loadPixels();

  for (int i = 0; i < img1.width; i++) {
    for (int j = 0; j < img1.height; j++) {
      int index = i + j * img1.width;
      color c1 = img1.pixels[index];
      
      float r1 = red(c1);
     
      
      if (red(c1) % 2 != 0) {
       
        c1 = color(255, 255, 255);
      } else {
        c1 = color(0, 0, 0);
      }

      
      img1.pixels[index] = c1;
    }
  }

  updatePixels();
  image(img1, 0, 0);

saveFrame("screen-0017.png");
  noLoop();
}

photo extraite

bug si les formats d'image ne correspondent pas


conclusion

pour conclure, je suis content Des apprentissages que j'ai pu faire lors de ce cours, ce que j'ai pu y réaliser reste encre difficile a associer avec ma pratique photo courante mais cette ouverture du médium m'a permis d'envisager de mulitples nouveaux projets.