MySQL Java JavaScript PHP Python HTML-CSS C-sharp

Editarea pixelilor

JavaScript oferă funcționalități încorporate pentru editarea imaginilor și setarea valorilor pixelilor specifici pe canvas. În special, putem modifica valorile de culoare ale unui pixel, precum și transparența acestuia. Pentru aceasta sunt destinate metode precum getImageData(), putImageData() și createImageData().

Metoda getImageData()

Metoda getImageData() permite extragerea unei anumite părți a imaginii de pe canvas. Are următoarea definiție:

getImageData(sx, sy, sw, sh);

Aici, sx și sy sunt coordonatele colțului stânga sus al zonei din care sunt extrase datele pe canvas, iar sw și sh sunt respectiv lățimea și înălțimea acestei zone.

Datele din zona definită de acești parametri sunt extrase sub forma unui obiect ImageData, care ulterior este folosit pentru manipularea pixelilor.

Exemplu de utilizare:

const canvas = document.getElementById("canvas");
const context = canvas.getContext("2d");
               
const img = new Image();
img.src = "forest.png";
img.onload = function() {
   context.drawImage(img, 0, 0);
   const imageData = context.getImageData(0,0, 100, 100);
};

Toate datele despre imagine în obiectul ImageData sunt stocate în array-ul data. Fiecare pixel pe canvas este caracterizat de patru componente în format RGBA: componenta roșie, verde, albastră, care stabilesc culoarea, și componenta alfa, care stabilește transparența.

Fiecare componentă acceptă valori de la 0 la 255. Pentru a obține valorile de culoare pentru primul pixel în ImageData, trebuie să obținem secvențial patru valori din array-ul data:

const canvas = document.getElementById("canvas");
const context = canvas.getContext("2d");
               
const img = new Image();
img.src = "fox2.png";
img.onload = function() {
               
   context.drawImage(img, 0, 0);
   const imageData = context.getImageData(0,0, 100, 100);
   const red = imageData.data[0];  // componenta roșie
   const green = imageData.data[1];    // componenta verde
   const blue = imageData.data[2]; // componenta albastră
   const alpha = imageData.data[3];    // componenta transparenței
};

Pentru a obține informații despre al doilea pixel, care are coordonatele x=1 și y=0, trebuie să obținem următoarele patru valori din array-ul data:

imageData.data[4];  // componenta roșie
imageData.data[5];  // componenta verde
imageData.data[6];  // componenta albastră
imageData.data[7];  // componenta transparenței

Și așa mai departe, putem obține informații despre toți pixelii.

Metoda putImageData()

Metoda putImageData() stabilește pe canvas datele noi. Această metodă are următoarele forme:

putImageData(imageData, dx, dy)
putImageData(imageData, dx, dy, dirtyX, dirtyY, dirtyWidth, dirtyHeight)

Parametrii dx și dy indică coordonatele colțului stânga sus al dreptunghiului imaginar imageData, care este plasat pe canvas.

Parametrii adiționali dirtyX și dirtyY indică respectiv coordonatele X și Y ale colțului stânga al zonei dreptunghiulare, care va fi extrasă din imaginea obținută. Parametrii dirtyWidth și dirtyHeight stabilesc respectiv lățimea și înălțimea acestei zone.

Utilizarea metodelor getImageData() și putImageData() pentru transformarea imaginii:

<!DOCTYPE html>
<html>
<head>
   <meta charset="utf-8" />
   <title>FDC.COM</title>
</head>
<body>
<canvas id="canvas" width="700" height="300"></canvas>
<script>
const canvas = document.getElementById("canvas");
const context = canvas.getContext("2d");

const img = new Image();
img.src = "fox2.png";
img.onload = function() {
                 
   context.drawImage(img, 0, 0);
   const imageData = context.getImageData(0,0, img.width, img.height);
   let red, green, blue, grayscale;
                 
   for (let i = 0; i < imageData.data.length; i += 4) {
       red = imageData.data[i]; // obținem componenta roșie
       green = imageData.data[i + 1];  // obținem componenta verde
       blue = imageData.data[i + 2];   // obținem componenta albastră
       grayscale = red * 0.3 + green * 0.59 + blue * 0.11; // calculăm nuanța de gri
       imageData.data[i] = grayscale;  // setăm culoarea gri
       imageData.data[i + 1] = grayscale;
       imageData.data[i + 2] = grayscale;
   }  
   context.putImageData(imageData, img.width + 10, 0);
};
</script>
</body>
</html>

