Come generare immagini in JavaScript

P5.js per generare immagini sul web


Come generare immagini in JavaScript

Generare immagini in JavaScript

Idea, ricerca, risorse e primo sketch

Qualche giorno fa, volendo aggiungere un sistema di generazione automatico di immagini, sono tornato a curiosare sul sito della libreria p5.js.

P5.js anche conosciuta come p5* semplifica il processo di riempimento di elementi canvas ed è molto utilizzata per rappresentazioni grafiche e arte generativa.

Già in passato avevo sfruttato le sue potenzialità per la creazione di frattali e per la riproduzione grafica di algoritmi di ordinamento. Non è stato quindi difficile recuperare le informazioni necessarie per creare una generatore di immagini in JavaScript.

Per prima cosa mi sono rinfrescato la memoria guardando qualche esempio sul sito, poi sono direttamente andato in cerca del canale The Coding Train di Daniel Shiffman che è pieno di risorse riguardo p5.js, processing ed altre librerie JavaScript open-source e che vi consiglio di visitare.

Sono così finito a spulciare il suo repository GitHub ed a scegliere questo sketch come punto di partenza per il generatore di immagini.

Quello che fa lo sketch in questione è generare cerchi randomicamente all'interno di un canvas senza che si tocchino tra loro.

Modifiche allo sketch - palette e colori

Il sito di p5.js possiede anche un editor in cui è possibile testare sketch ed anche salvarli. Trovo questo strumento molto utile quando voglio fare dei test veloci e così ho iniziato a modificare lo sketch direttamente da lì.

Per prima cosa ho aggiunto un sistema di gestione dei colori in modo che non siano totalmente randomici dato che alcuni sono piacevoli da vedere assieme ma altri non proprio. Ho quindi una costante che contiene palette di colori così che randomicamente sia possibile scegliere una palette e successivamente tra i colori di quella palette.


const palettes = [
[[255,229,153], [255,217,102],[227,241,243], [111,168,220], [159,197,232]],
[[129,186,229], [228,193,213], [87,68,129], [228,78,123], [63,63,61]],
[[200,67,67], [144,181,144], [77,110,87], [64,71,123], [152,162,208]],
[[248,227,116], [246,84,106], [27,151,173], [49,171,171], [71,69,69]],
[[255,194,194], [255,255,255], [85,142,255], [232,232,232], [255,234,105]]
];

Aggiungere una nuova palette è quindi tanto facile quanto duplicare una riga e cambiare i valori RGB dei colori. Io ne ho aggiunte una ventina. *Per scegliere palette di colori puoi utilizzare il sito colors.co

La scelta dei colori è quindi randomica all'interno della palette cromatica scelta randomicamente.


let palette_n = int(random(0, palettes.length));
let palette = palettes[palette_n];
let color_n = int(random(0, palette.length));

Tuttavia è necessario, una volta scelto, rimuovere il colore assegnato allo sfondo per evitare che alcune delle forme generate successivamente risultino invisibili perché dello stesso colore.


background(palette[color_n]);
palette.splice(color_n, 1);

A questo punto è sufficiente assegnare un colore random, tra quelli rimasti nella palette, ad ogni forma.


let rand_color = palette[int(random(0, palette.length))];
fill(rand_color[0], rand_color[1], rand_color[2]);

Nuovo sketch

Generare solo cerchi tuttavia non mi soddisfava abbastanza quindi ho voluto modificare ulteriormente lo sketch di partenza generalizzandolo così che venga randomicamente scelta anche la forma degli elementi da disegnare e la loro grandezza all'interno di un intorno ragionevole.

Lo sketch così risultante è questo:


const palettes = [
[[255,229,153], [255,217,102],[227,241,243], [111,168,220], [159,197,232]],
[[129,186,229], [228,193,213], [87,68,129], [228,78,123], [63,63,61]],
[[200,67,67], [144,181,144], [77,110,87], [64,71,123], [152,162,208]],
[[248,227,116], [246,84,106], [27,151,173], [49,171,171], [71,69,69]],
[[255,194,194], [255,255,255], [85,142,255], [232,232,232], [255,234,105]]
];
//Add a new palette [[], [], [], [], []],

let geometries = [];

function setup() {
  createCanvas(640, 360);
  randomSeed(new Date().getTime());

  // Squares (0), Circles (1), Rect (2)?
  let flag = int(random(0, 3));
  let min_dim = 10;
  let max_dim = 100;
  if (flag === 0) {
    max_dim = 200;
  }

  // Generating geometry
  for (let cont = 0; cont < 10000; cont += 1) {
    if (geometries.length < 700) {
      // Pick a random circle
      var geometry = {
        x: random(width),
        y: random(height),
        d: random(min_dim, max_dim),
      };

      // Does it overlap any previous circles?
      var overlapping = false;
      for (var j = 0; j < geometries.length; j++) {
        var other = geometries[j];
        var d = dist(geometry.x, geometry.y, other.x, other.y);
        if (d / random(1, 2) < geometry.d + other.d) {
          overlapping = true;
        }
      }

      // If not keep it!
      if (!overlapping) {
        geometries.push(geometry);
      }
    }
  }

  // Choosing colors
  let palette_n = int(random(0, palettes.length));
  print(palette_n)
  let palette = palettes[palette_n];
  let color_n = int(random(0, palette.length));

  // Draw background
  background(palette[color_n]);
  palette.splice(color_n, 1);

  // Draw all the geometries
  for (var i = 0; i < geometries.length; i += 1) {
    let rand_color = palette[int(random(0, palette.length))];
    fill(rand_color[0], rand_color[1], rand_color[2]);
    noStroke();
    if (flag === 0)
      rect(geometries[i].x, geometries[i].y, geometries[i].d, geometries[i].d);
    else if (flag === 1)
      ellipse(geometries[i].x, geometries[i].y, geometries[i].d * 2, geometries[i].d * 2);
    else
      rect(geometries[i].x, geometries[i].y, geometries[i].d * int(random(0, 3)), geometries[i].d * int(random(0, 3)));
  }
}

È sorprendente quanto delle semplici forme generate da un codice altrettanto semplice possano dare vita a delle immagini così piacevoli.

generate images javascript

Ho così deciso di integrare lo sketch all'interno del sito TODO:LINK con qualche modifica per renderlo più funzionale. Visitando questa pagina potrete generare immagini a volontà gestendone i parametri di generazione e scaricare quelle che più vi piacciono.

Se ti è piaciuto questo articolo e vorresti leggerne altri quando disponibili, considera di aggiungere il Feed RSS in un aggregatore di notizie come Feedly oppure salva questo sito tra i preferiti e torna quando vuoi 👋


Author: Fantantonio 

Date: 24/03/2022

Categories: devexp

Tags: javascript p5.js web generative art generate images