NovaMonoFix
Errores PHP
X
Usuario
Password
0 FPS

Tutorial HTML5 Canvas2D parte 4 (imagenes)

16 de Noviembre del 2011 por Josep Antoni Bover, 0 visitas, 0 comentarios, 0 votos
Categorías : Canvas 2D, HTML, JavaScript, Programación.
La web está en segundo plano, animación en pausa.
Cargando animación...
Tutorial HTML5 Canvas2D parte 4 (imagenes)

Ha pasado algo más de una semana desde el ultimo tutorial del canvas 2d, pero tranquilos que no me he olvidado de él.

Esta vez vamos a trastear con imágenes, y veremos hasta que punto podemos toquetearlas.

Para ello voy a tomar una imagen del bender, y la voy a mostrar utilizando un único canal de color cada vez, de esta forma veréis como queda distribuida la imagen en memoria una vez cargada, y como poder modificar uno o más pixeles de ella.

En primer lugar vamos a crear algunas variables globales que necesitaremos para el ejemplo :


JavaScript : variables globales
1
2
3
4
// Variables globales
var Imagen = new Image(); // Contenedor para la imagen
var Canvas; // Objeto Canvas
var Context; // Contexto 2D

Una vez tenemos las variables globales declaradas, crearemos una función para comprobar si el navegador es compatible con el objeto Canvas2D, y de ser ese el caso cargaremos la imagen que queremos mostrar :

Función JavaScript : Empezar()
1
2
3
4
5
6
7
8
9
10
11
12
13
// Función que inicia el objeto Canvas y carga la imagen del bender
function Empezar() {
Canvas = document.getElementById("CanvasBender");
if (Canvas.getContext) {
Context = Canvas.getContext("2d");
}
else {
alert("Tu navegador no soporta el objeto canvas!");
return;
}
Imagen.onload = Pintar;
Imagen.src = "bender.jpg";
}

Fijaros en la línea 11 que se llama a la función Pintar una vez cargada la imagen, veamos la función Pintar :

Función JavaScript : Pintar()
1
2
3
4
5
6
7
// Función que pinta la imagen original y luego pinta las imagenes con un solo canal
function Pintar() {
Context.drawImage(Imagen, 0, 0);
PintarCanal(0, 192, 0); // Pinta el canal rojo
PintarCanal(1, 192 * 2, 0); // Pinta el canal verde
PintarCanal(2, 192 * 3, 0); // Pinta el canal azul
}

En la línea 3 de la función Pintar utilizamos la función drawImage que pinta la imagen previamente cargada sin ninguna modificación en el canvas. Es necesario pintar la imagen en el canvas para luego poder obtener los bytes de la imagen y poderlos modificar a nuestro antojo (cosa que no me ha gustado mucho).

Imagino que si tenemos que trabajar con muchas imágenes lo que se puede hacer es crear un canvas oculto para utilizarlo de backbuffer, y de esta forma no tenemos que ir pintando las imágenes en el canvas visible.

Una vez pintada la imagen en el canvas llamamos a la función PintarCanal, veamos su código :

Función JavaScript : PintarCanal()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// Función que pinta la imagen utilizando uno de los tres canales RGB.
// ConservarRGB = 0 (rojo)
// ConservarRGB = 1 (verde)
// ConservarRGB = 2 (azul)
function PintarCanal(ConservarRGB, nX, nY) {
var Origen = Context.getImageData(0, 0, 192, 192);
var Destino = Context.createImageData(192, 192);
// Obtenemos el tamaño de la imagen
var Ancho = Origen.width;
var Alto = Origen.height;
var Posicion = 0;
// de 0 al ancho de la imagen
for (var An = 0; An < Ancho; An++) {
// de 0 a la altura de la imagen
for (var Al = 0; Al < Alto; Al++) {
// de 0 a 3 (R, G, B)
for (var CanalRGB = 0; CanalRGB < 3; CanalRGB++) {
Posicion = (((An * Alto) + Al) * 4) + CanalRGB;
if (CanalRGB == ConservarRGB) Destino.data[Posicion] = Origen.data[Posicion];
else Destino.data[Posicion] = 0;
}
// Conservamos el canal alpha
Destino.data[Posicion + 1] = Origen.data[Posicion + 1];
}
}
Context.putImageData(Destino, nX, nY);
}

Para entender bien esta función tenemos que imaginar que la imagen es un array de una sola dimensión donde se guardan los pixeles. Cada pixel utiliza cuatro bytes : Rojo, Verde, Azul y Alpha.

En primer lugar en la línea 6 creamos la variable Origen y le cargamos la porción donde se ha pintado la imagen (0, 0, 192, 192) con la función getImageData. Una vez cargados los datos podemos modificar el miembro data de origen que es el que contiene el array de pixeles.

En la línea 7 creamos un objeto ImageData dentro de la variable Destino en el que guardaremos la imagen pintada con un solo canal, y para ello utilizamos la función createImageData a la que especificamos 192 pixeles de ancho y de alto.

A partir de la línea 13 creamos un bucle que recorre pixel a pixel la imagen, si os fijáis en la línea 17 es el ultimo bucle que recorre los canales de un pixel en concreto, en la cual establecemos la posición del pixel en el array de datos con la siguiente fórmula : Posicion = (((An * Alto) + Al) * 4) . A partir de esa posición hay 4 bytes que serán los canales RGBA.

En la línea 19 comprobamos si el canal actual es igual a la variable ConservarRGB, y de ser ese el caso copiamos el mismo valor que tiene la imagen Origen a la imagen Destino. Si resulta que la variable ConservarRGB no coincide con el CanalRGB actual asignamos el valor a 0.

En la línea 23 copiamos el canal alpha tal cual viene de la imagen Origen a la imagen Destino.

Y por ultimo en la línea 26 utilizamos la función putImageData para pintar la imagen Destino en el canvas.

Y esto es todo por hoy, como siempre podéis ver un ejemplo online, o descargar-lo.

Ver ejemplo Descargar ejemplo