Manipular imágenes
El <canvas>
nos permite modificar, uno por uno, los píxeles de una imagen.
Para esto tenemos a nuestra disposición tres propiedades y tres métodos() de <canvas>
Importante: si queremos experimentar manipulando imágenes en el <canvas>
tenemos que hacerlo en un sitio web de verdad, como por ejemplo locahost.
JavaScript | Descripción | Defecto | |
---|---|---|---|
width | imgData.width | Devuelve el ancho del objeto ImageData, en píxeles | |
height | imgData.height | Devuelve la altura del objeto ImageData, en píxeles | |
data | imageData.data | Devuelve un objeto conteniendo todos los datos del objeto ImageData. | |
createImageData() | context.createImageData(ancho, alto); | Crea un nuevo objeto ImageData en blanco. Toma dos argumentos: la anchura y la altura del objeto creado | |
createImageData() | context.createImageData(imgData); | Crea un nuevo objeto ImageData con las mismas dimensiones que el objeto especificado por el argumanto imgData. | |
getImageData() | context.getImageData ( x, y, ancho, alto ); | Devuelve un objeto ImageData que copia los datos de los píxeles del rectángulo especificado. | |
putImageData() | context.putImageData( imgData, x, y, [dirtyX, dirtyY, dirtyWidth, dirtyHeight] ); | Pone los datos de la imagen (de un objeto ImageData especificado) de nuevo en el canvas |
Vea la chuleta con las propiedades y metodos() de canvas.
Un poco de teoría
Los píxeles de una imagen "en crudo" tienen una "anchura" de 4 bytes, uno por cada componente R G B A. ( Red (rojo), Green (verde), Blue (azul) y Alpha (transparencia) ).
Accediendo uno por uno los pixeles de una imagen podemos modificar estos componentes de color, y por tanto manipular el aspecto de las imágenes en el <canvas>
.
Ojo: por razones de seguridad la imagen manipulada y el <script>
que la manipula tienen que provenir de la misma página web.
De otra manera el acceso al <script>
será denegado y el navegador levantará una excepción de seguridad.
Un ejemplo fácil
A continuación dibujamos un cuadrado utilizando el método createImageData()
. Ya lo se, sería mucho más fácil dibujarlo con fillRect()
,
pero es solo para demonstrar como podemos dibujar una imagen sencilla partiendo prácticamente desde cero.
- 1. El método
createImageData(anchura , altura)
crea un nuevo objetoImageData
en blanco, de anchura y altura dadas. - 2. En el siguiente paso iremos de pixel en pixel modificando uno por uno el valor de los componentes RGBA.
Como ya hemos visto cada pixel tiene una "anchura" de 4 bytes, donde el primer byte representa el rojo, el segundo representa el verde, el tercero el azul y el cuarto es el componente alpha o el grado de transparencia.
Siendo bytes pueden tomar valores entre 0 y 255.
En el siguiente ejemplo manipulamos cada pixel para que:
- el rojo = 255; (100%)
- el verde = 0;(ausente)
- el azul = 0; (ausente)
- alpha = 255; (totalmente opaco)
- 3. Después de manipular los pixeles volvemos a colocar la imagen en el
<canvas>
conputImageData()
.
El métodoputImageData()
toma ( en este caso ) tres argumentos: la imagen manipulada y las coordenadas x e y de donde poner la imagen en el<canvas>
var canvas = document.getElementById("lienzo");
if (canvas && canvas.getContext) {
var ctx = canvas.getContext("2d");
if (ctx) {
// 1. crea un objeto ImageData en blanco;
var imgData=ctx.createImageData(100,100);
// 2. para cada pixel modifica el valor de los componentes RGBA;
for (var i = 0; i < imgData.data.length; i+= 4)
{
imgData.data[i+0]=255; // rojo = 100%;
imgData.data[i+1]=0; // verde - ausente;
imgData.data[i+2]=0; // azul - ausente;
imgData.data[i+3]=255; // alpha - opaco;
}
// 3. coloca la nueva imagen en el canvas;
ctx.putImageData(imgData,75,10);
}
}
ImageData.width e ImageData.heught
En el ejemplo anterior hemos utilizado la propiedad data
del objeto ImageData que representa un array unidimensional que contiene los datos rgba
de cada pixel. La longitud de este array es igual al número de pixeles multiplicado por 4. ( Ya hemos visto que cada pixel tiene una "anchura" de 4 bytes. )
Otra manera de hacer lo mismo es utilizando las propiedades width
( anchura ) y height
( altura ) del objeto ImageData
.
Si en el ejemplo anterior hemos utilizado un solo bucle for, ahora necesitamos utilizar dos bucles for anidados: uno para las coordenadas en x
y otro para las coordenadas en y
de cada pixel.
for (var y = 0; y < imgData.height; y ++) { //imgData.height = 250 for (var x = 0; x < imgData.width; x ++) { //imgData.width = 250 // aquí va el código } }
La fórmula para encontrar el índex de los datos en el array ImageData.data
es:
var i = (y*imgData.width + x)*4;
Todo lo demás queda igual que antes:
for (var y = 0; y < imgData.height; y ++) { //imgData.height = 250 for (var x = 0; x < imgData.width; x ++) { //imgData.width = 250 var i = (y*imgData.width + x)*4; imgData.data[i + 0] = 255; // rojo = 100%; imgData.data[i + 1] = 0; // verde - ausente; imgData.data[i + 2] = 0; // azul - ausente; imgData.data[i + 3] = 255; // alpha - opaco; } } ctx.putImageData(imgData,75,75);
Vea el código en CodePen
See the Pen imgData.width, imgData.heigh* by Gabi (@enxaneta) on CodePen.