Home Assistant Fácil

Curso de Home Assistant y domótica

  • Blog
  • Soy un pardillo
  • Podcast
  • Curso Arduino
  • Curso Domótica
  • Acceder
Usted está aquí: Inicio / Tutoriales / Fragmentos / JavaScript / Marca de agua con JavaScript

Marca de agua con JavaScript

Luis del Valle Hernández

En este fragmento de código y, siguiendo con el anterior fragmento de código ya publicado donde veíamos como podemos convertir una imagen a escala de grises, vamos a ver como podemos añadir una marca de agua con JavaScript. Lo enmarcamos dentro de los fragmentos dedicados al tratamiento digital de imágenes. Este fragmento resulta un poco más complicado debido a que tenemos que incrustar una imagen dentro de otra. El resultado que queremos obtener es el siguiente:

  • marca-de-agua

Como puedes comprobar las dos imágenes son de diferente tamaño y el logotipo o la marca es una imagen binaria (dos colores). El color negro se va a eliminar y el color blanco es el que vamos a tener en cuenta para hacer la marca de agua.

Respecto al código hay que tener en cuenta ciertas cosas a la hora de recorrer la imagen. Como quiero colocar la marca de agua en el centro hay que calcular la posición donde vamos a insertar la marca para ello calculamos el centro de la imagen original o la imagen donde queremos colocar la marca de agua. Se hace dividiendo por dos el ancho y el alto de la imagen. Obtenido el centro ya podemos calcular la posición X (columnas) e Y (filas) máximo y mínimo para recorrer la imagen original, lo podéis ver más claro en el código.

Para mezclar las dos imágenes se hace una simple media entre las componentes de color. Recuerda que cuando estamos tratando una imagen píxel a píxel, cada uno de ellos tiene cuatro componentes de color R (rojo), G (verde), B (azul) y A (transparencia). La transparencia no la trataremos en este fragmento así que no se tocará. Sumamos las componentes R de la imagen original y de la imagen marca de agua y la dividimos por 2, eso lo hacemos por cada componente y por cada píxel de la imagen. El resultado lo debemos asignar a la imagen original y ya tendríamos nuestra marca de agua incrustada en la imagen original, así de sencillo. A continuación podemos ver todo el código y el resultado de este fragmento.

See the Pen OyJevx by Luis (@delValle) on CodePen.

Si quieres descargarlo todo en un archivo lo puedes hacer con el siguiente código, guárdalo como un archivo HTML y lo puedes ejecutar en tu propia máquina.

<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="https://code.jquery.com/jquery.min.js"></script>

<style>
    #canvas1{border:1px solid #2980b9; background: red;}
    #canvas2{border:1px solid #2980b9; display:none;}
    #original{border:1px solid #2980b9;}
    #logo{border:1px solid #2980b9;}
    td{text-align: center;}
</style>