P.S. Ca să nu aveți eroare, ar fi bine să rulați programul de pe server.js care l-ați făcut în temele anterioare și să treceți pe locallhost:3000.

Secțiunea cheie a codului este bucla, în care are loc transformarea imaginii în gri:

let red, green, blue, grayscale;
                 
for (let i = 0; i < imageData.data.length; i += 4) {
   red = imageData.data[i]; // obținem componenta roșie
   green = imageData.data[i + 1];  // obținem componenta verde
   blue = imageData.data[i + 2];   // obținem componenta albastră
   grayscale = red * 0.3 + green * 0.59 + blue * 0.11; // calculăm nuanța de gri
   imageData.data[i] = grayscale;  // setăm culoarea gri
   imageData.data[i + 1] = grayscale;
   imageData.data[i + 2] = grayscale;
}

Aici, parcurgem întregul array imageData.data, procesând câte patru elemente odată, care reprezintă un singur pixel. Luăm în considerare doar trei elemente, deoarece componenta de transparență nu ne interesează în acest caz.

În primul rând, obținem componentele RGB. Apoi, aplicând formula matematică, transformăm valorile RGB în nuanța de gri. La final, culoarea gri este setată pentru elementele pixelului.

Probleme de securitate

Dacă încercăm să deschidem direct fișierul paginii web cu codul menționat mai sus în browserul Google Chrome sau prin dublu clic, Google Chrome nu va afișa imaginea transformată în gri din cauza politicilor browserului. Deși în alte browsere, precum Firefox sau Microsoft Edge, totul poate funcționa normal.

Motivul este că Google Chrome nu permite manipularea imaginilor unui site dintr-un domeniu de către un utilizator din alt domeniu. Practic, când încărcăm fișierul prin protocolul file:// (prin tragerea fișierului în browser sau prin dublu clic), browserul consideră utilizatorul și pagina web deschisă ca fiind din domenii diferite.

Dacă pagina web este găzduită pe un server web și încărcată prin protocolul http, cum este obișnuit, atunci problema nu va apărea, deoarece utilizatorul și site-ul vor opera în cadrul aceluiași domeniu. Pentru testare, va trebui fie să utilizăm un server web, fie să ajustăm corespunzător setările browserului Google Chrome.

Metoda createImageData()

Metoda createImageData() creează un nou obiect ImageData, care ulterior poate fi utilizat pe canvas. Metoda createImageData() are două forme:

createImageData(width, height);
createImageData(imagedata);

Prima formă primește parametrii width și height, care stabilesc respectiv lățimea și înălțimea obiectului ImageData creat.

A doua formă primește ca parametru un alt obiect ImageData, pe baza căruia va fi creat un nou obiect ImageData.

Exemplu de utilizare:

const canvas = document.getElementById("canvas");
const context = canvas.getContext("2d");

const img = new Image();
img.src = "fox2.png";
img.onload = function() {
               
   context.drawImage(img, 0, 0);
   const imageData = context.getImageData(0,0, img.width, img.height);
   const newImageData = context.createImageData(imageData);
               
   for (let i = 0; i < newImageData.data.length; i++) {
               
       newImageData.data[i] = imageData.data[i];
       // dacă este componenta alfa
       if((i+1)%4===0){
                       
           newImageData.data[i] = 120;
       }
   }
   context.putImageData(newImageData, img.width + 10, 0);
};

În acest caz, se creează un nou obiect newImageData, în care sunt copiate toate datele din imageData curent, ce reprezintă imaginea pe canvas. În timpul copierii, valorii componentei alfa, care răspunde de transparență, i se atribuie valoarea 120, adică face pixelul semitransparent.

← Lecția anterioară Lecția următoare →