Foto-blog de Antonio Castro

Retoque fotográfico con Gimp, fotos copyleyft, licencia Creative Commons (CC-BY), fotos gratis para uso comercial con reconocimiento.

Macrofotografía abeja

Etiqueta: jpeg

Bug repartido entre ImageMagick, ffmpeg, mencoder, y recordmydesktop.

Si haces uso de estos programas este artículo te puede interesar, y en caso contrario te parecerá la típica batallita de programación que sólo interesa a los frikis del software libre.

Tengo publicado un artículo en el cual presenté un script ‘dir2avi.py’ que procesaba todas la imágenes ‘*.jpg’ de un directorio y obtenía un vídeo avi, pero he descubierto que no siempre funciona bien, lo curioso es que no es por un problema de mi script y el bug está muy repartido entre diversas aplicaciones.

El fallo de ordenador de dio nombre a los bugs de programación.

El fallo de ordenador de dio nombre a los bugs de programación.

He usado aquel script y en determinadas ocasiones generaba unos vídeos con ciertas anomalías cromáticas, apareciendo manchas de colores. Incluso he publicado algún vídeo en youtube que presentaba este problema ante la impotencia de localizar el problema, pero esta vez me afectaba a un proyecto que quiero que tenía mucho interés en que quedara perfecto así que he dedicado bastante tiempo a investigarlo.

El vídeo siguiente de sólo 8 segundos muestra el efecto que tiene el bug en un vídeo.

Hice varias pruebas haciendo toda clase de variaciones posibles para hacer vídeos a partir de imágenes y para mi sorpresa resultó que de una forma o de otra en algunos casos concretos reaparecía siempre el mismo problema fuera cual fuera el método empleado.


Las imágenes jpeg de partida aparecían perfectas, pero el vídeo que producían determinadas colecciones de imágenes presentaba problemas y era difícil saber la razón. Intenté un montón de cosas:
  • Para descartar un bug en ffmpeg probé a generar el vídeo con mencoder, pero no tuve suerte.
  • Para descartar un bug en algún codec probé con distintos codecs de vídeo en ffmpeg, igualmente sin éxito.
  • El problema también apareció pasando un vídeo de formato ogg a un formato avi con ffmpeg, lo cual parecía descartar totalmente el problema en mis imágenes. Este ogg lo generé capturando vídeo desde el escritorio con recordmydesktop así que  el problema parecía burlarse de mi sentido de la lógica.
  • Quizás fuera el formato de vídeo y probé a generarlo en varios formatos (avi, mp4, mpeg, ogg, flv), pero tampoco.
  • Quizás a ffmpeg no le gusta que yo redimensione con la opción -s y use simultáneamente -sameq, así que probé a no redimensionar, a redimensinar con el mismo tamaño de la imagen, a no indicar la dimensión para que la tomara de las imágenes originales, pero nada de eso tuvo éxito.

Fueron varios días insistiendo sin éxito. El problema sólo aparece usando algunas colecciones de imágenes,  pero no lograba descubrir en que se diferencian los jpegs que daban problemas de los restantes que no los daban. Por fin llegó mi primer éxito y una posible solución. Si las imágenes que daban problemas al pasarlas a vídeo eran convertidas previamente a otro formato, por ejemplo png, el problema desaparecía confirmando el problema con el formato de las imágenes de entrada.

Decido entonces investigar un poco más los jpegs y verificando una de estas imágenes usando el comando identify -verbose de ImageMagick descubro que aparece una información contradictoria en la cabecera exif respecto al ColorSpace. En la misma imagen figura lo siguiente:
  • exif:ColorSpace: 1
  • jpeg:colorspace: 2

Uno de los dos valores debe de ser incorrecto, y los campos exif son meramente informativos.

Una breve aclaración sobre exif:
Exchangeable image file format (abreviatura oficial Exif) es una especificación para formatos de archivos de imagen usado por las cámaras digitales. Las etiquetas (tags) de metadatos definidas en el estándar Exif cubren un amplio espectro de valores. Los programas antiguos no tienen en cuenta estos valores, y los modernos los manejan como información de usuario final  principalmente.
Una imagen sin información exif es perfectamente funcional, así que no parecía muy lógico que un dato erróneo en un campo exif tuviera consecuencias en el software, pero tratándose de un caso rarito y existiendo el dato contradictorio me construyo un script que elimine todos los campos exif de mis imágenes jpeg, y … ¡Eureca!
Quitar la información exif en la imágenes jpg solucionaba el problema para ffmpeg.

