Archivo

Entradas Etiquetadas ‘imagemagick’

Limitando recursos en ImageMagick

Jueves, 21 de Abril de 2011 Gaspar Fernández 2 comentarios

A veces, utilizar ImageMagick puede ser horrible, sobre todo porque en ocasiones, se come todos los recursos de nuestro sistema, al procesar imágenes grandes, múltiples imágenes, vídeo, etc… en ocasiones puede que el OOM Killer de Linux detenga la tarea, y puede que mientras procesamos las imágenes, necesitemos el ordenador para algo.

NOTA: Utilizaré convert para poner ejemplos de cómo utilizar esta herramienta, pero estos consejos valen para todos los programas de tratamiento de imagen que componen imagemagick: convert, mogrify, montage…

Bien, ImageMagick tiene opciones para modificar cuánta memoria va a acaparar. Si sabemos que es una tarea muy pesada para la memoria (una imagen de 5000×5000 ocupará cerca de 70Mb, una imagen de 10000×10000 cerca de 300Mb, sin contar la memoria utilizada para el tratamiento de la imagen) podemos decir a ImageMagick que utilice como mucho 20Mb de RAM (el resto de memoria que necesite la cogerá del disco duro, de nuestro directorio temporal).
Para esto, podemos utilizar lo siguiente:

$ convert imagenA.jpg -limit memory 20MiB -resize 50% imagenB.png

Si durante el proceso, ejecutamos top podremos ver la diferencia de memoria utilizada.
Podemos ver los recursos que podemos limitar con:

$ identify -list resource
File Area Memory Map Disk Thread Time
——————————————————————————-
768 4.2324GB 2.9563GiB 7.8835GiB 18.446744EB 1 unlimited

Las peticiones de memoria que hace ImageMagick como vemos aquí son las siguientes:
Se intenta reservar memoria para los pixels, pero si la memoria excede el límite de memory, o falla (puede que el sistema no disponga de memoria suficiente), lo escribirá en disco y lo mapeará en memoria, pero si se excede la memoria del mapa de memoria, todo va a disco, si ya no tenemos disco duro suficiente, o hemos limitado el disco disponible fallará.
Tenemos que tener en cuenta que hacemos distinción entre MiB (MebiBytes) (1MiB=1.048.576 bytes) y MB (MegaByte) (1MB = 1.000.000 bytes)

Así que también podemos limitar la memoria de los mapas de memoria, de disco, los threads a utilizar (o podemos darle más, si queremos), por ejemplo, si queremos insertar imágenes en un pdf:

$ convert *.jpg -limit memory 200MiB -limit map 200MiB resultado.pdf

También es muy útil el parámetro de area, este vale para limitar la memoria de forma absoluta, es decir, para que ImageMagick no intente hacer nada en memoria si excedemos esta cantidad de memoria (a veces es mejor limitar la memoria, antes de que intente encajar las reservas de memoria en los otros dos parámetros, y tenemos más control sobre la memoria utilizada):

$ convert *.jpg -limit area 300M resultado.pdf

Todas estas opciones de ImageMagick pueden ser variables de entorno: MAGICK_AREA_LIMIT, MAGICK_DISK_LIMIT, MAGICK_FILE_LIMIT, MAGICK_MEMORY_LIMIT, MAGICK_MAP_LIMIT, MAGICK_THREAD_LIMIT, MAGICK_TIME_LIMIT. Podemos hacer lo siguiente para ver que los cambios se aplican correctamente:

$ export MAGICK_AREA_LIMIT=50M
$ export MAGICK_MEMORY_LIMIT=10MiB
$ export MAGICK_MAP_LIMIT=30MiB
$ convert -list resource
File Area Memory Map Disk Thread Time
——————————————————————————-
768 50MB 10MiB 30MiB 18.446744EB 1 unlimited

Como habréis podido comprobar, también se puede limitar por tiempo, incluyendo -limit time [segundos] o con la variable de entorno MAGICK_TIME_LIMIT.

Pero no acaba aquí, podemos hacer que el procesado de imagen sea un poco más lento, pero nos deje el ordenador libre para otros usos, esto es con la variable de entorno MAGICK_THROTTLE, ImageMagick periodicamente dejará respirar el procesador tantos milisegundos como le hayamos asignado a la variable:

export MAGICK_THROTTLE=100

Dejará de procesar 100ms en varias ocasiones durante el proceso, lo podremos usar si vemos que el proceso será largo, no nos importa la velocidada y va a utilizar toda nuestra CPU.

También podemos acompañar todas estas opciones de ImageMagick con nice e ionice. Por ejemplo, con ionice podremos retrasar o priorizar los accesos a disco y con nice la prioridad del proceso. Si de verdad no nos importa cuánto tarde la conversión podemos hacer lo siguiente:

