El semestre antepasado lleve la clase de tratamiento de imágenes multiespectrales con el Dr jorge Lira. Fue un curso muy pesado tareas y practicas a diestra y siniestra, además incluían manejar imágenes en un formato RAW para evitar la pedida de información, (esto se traducía en que cada practica o tarea que queríamos hacer, involucraba de 500MB a 1GB en 10 o 15 imágenes). Lo mas feo del asunto es que las imágenes en RAW no son interpretables en casi ningún programa, para poder transformarlas en lindos png o jpg (o tiff) que pudiéramos usar en los reportes y tareas (Documentos de LaTeX o de Open Office).
Prácticamente dependíamos de un programa comercial (privativo) que el Dr tenia en su laboratorio para guardar una copia de la imagen en algún formato mas universal. No contentos con llevar nuestro GB de imágenes en raw con los datos de la practica, teníamos que viajar con una copia de la imagen en jpg para poder escribir nuestro reporte.
Fue entonces cuando mi amiga Etna, me presento con ImageMagick.
Y que es ImageMagick…
Es un conjunto de programas libres que sirven para convertir, transformar, y procesar imágenes en casi cualquier formato (y lo digo en serio). Lo que lo hace tan poderoso y flexible es que su interfaz es en linea de comandos, por lo que es ideal para desarrollar programas que ocupen ImageMagick y procesen imágenes (de hecho hay bindings para varios lenguajes de programación).
Una de las chucherias de ImageMagick es convertir de formato raw a cualquier formato.
Por que lo querría usar uno normalmente.
La segunda vez que me encontré con la necesidad de procesar un montón de imágenes y que me motivo a escribir este post fue regresando de las vacaciones en Oaxaca. Yo no llevaba mi cámara, pero Erika y Mag me pasaron sus fotos.
Ya saben tenia cientos de imágenes con títulos bien descriptivos como IMG_2379.JPG que pesaban algo así como 600Kb y median como 3072×2304 píxeles. Lo cual si hubiera querido subir en mi blog, conllevan un montón de trafico de red, y además seria un desperdicio, por que quien tiene un monitor con esa resolución (Vamos los que las vieran las tendrían que rescalar antes de verlas).
La solución de nuevo es ImageMagick
Como se usa ImageMagik
Pues el comando convert (que no es el único que conforma ImageMagick), nos da toda la versatilidad que queremos.
Escalando una imagen
Al escalar una imagen debemos de tener cuidado de hacerlo de una manera de que conserve su proporción (su aspect ratio), la mayoría del SW nos deja hacerlo si le decimos que no queremos deformaciones, también se puede hacer en ImageMagick
convert -resize 50% input.jpg output.jpg
Al darle en porcentaje el tamaño, Imagemagick sabe que no debe modificar el aspect ratio.
Reduciendo la calidad de la imagen
Hay dos tipos de compresión una donde no se pierde información llamada lossless, y otra llamada lossy compresión que es cuando un imagen pierde parte de su información al comprimirse. Cuando guardamos una imagen en formato jpg se esta haciendo una compresión con pérdida (lossy). El algoritmo del jpg es lo suficientemente flexible para dejarnos controlar la perdida con un parámetro de calidad. Mientras menos sea la calidad menor sera la perdida y mayor el tamaño de la imagen.
Sin embargo el algoritmo es tan bueno que bajar un poco la calidad de la imagen, suele bajar en mucho el tamaño (en bytes) de la misma, aproximadamente una imagen al 90% de calidad mide una cuarta parte que la imagen original. El estándar para publicar en una web es del 85%.
Para hacerlo en ImageMagick se ocupa el siguiente comando
convert -quality 85% input.jpg output.jpg
Corrigiendo la orientación
Otra cosa interesante es que ImageMagick puede corregir la orientación de una imagen de una cámara si los metadatos de la foto tienen esa orientación con el comando
convert -auto-orient input.jpg output.jpg
Ojo esto no siempre funciona (a veces los metadatos de la cámara no están bien), por lo que siempre es bueno darle una checada a la imagen de salida. También recuerda que en muchos navegadores de archivos se aplica esta corrección, pero eso no quiere decir que la imagen este volteada, si no que el visor de imágenes la esta transformando para que la veas.
Eso puede provocar que en tu máquina tu veas la imagen al derecho y cuando la subas a un sitio web, la veas al revés. La única forma de saberlo es viendo el tamaño de la imagen y ver si es mas alta que ancha o viceversa.
Y desde luego todos estos pasos se pueden llevar a cabo al mismo tiempo. Por ejemplo:
convert -auto-orient -quality 85% -resize 50% input.jpg output.jpg
Y poniendo todo en un script
Aprovechando que tuve que aprender un poco de bash, para un programa de la tesis, escribí el siguiente scrip en bash, para hacer las operaciones antes descritas sobre una carpeta con muchas imágenes.
El script tiene las siguientes características:
- Siempre trata de hacer la corrección de orientación
- Acepta opcionalmente los siguientes parámetros
- -q quality Para reducir de calidad las imágenes, el parámetro debe ser entero y estar en el intervalo (0, 100)
- -s size Para reducir el tamaño en un porcentaje, (en ImageMagick esto no necesariamente tiene que especificarse así, pero en el scrip valido que solo se pueda cambiar el tamaño en un porcentaje) que acepta enteros en el intervalo (0, 100)
- -n name Para especificar un patrón de nombre de la imagen de salida, en caso de que este parámetro no se le proporcione, las imágenes de salida tendrán el mismo nombre que las de salida (puede que las sobrescriban), con la única excepción que valido que en la imagen de salida la extensión siempre sea en minúsculas (odio que en la mayoría de las cámaras, las extensiones de las imágenes estén en mayúsculas DSC_001.JPG)
En resumen el scrip corrido en su forma completa por ejemplo:
photo2wp.sh -q 85 -s 50 –name Vacaciones
Tomara todas las imágenes con extensión jpg ó JPG que haya en el directorio actual. A cada una de ellas las escalará al 50% respetando su aspect ratio, las comprimirá en jpg, con el 85% de calidad y las imágenes de salida tendrán el nombre VacacionesXXX.jpg. Donde XXX es un numero progresivo que depende de la cantidad de imágenes que haya en la carpeta.
Es posible pasar mas de una palabra en el nombre pero entonces hay que encerrarlo en comillas:
photo2wp.sh -q 85 -s 50 –name “Mis Vacaciones”
Todos los argumentos son opcionales:
photo2wp.sh -q 85 –name Vacaciones
Por ejemplo comprime todas las imágenes al 85% y las renombra como VacacionesXXX.jpg, sin escalar su tamaño.
En un abuso de las opciones, puede usarse sin argumentos
photo2wp.sh
Que toma todas las imágenes, trata de corregir su orientación, y las guarda con el mismo nombre pero asegurándose que la extensión sea en minúsculas (si las imágenes originales tienen su extensión en minúsculas, las va a sobrescribir)
Por ultimo algunas recomendaciones:
- No he testeado el script al 100%, así que siempre ten una copia de tus imágenes originales. (Aún cuando no uses mi script esto es buena practica)
- Recuerda que el script solo funciona cuando ya tienes instalado el ImageMagick en tu maquina.
- Si quieres usar el script, recuerda que antes que nada debes darle permisos de ejecución.
- Recuerda que el script solo actúa sobre el directorio en el que esta siendo ejecutado. No se mete recursivamente en carpetas.
Finalmente el script esta aqui (copia y pega en un archivo de texto yo lo llame photo2wp.sh, pero pon el nombre que quieras):
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 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 | #!/bin/bash #Este scrip toma todas las fotos de la carpeta donde se ejecute y las #procesa. Primero la pone al derecho dependiendo de los metadatos, #les cambia de nombre y las guarda con un tamaño y una calidad #determinadas por las opciones function dameNumero { if [ $total -lt 100 ]; then if [ $cont -lt 10 ]; then number="0$cont" else number="$cont" fi elif [ $total -lt 1000 ]; then if [ $cont -lt 10 ]; then number="00$cont" elif [ $cont -lt 100 ]; then number="0$cont" else number="$cont" fi else if [ $cont -lt 10 ]; then number="000$cont" elif [ $cont -lt 100 ]; then number="00$cont" elif [ $cont -lt 1000 ]; then number="0$cont" else number="$cont" fi fi } #Aqui parseamos las opciones qflag=0 sflag=0 nflag=0 while getopts 'q:s:n:' OPTION do case $OPTION in q) qflag=1 quality="$OPTARG" ;; s) sflag=1 size="$OPTARG" ;; n) nflag=1 nameBase="$OPTARG" ;; *) printf "Usage: photo2wp.sh [-q <quality>] [-s <size>] [-n <name>]" >&2 exit 2 ;; esac done #Si no nos dieron quality asume el 100 if [ $qflag -ne 1 ]; then quality=100 fi #Si no nos dieron size asume el 100 if [ $sflag -ne 1 ]; then size=100 fi #Checamos que quality sea valido if [[ $quality =~ ^[0-9]+$ ]]; then if [ $quality -gt 100 -o $quality -lt 0 ] then echo "El parámetro quality debe se un número entero en el intervalo [0, 100]" >&2 exit 3 fi else echo "El parámetro quality debe se numérico y entero" >&2 exit 3 fi #Ahora validamos el valor de size if [[ $size =~ ^[0-9]+$ ]]; then if [ $size -gt 100 -o $size -lt 0 ] then echo "El parámetro size debe se un número entero en el intervalo [0, 100]" >&2 exit 3 fi else echo "El parámetro size debe se numérico y entero" >&2 exit 3 fi #Contamos cuantas imagenes hay total=`ls *.[jJ][pP][gG] 2>/dev/null | wc -l` if [ $total -eq 0 ]; then echo "No hay imagenes que procesar en esta carpeta" exit 1 fi #Calculemos las opciones y avisemos al usuario que vamos a hacer opciones="-auto-orient" echo "Hay $total fotos" if [ $sflag -eq 1 ]; then echo "Se van a escalar a un tamaño de: $size%" opciones="$opciones -resize $size%" fi if [ $qflag -eq 1 ]; then echo "Se van a comprimir con una calidad de: $quality%" opciones="$opciones -quality $quality%" fi if [ $nflag -eq 1 ]; then echo "Se guardaran con el nombre: $nameBase[XXX].jpg" fi #Todo correcto empezamos a procesar cont=0 number="" output_file="" images=*.[jJ][pP][gG] #Ciclo principal sobre todas las imagenes de entrada for input_file in $images do #Calculamos el nombre de la imagen de salida cont=`expr $cont + 1` dameNumero if [ $nflag -eq 1 ]; then output_file="$nameBase$number" else output_file=${input_file%%.*} fi #Realizamos la conversion if convert $opciones "$input_file" "$output_file.jpg" 2>/dev/null ; then echo "Imagen $cont de $total" else echo "$input_file no pudo ser procesada..." >&2 fi done exit 0 |
#1 by Etna on 16 julio 2010 - 18:00 pm
Suuuper padre el artículo
#2 by nemediano on 16 julio 2010 - 19:21 pm
Gracias, ahora que lo leo me falto decir como transformar los raw, que era el meollo con el que empezó esto XD.
y pues ahora a seguirle dando al Imagemagick
Que bueno que te gusto
#3 by Juan Adan on 28 agosto 2010 - 17:37 pm
Que ondas Antonio!!
me di tiempo y entre a tu blog
saludos!
#4 by nemediano on 30 agosto 2010 - 13:37 pm
Gracias por la visita Juan.
Tiene desde el noveno semestre de la carrera que no te veo y también un buen rato que no se de ti.
espero que tu estés bien, saludos