Esto puede que no resulte muy emocionante para la inmensa mayoría de los mortales, pero apuesto que son muchos a lo largo y ancho de Internet que han tropezado con este escurridizo bug sin sospechar de qué se trata. Para eliminar la información exif del jpeg recurrí a la librería de imágenes PIL en python, y lo que hago con cada fichero de imagen es simplemente esto:
import Image
img=Image.open(fi)
(x,y)=img.size
img.resize(img.size) # Redimensinamos al mismo tamaño. Es un truco para suprimir toda la info de exif
img.save(fi)
Después de hacer esto las imágenes quedan sin campo exif y ffmpeg ya genera el vídeo correctamente. (Me quedé muy sorprendido cuando esto funcionó y pensé que a pesar de que una historia de bugs no resulta muy emocionante merecía la pena comentarlo en un artículo).  Publicaré en breve alguna solución que incluiré como parte de un paquete de utilidades. De momento solo tengo un parche poco presentable.


Conclusiones:
Es muy posible que ImageMagick bajo ciertas circunstancias cometa algún error en el mantenimiento de la información exif, y puede que la inconsistencia en los campos exif no sea algo tan raro, incluso podría considerarse como algo asumible porque donde tiene realmente sentido es en un fichero recién salido de una cámara de fotos.
También es muy posible que recordmydesktop genere un vídeo ogg con metainformación errónea o inconsistente y sería un bug independiente del anterior. En cualquier caso el hecho de que la información exif pueda provocar fallos en ffmpeg como mencoder, significa que ambos hacen un uso muy cuestionable de esta información, que debería ser ignorada. Sí estas se suprimen el vídeo se genera perfectamente. No tiene mucho sentido.
No descarto que todos estos programas que estoy mencionando estén haciendo cosas incorrectas y que sólo den problemas cuando se hace un determinado uso combinado de los mismos. Estaríamos ante una epidemia de bugs.

Que ffmpeg y mencoder compartan un mismo bug en la adquisición de imágenes jpeg no sería demasiado sorprendente ya que ambos son software libre y cabe la posibilidad de que uno copiara el bug del vecino.

Calidad vs compresión de tamaño en imágenes.

Tener claridad de ideas sobre como afecta la compresión de una imagen a su calidad es algo que nos puede ayudar a tomar las decisiones más adecuadas en muy diversas circunstancias.

No soy partidario de aburrir con un montón de argumentos técnicos, porque seguramente eso solo sirve al que tiene posibilidades de resolver ese tipo de problemas por sí mismo. A mí me gusta enfocar las cosas desde un enfoque práctico y con ejemplos que estimulen la comprensión.

droid100

Antiguo logo de Ciberdroide Informática

Para ilustrar el primer ejemplo usaré el antiguo logotipo de Ciberdroide. (Antes era Ciberdroide Informática y era una tienda virtual. De eso hace ya algunos años). La imagen que pongo es una versión reducida del fichero original. Un fichero en formato tiff, con una imagen de 9350×2280 sin compresión. No la he subido porque ocupa 5,1Mb.

La imagen tiff de 5,1 MBytes tiene una calidad perfecta, pero ocupa mucho. Si la pasamos a jpeg con una calidad del 85% y usando un gran aumento podría llegar a apreciarse una ligera pérdida de calidad, pero tendrás un fichero con un tamaño que será la dieciseisava parte del original. Si pasamos una imagen tiff como la nuestra de 5,1Mbytes a jpeg con una calidad del 95%, se quedará en 2,2MBytes. Es decir en algo menos de la mitad. La calidad final con esta compresión rozaría la perfección, y es la que puede apreciarse en la parte izquierda de la última imagen de la serie que viene a continuación.


cabeza_droid05

Jpeg Calidad 05%

cabeza_droid15

Jpeg Calidad 15%

cabeza_droid25

Jpeg Calidad 25%

Calidad 35%

Jpeg Calidad 35%

Calidad 45%