<script>
// Función inicial de jQuery
$(function(){
  
  // Obtenemos el canvas
  var canvas1 = document.getElementById("canvas1");
  var ctx1 = canvas1.getContext("2d");

  // Creamos un nuevo canvas
  var canvas2 = document.getElementById("canvas2");
  var ctx2 = canvas2.getContext("2d");

  // Imagen original
  var imageOriginal = new Image();

  // Imagen marca de agua
  var imageAgua = new Image();

  //Método click sobre el botón
  $("#convertir").click(function(){

    // Siempre la marca de agua tiene que ser menor que la imagen original
    if(imageOriginal.width < imageAgua.width || 
      imageOriginal.height < imageAgua.height)
    {
      alert('Marca de agua menor que imagen original');
    }
    else
    {
      // Asignamos la misma altura y ancho de la imagen al canvas
      ctx1.canvas.height = imageOriginal.height;
      ctx1.canvas.width = imageOriginal.width;

      // Dibujamos la imagen en el canvas
      ctx1.drawImage(imageOriginal,0,0);

      // Asignamos la misma altura y ancho de la imagen al canvas
      ctx2.canvas.height = imageAgua.height;
      ctx2.canvas.width = imageAgua.width;

      // Dibujamos la imagen en el canvas
      ctx2.drawImage(imageAgua,0,0);

      // Obtenemos la matriz de información de la imagen original
      var imgData1 = ctx1.getImageData(0,0,canvas1.width,canvas1.height);
      var data1 = imgData1.data;

      // Obtenemos la matriz de información de la imagen logo
      var imgData2 = ctx2.getImageData(0,0,canvas2.width,canvas2.height);
      var data2 = imgData2.data;

      // Calculo de la posición central de la imagen
      var centroXmin = Math.round((imageOriginal.width /2) - (imageAgua.width / 2));
      var centroXmax = Math.round((imageOriginal.width /2) + (imageAgua.width / 2));
      var centroYmin = Math.round((imageOriginal.height /2) - (imageAgua.height / 2));
      var centroYmax = Math.round((imageOriginal.height /2) + (imageAgua.height / 2));

      // Variable para almacenar posición
      var posicion = 0;
      var posicionLogo = 0;

      // Recorremos las filas y las columnas de la imagen, píxel a píxel
      for (var x = centroXmin; x < centroXmax; x++) {
        for (var y = centroYmin; y < centroYmax; y++) {

          // Obtenemos posición
          posicion = 4 * (y * imageOriginal.width + x);
          posicionLogo = 4 * ((y - centroYmin) * imageAgua.width + (x - centroXmin));

          // No tenemos en cuenta el negro
          if(data2[posicionLogo] >= 100 &&
            data2[posicionLogo + 1] >= 100 &&
            data2[posicionLogo + 2] >= 100)
          {
            data1[posicion] = (data2[posicionLogo] + data1[posicion])/2;
            data1[posicion + 1] = (data2[posicionLogo + 1] + data1[posicion + 1])/2;
            data1[posicion + 2] = (data2[posicionLogo + 2] + data1[posicion + 2])/2;
          }
        }
      }

      // Asignamos la imagen al Canvas
      ctx1.putImageData(imgData1,0,0);
      ctx2.putImageData(imgData2,0,0);
    }

  });

  // Lectura de imagen OJO, esto puede dar error de acceso con imágenes protegidas
  // Original
  imageOriginal.crossOrigin = "anonymous";
  imageOriginal.src = $('#original').attr('src');
  // Marca de agua
  imageAgua.crossOrigin = "anonymous";
  imageAgua.src = $('#logo').attr('src');

});
</script>

</head>

<body>
  <table>
    <tbody>
      <tr>
        <td>
          <image id="original" src="https://farm4.staticflickr.com/3223/2962074312_06fcfc0a06_m.jpg"></image>
        </td>
        <td>
          <image id="logo" src="https://farm7.staticflickr.com/6058/6216328605_2d0c7b16be_q.jpg"></image>
        </td>
      </tr>
      <tr>
        <td colspan="2">
          <button id="convertir">Aplicar marca de agua</button>
        </td>
      </tr>
       <tr>
        <td colspan="2">
          <canvas id="canvas1" width=140 height=140></canvas>
          <canvas id="canvas2" width=140 height=140></canvas>
        </td>
      </tr>
    </tbody>
  </table>
</body>
</html>
NUKI SMART LOCK

Nuki Smart Lock Go, Pro o Ultra: cuál comprar y la prueba que lo decide todo

Mira chapapote, imagina la cara de tonto que se te queda cuando te gastas casi 350 pavos en una cerradura inteligente Nuki, llega a casa, la abres con … [+ info...]

slzb-06

SLZB-06U: migrar coordinador Zigbee desde Sonoff Dongle P (y por qué el Dongle E es diferente)

Vale, lo confieso: no hay nada que me dé más pereza en domótica que tener que migrar toda la red Zigbee. El típico momento en el que tu viejo … [+ info...]

Home Assistant 2026.6

Home Assistant 2026.6: dashboard inteligente, IR bidireccional y automatizaciones más claras

Llevas meses peleándote con el dashboard de Home Assistant: añadir una tarjeta requería saber de memoria el nombre de cada tipo de bloque, y al final … [+ info...]

Copyright © 2026 · Programar Fácil · Aviso legal