nice -n 20 ionice -c3 convert *.jpg -limit area 200M resultado.pdf

Con lo que asignaremos la menor prioridad al proceso, y además sólo accederá a disco cuando nadie más lo haga (si otro proceso quiere escribir en disco, convert tendrá que esperar)

Jugando con ImageMagick (III): Colecciones, texto, y unión de efectos

Lunes, 6 de Septiembre de 2010 Gaspar Fernández Sin comentarios

El tercer post de la serie, anteriormente hablábamos de:

  1. Dimensiones, Captura, Color y Efectos
  2. Color (continuación) y Rotación

Juntando imágenes en una sola

Ahora, la cosa se anima, veremos cómo recopilar varias imágenes en el mismo archivo de imagen; habréis visto algún ejemplo en la entrega II, en los que muestro varias imágenes juntas:

variasPara ello usamos montage:

$ montage -tile 4×2 -geometry 200×160+1+0 taza1.jpg taza2.jpg taza3.jpg taza4.jpg hamburgueson1.jpg hamburgueson2.jpg hamburgueson3.jpg hamburgueson4.jpg varias.jpg

Donde, con el parámetro tile, especificamos la agrupación de las imágenes ancho x alto (4×2 en este caso) y con geometry, el tamaño de cada imagen 200×160 de máximo, con una separación de 1 pixel a los lados y ninguno verticalmente.

La imagen conserva su aspecto, pero de alto ocupa 160 pixels por lo que existe una pequeña separación.

Añadiendo texto

outSin imagen original, simplemente un texto en un archivo de imagen. Obtenido de la siguiente forma:

$ convert -background black -fill red -gravity center -font Verdana -pointsize 20 -size 200×80 caption:’Rojo sobre negro’ rojosobrenegro.png

Donde:

  • -background especifica el color de fondo
  • -fill especifica el color de primer plano
  • -gravity es la alineación, centrada, tanto horizontal como verticalmente.
  • -font indica el tipo de letra
  • -pointsize indica el tamaño de la letra
  • -size indica el tamaño de la imagen (porque no vamos a utilizar ninguna imagen de origen).
  • caption:’Texto’ con ello indicamos el texto

out1

$ convert -size 300×120 xc:rgb\(50,50,70\) -fill rgb\(90,150,200\) -gravity SouthEast -font helvetica -pointsize 25 -draw ‘text 10 2 “Poesía Binaria”‘ poesia_binaria.jpg

Donde incluimos el texto en una determinada posición: 10×2 desde la esquina inferior derecha (SouthEast), tipo de letra helvetica y tamaño 25; de fondo (50,50,70) y de color (90,150,200).

out2Ahora, aprovecharemos un poco más las capacidades de la orden draw. Para ello, dibujaremos un cuadro en negro dentro de la imagen (antena.jpg de dimensiones 314×300) a modo de marco (verde); luego trazaremos una línea horizontal de color blanco (rojo) en el borde del cuadro que acabamos de dibujar y tras ello escribiremos un texto (azul).

$ convert antena_2.jpg -gravity SouthEast -font helvetica -pointsize 25 -fill black -draw ‘rectangle 0,270 314,300′ -fill white -draw ‘line 0,270 314,270′ -draw ‘text 13 1 “Mi antena Wifi”‘ out.jpg

out3Ahora introduciremos el texto directamente en la imagen, pero para facilitar la lectura incluiremos una sobra en el texto.

$ convert antena_2.jpg -gravity North -font helvetica -pointsize 25 -fill black -draw ‘text 0 0 “Mi antena Wifi”‘ -fill white -draw ‘text 1 1 “Mi antena Wifi”‘ out.jpg

Podemos incluir de forma opcional -blur 1×1 (por ejemplo) para difumirar el texto que hace de sombra y suavizarla.

Juntando los efectos disponibles

Uno de los mejores ejemplos es el siguiente: http://www.imagemagick.org/Usage/thumbnails/ aunque encontramos cientos de webs con efectos preparados para ImageMagick:

Uso de llaves en BASH

Sábado, 15 de Mayo de 2010 Gaspar Fernández 1 comentario

llaves
Leo en el blog de Thalskarth (proveniente de Tux Files, que a su vez venía de Slice of Linux) un truco para hacer copias de seguridad de un archivo con bash de la siguiente forma:

cp archivo{,.bk}

Lo que hacemos es parecido a escribir esto otro:

cp archivo archivo.bk

Por lo que podemos intuir fácilmente para qué valen las llaves en este contexto: replicar alternativas. Es decir escribiremos lo que hay antes de la llave, y lo terminaremos con cada una de las opciones de dentro de las llaves que están separadas por comas. Y lo más fácil para entender esto es utilizar echo.
Probaremos lo siguiente:

$ echo “Voy a pintar mi casa de “{verde,azul,rojo,amarillo}
Voy a pintar mi casa de verde Voy a pintar mi casa de azul Voy a pintar mi casa de rojo Voy a pintar mi casa de amarillo

Bien, el mensaje se replica con un espacio entre réplicas. Podemos ahora probar algo más:

$ echo -e “Voy a pintar mi casa de “{verde,azul,rojo,amarillo}”.\n”
Voy a pintar mi casa de verde.
Voy a pintar mi casa de azul.
Voy a pintar mi casa de rojo.
Voy a pintar mi casa de amarillo.

Además, podemos ver que la llave no tiene por qué estar al final del parámetro, podemos ponerla en mitad y sigue funcionando. Hay un espacio al principio de la línea, como mencioné antes, las frases irán separadas por un espacio (es normal, las llaves nos sirven para introducir nuevos parámetros). Podremos solucionarlo con \b (backspace).

echo -e “\bVoy a pintar mi casa de “{verde,azul,rojo,amarillo}”.\n”
Voy a pintar mi casa de verde.
Voy a pintar mi casa de azul.
Voy a pintar mi casa de rojo.
Voy a pintar mi casa de amarillo.

Antes de nada un apunte, no debemos dejar espacios dentro de las llaves, ni entre las comas, ni dentro de cada opción, no olvidemos que son parámetros, aunque sí que podríamos poner un espacio si éste va entre comillas (igual que ocurre con los parámetros).

Crear PDFs

Y a partir de aquí, sólo necesitamos imaginación, por ejemplo podemos ver cómo lo usamos para crear un pdf con imágenes en jpeg (de una carpeta llamadas test-N.jpg). Lo creamos con ImageMagick y sólo queremos de la 1 a la 12:

$ convert test-{?.,10.,11.,12.}jpg todos.pdf

Aunque hay un método mejor, {} (las llaves) soportan rangos, por lo que podemos hacer:

$ convert test-{1..12}.jpg todos.pdf

Comprimir directorios

Podemos, por ejemplo crear un archivo comprimido de un directorio con el mismo nombre de la siguiente manera:

$ tar cvjf test{.tar.bz2,/}

como sustitución a:

$ tar cvjf test.tar.bz2 test/

Diferencias

Encontrar la diferencia de un archivo con su backup (suponemos que el backup es el mismo nombre terminado en ~ (tilde de la ñ):

$ diff test{,~}

O para diferencias rutas (recordemos que podemos poner llaves entre parámetros:

$ diff ~/proyectos/www/{proyecto1,proyecto2}/www/lib/my_lib.h

Que es lo mismo que:

$ diff ~/proyectos/www/proyecto1/www/lib/my_lib.h ~/proyectos/www/proyecto2/www/lib/my_lib.h

Lectura de datos en scripts

Para leer desde la entrada estandar tenemos read, y si queremos introducir cada palabra en una variable podemos usar read palabra1 palabra2 palabra3, y si queremos que estas variables tengan un prefijo común:

$ read palabra{A,B,C}

Combinaciones y juegos

Vamos a hacer múltiples sumas con bc:

$ echo -e {1..4}”+”{4..1}”\n” | bc

Esto pondrá en pantalla el resultado de: 1+4, 1+3, 1+2, 1+1, …, 4+3, 4+2, 4+1.
Con esto vemos que los rangos no sólo van en incremento sino también en decremento.
Pero aún más si hacemos:

echo test{a..z}

Nos completará con testa testb testc…testx, testy, testz

Por último, un ejemplo más complicado, y que, aunque pocas veces nos sirva (más que nada por no acordarnos), ahí queda, llaves anidadas:

$ echo test-{1{10..12},3{9..1}}
test-110 test-111 test-112 test-39 test-38 test-37 test-36 test-35 test-34 test-33 test-32 test-31

Tenemos la posibilidad de introducir opciones dentro de otras opciones y todas se representarán seguidas. ¿Tal vez nos sirva alguna vez para crear un fichero de texto con datos de prueba? Para crear un archivo con temperaturas de varias ciudades:

$ echo -e “\b”{”Madrid 1″{1..4},”Barcelona 1″{3..5},”Malaga “{19..22},”Sevilla 2″{3..4}}”\n” > test

Esto creará un fichero llamado test con el siguiente contenido:

Madrid 11
Madrid 12
Madrid 13
Madrid 14
Barcelona 13
Barcelona 14
Barcelona 15
Malaga 19
Malaga 20
Malaga 21
Malaga 22
Sevilla 23
Sevilla 24

Foto: bohman (Flickr)

Visita otras webs de la red