Como obtener el tamaño de imágenes con Google Apps Script

Puede haber ocasiones en que obtener el tamaño de imágenes usando Google Apps Script puede ser extremadamente útil para automatizar tareas, el problema es que esto es bastante difícil de conseguir (te reto a que lo encuentres :) ).  Aunque me ha costado bastante he conseguido desarrollar un manera de hacerlo y que me permite ahorra bastante tiempo diario al calcular los tamaños de grupos de imágenes.

He montado un spreadsheet con esta estructura, donde puedes poner la lista de url a las imagenes y al ejecutar el script se rellenan el height y el width de la imagen gracias a la magia de Google Apps Script.
como calcular tamaño de una imagen con Google Apps Script


Como conseguirlo?
En este caso concreto, el gran problema no es saber programar, sino encontrar la manera de poder obtener la información que queremos. Desde Google Apps Script es IMPOSIBLE conseguirlo directamente, no hay herramienta que te lo permita, pero, desde JavaScript si que es factible saber el tamaño de una imagen.

El código para saber el tamaño de una imagen con JavaScript seria tal que así:
function GetImagesize()
{
	var img = new Image();
	img.addEventListener("load", function()
            {
               var url = this.currentSrc;
               var width  = this.naturalWidth;
               var height = this.naturalHeight; 
		//Aqui hacemos lo queramos con ese tamaño	
            });
	img.src = url_de_tu_imagen;
}

Básicamente, creamos un objeto de tipo imagen (una de las pocas cosas de JavaScript que no podemos hacer en Google Apps Script), le marcamos que cuando la imagen este cargada obtenga el tamaño de la imagen correspondiente y le damos la url de la imagen a cargar.

Tal como hemos dicho esto no puede hacerse en Google Apps Script, pero... desde Google Apps Script si que podemos servir una web que use JavaScript. Es más, podemos hacer que esta web esta embedida dentro de un popup en un spreadsheet, de forma que cuando llamemos a este popup desde nuestro spreadsheet se realice todo el proceso de obtención de tamaños de imágenes. 

Ahora el problema que tendremos es que la obtención de los tamaños de las imágenes se producirá de forma asíncrona (se obtendrá cuando la imagen se haya cargado), de forma que esta información la tendremos que ir guardando hasta que no la podamos recuperar toda. La forma más fácil es usar la cache ( sessionStorage ) de JavaScript.

Finalmente solo necesitaremos transferir toda esta información desde JavaScript a Google Apps Script para poder guardarla en nuestro spreadsheet.

Como podéis ver, el proyecto es bastante más complicado de lo que parece, pero personalmente ha sido todo un orgullo poderlo completar.

Os adjunto todo el código del proyecto para que podáis ponerlo en práctica.

Espero que os sirva! 

No dudéis en hacerme llegar vuestras propuestas!

Code.gs
function onOpen()
{
  SpreadsheetApp.getUi().createMenu("SCRIPT")
          .addItem("CheckSize","CheckSize")
          .addToUi();
}

function AskForList()
{
  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  var sheeturl = spreadsheet.getActiveSheet();
  var images   = sheeturl.getRange(1,1,sheeturl.getLastRow(), 1 ).getValues();

  var elements = new Array();
  for(var i = 1 ; i < images.length ; ++i)
  {
      var url = images[i][0];
      var element = new Object();
      element.url    = url;
      elements.push(element);
  }
  return elements;
}

function ReportSizes(sizes)
{
   var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
   var sheet = spreadsheet.getActiveSheet();
   for(var i = 0 ; i < sizes.length ; ++i)
   {
     var size = sizes[i];
     sheet.getRange(i+2,2).setValue(size.Height);
     sheet.getRange(i+2,3).setValue(size.Width);
   }
}

function CheckSize()
{
  var html = HtmlService.createHtmlOutputFromFile('index').setWidth(100).setHeight(100);
  SpreadsheetApp.getUi().showModalDialog(html,"Image Size");
}

index.html
<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <script>
      function getSize(url)
      {   
        var img = new Image();
        img.addEventListener("load", function()
            {
               var url = this.currentSrc;
               var width  = this.naturalWidth;
               var height = this.naturalHeight; 
               sessionStorage[url+"_width"] = width;
               sessionStorage[url+"_height"]= height;
            });
        img.src = url;
      }
      
      function ReciveDone()
      {
        document.getElementById("button").innerHTML = "<a> PROCESS END </a>";
      }

      function ReciveWaiting(list)
      {
         var errors = new Array();
         
         for(var i = 0 ; i < list.length ; ++i )
         {
            var element = list[i];
            var width  = sessionStorage[element.url+"_width"];
            var height = sessionStorage[element.url+"_height"];
            list[i].Height = height;
            list[i].Width  = width;
         }

         google.script.run.withSuccessHandler(ReciveDone).ReportSizes(list);
      }

      function ReciveList(list)
      {
         sessionStorage.clear();
         for(var i = 0 ; i < list.length ; ++i )
         {
            var element = list[i];
            getSize(element.url);
         }
         google.script.run.withSuccessHandler(ReciveWaiting).AskForList();
      }

      function AskForList()
      {
         document.getElementById("button").innerHTML = "";
         google.script.run.withSuccessHandler(ReciveList).AskForList();
      }
    </script>
  </head>
  <body>
     <div id="button">
        <input type="button" onclick="AskForList()" value="PROCEED">  
     </div>
  </body>
</html>

4 comentarios:

  1. Hola Fátima,
    Te tengo que decir que no lo se. Tendría que mirarmelo. El tema del recorte lo veo complicado la verdad.
    Me lo apunto y cuando tenga un rato me lo miro, no te aseguro nada.
    Nos vemos!

    ResponderEliminar
  2. Gracias por compartir.
    Estoy intentando obtener el tamaño de una imagen (desde una URL) y al colocar el código de la función "getSize(url)" en el archivo "Code.gs" - hoja de scripts del spreadsheet; pero, al ejecutar la función dice "ReferenceError: Image is not defined".
    Mirando más de cerca su código; la función "getSize(url)" está en una página .html "index.html"
    Tengo varias inquietudes.
    1. ¿No hay manera de que google app script reconozca la "clase" Image?
    2. ¿Cómo colocar el archivo html "oculto" para (desde allí colocar la función que obtiene el tamaño de la imagen)?
    3. ¿Qué alternativas hay para obtener el tamaño de la imagen?
    He buscado y esta es la opción más cercana, pero, no veo cómo google app script no tiene habilitado javascript - la verdad no sé cómo es que está la clase "Image" enlazada a javascript o JQuery.
    Gracias.

    ResponderEliminar
    Respuestas
    1. Hola,
      1. Nope, por ahora al menos,no. GAS es lenguaje de servidor, no de cliente.
      2. La única forma que encontré es la que mostré en este artículo, sorry.
      3. Creo q hay alguna librería ( tendrías que buscarla ) que te permite analizar las imagenes y através de su parseo decidir el tamaño. Por lo que vi en su momento, no era fiable y daba bastantes errores, así que no la tuve ni en cuenta. Tal vez si buscas encuentras algo que esté mejor a dia de hoy.

      Si te sirve de consuelo, todas las preguntas que te estás haciendo fueron las mismas que me hice yo en su momento.

      Suerte!

      Eliminar
  3. Saludos! una pregunta, cuando intento correrlo solo aparece la ventana donde hago click en proceed, y no pasa nada luego. ¿Me estoy brincando algún paso para su ejecución?

    ResponderEliminar

Tal vez te interese