Jpeg Calidad 45%

Calidad 55%

Jpeg Calidad 55%

cabeza_droid65

Jpeg Calidad 65%

Calidad 75%

Jpeg Calidad 75%

Calidad 85%

Jpeg Calidad 85%

Calidad 95%

Jpeg Calidad 95%



isbn_1

isbn_2



La compresión jpeg en imágenes pequeñas funciona ligeramente peor que en las grandes y podemos ver que la última imagen de la derecha de esa serie que termina con calidad del 95% es algo inferior a la de la parte izquierda. Explicaremos la razón de esto.

Lo que he hecho es tomar un trozo de 482×464 pixels de la imagen original con el detalle de la cabeza del ciberdroide. Con el programa convert lo he pasado a formato jpeg con distintos niveles de compresión.

Ya hemos mencionado muchas veces la utilidad convert de ImageMagick, podemos usarla para pasar de un formato de imagen cualquiera, a otro, y para muchas más cosas.

Para pasar de formato tiff a jpeg con calidad del 75% podemos usar el comando siguiente:

convert -quality 75 imagen.tiff imagen.jpg

Sin embargo, para nuestro ejemplo, puesto que partimos de una imagen más grande,  hay dos formas de hacer esto, y el resultado no es el mismo:

  1. 1) Podemos comprimir primero la gran imagen tiff de 9350×2280 pixels, pasándola a jpeg con los mismos pixels pero comprimida, y luego recortarla a 482×464 pixels.

  2. 2) Primero recortamos la imagen tiff de 9350×2280 pixels a 482×464 pixels y luego pasamos a jpeg comprimiendo.

Vemos que el resultado no es el mismo. Esto se aprecia mejor pinchando en las primeras imágenes (calidad de 15%).

En las últimas (calidad del 95%) también se puede apreciar si se usa una visualización con suficiente aumento.

En las imágenes dobles que muestro vemos que la parte izquierda tiene siempre un poco más de calidad, y está realizada con el procedimiento primero, mientras que la parte derecha se uso el procedimiento segundo. Es decir el procedimiento primero actúa comprimiendo sobre la imagen grande, y el segundo actúa comprimiendo sobre una porción pequeña.

La mala fama del JPEG se debe sobre todo a malas experiencias con un montón de programas que producen por defecto salida JPEG con una calidad baja, pero Gimp pregunta siempre que calidad quieres usar. Un jpeg con una calidad del 95% tiene una calidad muy buena.

El sistema de resolver el problema de la compresión, se llama algorítmo de compresión, y en el caso del jpeg implica pérdida de calidad. Esto ocurre porque al comprimir el fichero se pierde algo de la información original, y la imagen perderá calidad apareciendo un efecto ruido.

Hay otros algoritmos de compresión que conservan toda la calidad porque no se produce pérdida de información. Por ejemplo el formato gif usa un sistema de compresión que no es adecuado ni para fotos ni para imágenes donde los tonos de los pixels sufran gradientes o degradados.

El algoritmo de compresión para ficheros gif funciona bien en imágenes de dibujos con colores planos, tipo logotipos, etc. Eso es así porque lo que viene a hacer el algoritmo gif es ahorrar espacio de almacenamiento cuando descubre en horizontal varios píxels con idéntico color. Anota los valores de color del pixel indicando las veces que se repetirá en sentido horizontal y así ahorra espacio en el fichero.

Para demostrar esto hemos tomado una imgjen gif de un código de barras y la hemos girado 90 grados. El resultado es que mientras la primera imagen ocupa 92Kbytes la segunda, simplemente por haberla girado, ocupará 36Kbytes.

Los trazos finos horizontales se comprimen en gif mejor que los verticales.

Para solventar las carencias del formato gif se diseñó un nuevo formato que a diferencia del formato gif no está sujeto a patentes. Se trata del formato png. Usa al igual que gif un tipo de compresión sin pérdidas, es algo más sofisticado que el gif. Su implementación en los navegadores no está tan extendida como el formato gif o el jpeg.

Al igual que gif su uso es recomendable para comprimir imágenes con grandes áreas con colores planos.

Glosario de términos que puede consultar en la wikipedia:

Funciona con WordPress & Tema de Anders Norén