¿Cómo cambiar el contraste de una imagen con HTML5?

- Andrés Cruz

In english
¿Cómo cambiar el contraste de una imagen con HTML5?

En este artículo veremos cómo aumentar o reducir el contraste de una imagen con HTML5; además hablaremos un poco de como sería el proceso para aumentar el brillo de una imagen; que es un caso similar.

Estos son algunos de los métodos, tecnologías y conceptos que van a ser utilizados para llevar a cabo el desarrollo de este ejercicio:

  • Canvas: Para utilizarlo como lienzo y dibujar una imagen.
  • getImageData(): Permite obtener data sobre la imagen dibujada en el Canvas (ImageData):
    • ImageData.width: Anchura en píxeles de la ImageData.
    • ImageData.height: Altura en píxeles de la ImageData.
    • ImageData.resolution: La densidad de píxeles que posee la imagen.
    • ImageData.data: Array de una dimensión que contiene la data en RGBA (en ese orden), con enteros entre 0-255; representa los colores que componen la imagen dibujada en el Canvas; en otras palabras; los valores de los píxeles que componen a la imagen dibujada en el Canvas.
    • img.onload: Evento que se manifiesta una vez que la imagen ha sido cargada.

La fórmula del contraste

Queda fuera del alcance de este artículo definir el contraste en toda su extensión; sin embargo podemos definir el contraste como una variación de intensidades que permite incrementar la luminosidad entre las zonas oscuras y claras de una imagen permitiendo un mejor enfoque y claridad de la imagen; la fórmula empleada a nivel de pixel será la siguiente:

valorNuevo = ( valorAnterior - 128) * tan(ángulo) + 128

En donde:

  • valorAnterior: Es el valor original de un píxel en la imagen.
  • ángulo: Calculamos el ángulo como:  Math.tan(val * Math.PI / 180.0);
    • val : El valor del campo de tipo rango manejado por el usuario.

Puedes obtener más información sobre la fórmula en el siguiente enlace: Generación de Imágenes.

Definiendo el HTML

Primero necesitaremos un Canvas; el cual utilizaremos como lienzo para pintar una imagen y poder manipularla a nivel de pixeles:

<canvas id="canvas">
	<p>Tu navegador no soporta Canvas.</p>
</canvas>

Un campo de tipo rango (type="range") para poder aumentar y decrementar el contraste fácilmente:

<input type="range" id="contrast" min="-90" max="90" step="5" value="0">

Definiendo el JavaScript

Variables globales:

	var canvas = document.getElementById('canvas');// canvas
	var ctx = canvas.getContext('2d'); // contexto
	var contrast = document.getElementById("contrast");// input de tipo rango
	var srcImg = "image.png";// imagen fuente

Primero es necesario crear un objeto de tipo image a la cual se le establece una imagen fuente que será utilizada para pintarla en el Canvas con el método drawImage():

	// nueva imagen
	img = new Image();
	img.src = srcImg;

	img.onload = function() {
	
		// reescalamos el canvas a las dimenciones de la imagen
		canvas.width = img.width;
		canvas.height = img.height;
	
		// dibujamos la imagen en el Canvas
		ctx.drawImage(this, 0, 0);
		
	};

La siguiente función permite aumentar el contraste de la imagen pintada en el Canvas:

	// aumenta el contraste
	function AddContrast(val) {

		//combino la formula para obtener el contraste con el valor obtenido del elemento ranges
		var contrast = Math.tan(val * Math.PI / 180.0);

		// reescalamos el canvas a las dimenciones de la imagen
		canvas.width = img.width;
		canvas.height = img.height;
	
		// dibujamos la imagen en el Canvas
		ctx.drawImage(img, 0, 0);
		
		// obtenemos el ImageData
		var imgd = ctx.getImageData(0, 0, canvas.width, canvas.height);
		var pix = imgd.data;
		
		// cambiamos el contraste
		for (var i = 0, n = pix.length; i < n; i += 4) {
			//incremento los valores rojo, verde y azul de cada pixel
			pix[i] = rangeColor(128 + (pix[i] - 128) * contrast);
			pix[i + 1] = rangeColor(128 + (pix[i + 1] - 128) * contrast);
			pix[i + 2] = rangeColor(128 + (pix[i + 2] - 128) * contrast);
		}
		
		// retornamos la data modificada al Canvas
		ctx.putImageData(imgd, 0, 0);
	}

Analizando la función anterior...

Creamos un objeto de tipo Image y le asignamos una imagen fuente.

img = new Image();
img.src = srcImg;

Obtenemos el imageData del Canvas y se opera a nivel de píxeles con el ImageData.data:

// obtenemos el ImageData var imgd = ctx.getImageData(0, 0, canvas.width, canvas.height); var pix = imgd.data;

Por último alteramos los valores de los pixeles agregando contraste a la imagen a los píxeles en su notación RGB:

        for (var i = 0, n = pix.length; i < n; i += 4) {
            //incremento los valores rojo, verde y azul de cada pixel
            pix[i] = rangeColor(128 + (pix[i] - 128) * contrast);
            pix[i + 1] = rangeColor(128 + (pix[i + 1] - 128) * contrast);
            pix[i + 2] = rangeColor(128 + (pix[i + 2] - 128) * contrast);
        }

Para asegurarnos de que el color no se salga del rango 0-255 empleamos la siguiente función:

// valida que el color este en un rango valido function rangeColor(pix) {    if (pix < 0)        pix = 0;    if (pix > 255)        pix = 255;    return pix; }

El brillo

En cuanto al brillo, el mismo consiste en sumar una constante (K) que se encuentre en el rango 0-255; así que con tan solo modificar esta sección de código:

        for (var i = 0, n = pix.length; i < n; i += 4) {
            //incremento los valores rojo, verde y azul de cada pixel
            pix[i] = rangeColor(128 + (pix[i] - 128) * contrast);
            pix[i + 1] = rangeColor(128 + (pix[i + 1] - 128) * contrast);
            pix[i + 2] = rangeColor(128 + (pix[i + 2] - 128) * contrast);
        }

Por esta otra:

        for (var i = 0, n = pix.length; i < n; i += 4) {
            //cambio los valores rojo, verde y azul de cada pixel
            pix[i] = rangeColor(pix[i] + K);
            pix[i + 1] = rangeColor(pix[i + 1] + K);
            pix[i + 2] = rangeColor(pix[i + 2] + K);
        }

Podrás cambiar fácilmente el brillo de una imagen con solo HTML5; la constante K puede ser obtenida a partir de un campo de tipo rango como en el caso del contraste:

<input type="range" id="brightness" min="0" max="255" step="1" value="0">

Enlaces de Interés

Resultado Final

Ver demo Descargar Fuente

Andrés Cruz

Desarrollo con Laravel, Django, Flask, CodeIgniter, HTML5, CSS3, MySQL, JavaScript, Vue, Android, iOS, Flutter

Andrés Cruz en Udemy

Acepto recibir anuncios de interes sobre este Blog.