0
votes

Pixel JavaScript par Pixel Toile Manipulation

Je travaille sur une application Web simple qui simplifie les couleurs d'une image téléchargée sur une palette de couleurs sélectionnée par l'utilisateur. Le script fonctionne, mais il faut très longtemps pour boucler à travers l'image entière (pour de grandes images, il est plus de quelques minutes), en changeant les pixels.

Initialement, j'écris à la toile elle-même, mais j'ai changé le code afin que des modifications soient apportées à un objet imagédata ​​code> et que la toile n'est mise à jour à la fin du script. Cependant, cela n'a pas vraiment fait beaucoup de différence. P>

// User selects colours:
colours = [[255,45,0], [37,36,32], [110,110,105], [18,96,4]];

function colourDiff(colour1, colour2) {
    difference = 0
    difference += Math.abs(colour1[0] - colour2[0]);
    difference += Math.abs(colour1[1] - colour2[1]);
    difference += Math.abs(colour1[2] - colour2[2]);
    return(difference);
}

function getPixel(imgData, index) {
    return(imgData.data.slice(index*4, index*4+4));
}

function setPixel(imgData, index, pixelData) {
    imgData.data.set(pixelData, index*4);
}

data = ctx.getImageData(0,0,canvas.width,canvas.height);
for(i=0; i<(canvas.width*canvas.height); i++) {
    pixel = getPixel(data, i);
    lowestDiff = 1024;
    lowestColour = [0,0,0];
    for(colour in colours) {
        colour = colours[colour];
        difference = colourDiff(colour, pixel);
        if(lowestDiff < difference) {
            continue;
        }
        lowestDiff = difference;
        lowestColour = colour;
    }
    console.log(i);
    setPixel(data, i, lowestColour);
}
ctx.putImageData(data, 0, 0);


0 commentaires

3 Réponses :


0
votes

Un problème ou une option d'amélioration est clairement votre fonction SLICE , qui créera un nouveau tableau à chaque appel, vous n'en avez pas besoin. Je changerais la boucle pour la boucle comme si: xxx


0 commentaires

0
votes

Il n'est pas nécessaire de trancher la matrice chaque itération. (Alors que Niklas a déjà déclaré).

Je bouclerais sur la matrice de données au lieu de boucler sur les dimensions de la toile et modifiez directement le tableau. P>

for(let i = 0; i < data.length; i+=4) { // i+=4 to step over each r,g,b,a pixel
  let pixel = getPixel(data, i);
  ...
  setPixel(data, i, lowestColour);
}

function setPixel(data, i, colour) {
    data[i] = colour[0];
    data[i+1] = colour[1];
    data[i+2] = colour[2];
}

function getPixel(data, i) {
    return [data[i], data[i+1], data[i+2]];
}


0 commentaires

0
votes

Trouver la différence de couleur

J'ajoute une réponse parce que vous avez un algorithme de correspondance de couleur très médiocre. P>

Trouver comment une couleur correspond à une autre est meilleure si vous imaginez chaque couleur unique possible. comme un point dans l'espace 3D. Les valeurs rouges, vertes et bleues représentent la coordonnée X, Y, Z. P>

Vous pouvez ensuite utiliser une géométrie de base pour localiser la distance d'une couleur à l'autre. P>

  function convertBitmap(canvas, maxTime) { // maxTime in ms (1/1000 second)
     return new Promise(allDone => {
         const ctx = canvas.getContext("2d");
         const pixels = ctx.getImageData(0, 0, canvas.width, canvas.height);
         const data = pixels.data;
         var idx = data.length / 4;
         processPixels(); // start processing
         function processPixels() {
             const time = performance.now();
             while (idx-- > 0) {
                 if (idx % 1024) { // check time every 1024 pixels
                      if (performance.now() - time > maxTime) {
                          setTimeout(processPixels, 0);
                          idx++;
                          return;
                      }
                 }
                 let i = idx * 4;
                 const col = findClosest(data[i], data[i + 1], data[i + 2]);
                 data[i++] = col[0];
                 data[i++] = col[1];
                 data[i] = col[2];
             }
             ctx.putImageData(pixels, 0, 0);
             allDone("Pixels processed");
         }
      });
  }

  // process pixels in 10ms slices. 
  convertBitmap(myCanvas, 10).then(mess => console.log(mess));
      

      

  


0 commentaires