DesarrolloLibre

Desarrollo Web, Android, juegos y mucho más

Categorias
29-01-2015

En esta entrada veremos como copiar una imagen producto de una captura de pantalla que se encuentre guardada de manera temporal en el portapapeles o clipboard en un elemento <img>.

Además veremos como podemos enviar esta imagen a través de Ajax para su procesamiento y guardado en el servidor; a continuación, la tabla de contenido:

  1. Capturando la pantalla de un ordenador
  2. Guardando la captura de pantalla en un elemento con JavaScript
    1. El evento paste en JavaScript
    2. Definiendo nuestra función para capturar el evento
    3. Explicando la función anterior…
  • Enviando la imagen copiada del clipboard al servidor con Ajax
    1. Guardando la imagen en el servido
    2. Generando un string codificado en base64 de la imagen en el servidor
    3. ¿Cómo guardar la imagen en base64 en nuestra base de datos?
  • 1.0 Capturando la pantalla de un ordenador

    Muchas distribuciones en Linux como Fedora ofrecen aplicaciones desde las cuales podemos realizar capturas de pantallas:

    captura de pantalla aplicación

    Que permiten guardar una imagen producto de la captura de pantalla en alguna ubicación en la computadora o en el portapapeles; este último es parte de nuestro caso de interés.

    También se pueden usar la tecla F12 o la tecla ImprPant provista en muchos teclados; aunque es posible que estas acciones no copien la imagen en el portapapeles o inclusive que no funcionen en determinados sistemas operativos.

    2.0 Guardando la captura de pantalla en un elemento <img> con JavaScript

    Una vez que nos hayamos hecho con la captura de pantalla en el portapapeles, debemos definir un evento que permita capturar el momento cuando copiamos algún contenido en un sitio web mediante:

    Más información en la w3schools.

    2.1 El evento paste en JavaScript

    La API de JavaScript provee un evento que permite capturar el evento paste/pegar a través de la siguiente línea de código:

    window.addEventListener("paste", pasteEvent);
        

    2.2 Definiendo nuestra función para capturar el evento

    Ahora podemos definir la función llamada pasteEvent() que se ejecutará cuando ocurra alguno de los eventos mencionados anteriormente; dicha función permite copiar el contenido del portapapeles en un elemento de tipo <img>; veamos la definición completa de la función:

              window.addEventListener("paste", processEvent);
    
                function processEvent(e) {
    
                    for (var i = 0; i clipboardData.items.length; i++) {
                        // get the clipboard item
                        // obtengo el clipboard item
                        var clipboardItem = e.clipboardData.items[0];
                        var type = clipboardItem.type;
    
                        // verifico si es una imagen
                        if (type.indexOf("image") != -1) {
    
                            // obtengo el contenido de la imagen BLOB
                            var blob = clipboardItem.getAsFile();
                            console.log("blob", blob);
                            // creo un la URL del objeto
                            var blobUrl = URL.createObjectURL(blob);
                            console.log("blobUrl", blobUrl);
                            // agrego la captura a mi imagen
                            document.getElementsByTagName("img")[0].setAttribute("src", blobUrl);
    
                        } else {
                            console.log("No soportado " + type);
                        }
                    }
                }
        

    2.3 Explicando la función anterior…

    ClipboardEvent.clipboardData para leer los datos del portapapeles

    El objeto clipboardData permite acceder en modo sólo lectura a la data contenida en el portapapeles a través de un Array de items; También podemos encontrar el tipo de datos (el cual puede ser texto, imágenes, etc) que se encuentra en una posición determinada del Array.

    var clipboardItem = e.clipboardData.items[i];
        

    Una vez que tengamos el item a evaluar; determinamos el tipo de data y la data almacenada respectivamente:

    Luego de inspeccionar el tipo de data y obtenida la misma, es necesario convertir la data de un objeto BLOB a un DOMString empleando el método createObjectURL() que crea una URL que representa el objeto, para que la imagen pueda ser reenderizada en un elemento de tipo <img>:

    var blobUrl = URL.createObjectURL(blob);
        

    Finalmente copiamos el contenido de la imagen proveniente de la captura de pantalla en un elemento <img>:

    img.attr("src", blobUrl);
        

    2.4 Resultado final del experimento

    Copia la imagen que tengas en el portapapel con Ctrl + V u otra modalidad.

    3. Enviando la imagen copiada del clipboard al servidor con Ajax

    3.1 Guardando la imagen en el servidor

    Un uso útil del experimento presentado anteriormente consiste en poder guardar la imagen ya generada y guardada en un elemento <img> en el servidor; para esto podemos emplear Ajax o un formulario de la manera tradicional; aunque antes de poder guardar la imagen en el servidor debemos procesarla para que pueda ser manejada correctamente.

    3.2 Generando un string codificado en base64 de la imagen en el servidor

    Llegado a este punto, si verificamos el atributo source src de la imagen:

    src img

    Nos daremos cuenta que no es más que un valor que representa nuestra imagen, más no nos ofrece ninguna información sobre la misma; para poder guardar una imagen en el servidor no es posible emplear un tipo BLOB o la URL que lo represente; debemos de codificar la misma en base64 para que la imagen pueda ser procesada fácilmente desde el servidor.

    Podemos convertir nuestra imagen fácilmente de un tipo BLOB a base64 con el siguiente script:

                var reader = new window.FileReader();
                reader.readAsDataURL(clipboardItem.getAsFile());
                
                reader.onload = function() {
                    console.log(reader.result.replace('data:image/png;base64,', '')
                            .toString()
                    $.ajax({
                        type: 'POST',
                        url: URL,
                        data: {
                            'pantalla': reader.result
                                    .replace('data:image/png;base64,', '').toString(),
                        },
                        success: function(response) {}
                });
                }
        

    El objeto FileReader()

    Primero creamos un objeto de tipo FileReader() que permite leer archivos de manera asíncrona.

    Una vez leído el archivo (nuestra imagen) la propiedad result para leer el contenido del archivo/imagen ya codificado en base64;.

    Una vez codificada nuestra imagen, es posible enviar la imagen codificada en base64 por Ajax o a través de un campo en un formulario.

    3.3 ¿Cómo guardar la imagen en base64 en nuestra base de datos?

    Una vez obtenida nuestra imagen codificada en base64 en el lado del servidor se debe de decodificar la misma; si empleamos Java Web podemos usar la siguiente función para decodificar la imagen en base64 a un arreglo de byte:

    byte imagen[] = Base64.decodeBase64(imageString);
        

    En PHP existe una función similar:

    $data = base64_decode($data);
        

    Ya decodificada la imagen se puede guardar el base de datos como si se tratase de cualquier otro archivo obtenido en el servidor por un input de tipo file.

    Consideraciones

    Dependiente de la función empleada para decodificación a emplear puede ser necesario retirar la cabecera data:image/png;base64 presente en nuestra imagen codificada en base64; esto se aplica en para la función Base64.decodeBase64 en Java, en caso de dejarse esta cabecera la imagen podría decodificarse con errores y por lo tanto el archivo estaría corrupto.


    Publicidad

    Give me for a beer!

    Algunos recursos que te pueden interesar

    Eye Candy

    Eye Candy

    Multiple.js para fundir nuestros fondos en HTML

    Multiple.js para fundir nuestros fondos en HTML

    FastClick para eliminar el delay de los 300ms

    FastClick para eliminar el delay de los 300ms

    Algunos artículos que te pueden interesar

    ¿Cómo hacer una sencilla galería con CSS y 6 líneas de JavaScript?

    ¿Cómo hacer una sencilla galería con CSS y 6 líneas de JavaScript?

    En esta entrada explicaremos como crear una sencilla galería empleando CSS y seis (6) líneas de JavaScript.

    Andrés Cruz 12-02-2015

    ¿Cómo agregar markers (POIs) en Google Maps?

    ¿Cómo agregar markers (POIs) en Google Maps?

    Utilizando la API de Google Maps para mostrar la ubicación del usuario.

    Andrés Cruz 01-05-2014

    Cómo cargar y reproducir videos de YouTube de manera programatica con JavaScript

    Cómo cargar y reproducir videos de YouTube de manera programatica con JavaScript

    Se explica como emplear la API de YouTube para JavaScript para controlar el estado de los videos de YouTube en nuestra web.

    Andrés Cruz 01-05-2017