⚠️ Este es un sitio de traducción no oficial, sin relación con ImageMagick Studio LLC. Para información autorizada, consulte la página original (https://usage.imagemagick.org/quantize/index.html).

Ejemplos de ImageMagick -- Cuantización de color y tramado

Ejemplos de ImageMagick: prefacio e índice
Introducción a la reducción de color (en qué consiste)
Los colores de una imagen (qué colores usa una imagen)

Reducir el número de colores o sustituir colores concretos es un paso muy complejo y difícil del procesamiento de imágenes, y ese es el tema que cubren estas páginas de ejemplos. Esto incluye decidir qué colores usar (cuantización de color) y cómo colocar esos colores en la imagen (tramado y creación de patrones). También incluye la generación de imágenes de mapa de bits o de dos colores, e incluso el manejo de la transparencia booleana (activada/desactivada). Esto es tan importante que la reducción o cuantización de color suele realizarse de forma automática y entre bastidores, precisamente para que ImageMagick pueda llevar a cabo su tarea principal original: convertir imágenes de un formato de archivo a otro con menos colores, como los formatos GIF, XPixmap y XBitmap. Conocer cómo funciona esto te permite controlar mejor el proceso, de modo que puedas mejorar la imagen resultante guardada en un formato de archivo concreto.


Introducción a la reducción de color

La reducción de color es un aspecto muy importante de ImageMagick. Por ejemplo, para convertir una imagen JPEG o PNG que contiene millones de colores en una imagen GIF con un máximo de 256 colores, hay que ser realmente capaz de reducir los colores de forma eficiente y eficaz. A menudo, durante una conversión de formato, esto ocurre de forma automática entre bastidores, pero otras veces conviene hacerlo manualmente. Reducir el número de colores de una imagen suele ser un proceso de tres pasos:

  1. Primero, normalmente hay que examinar los colores que usa una imagen. No solo para ver cuántos colores se usan en realidad, sino con qué frecuencia se usa cada color. No tiene sentido conservar un color concreto si solo un único píxel lo usa, aunque a veces aun así haya que hacerlo.
  2. Después hay que decidir de algún modo el conjunto final de colores al que quieres limitar la imagen. Puede que quieras que IM intente determinar el conjunto «óptimo» de colores para una imagen concreta. Otras veces querrás algo más general y global que pueda aplicarse a cualquier imagen. Incluso puede que quieras añadir o quitar de forma explícita un color del conjunto de colores que se va a usar.
  3. Y por último hay que modificar la imagen para que solo use los colores que has seleccionado. Lo ideal es que el resultado se vea bien, o quizá que se comprima, se compare o se optimice bien.

Para complicar aún más las cosas, estos pasos suelen estar interrelacionados, ya que un método de sustitución de colores a menudo solo puede aplicarse con conjuntos de colores concretos. Y si usas un conjunto de colores concreto, no hace falta hacer ningún tipo de examen de colores, o quizá necesites hacer excepciones para ciertos colores. En resumen, aunque la reducción de color suele gestionarse de forma automática entre bastidores, conviene al menos ser consciente de qué está ocurriendo y de cuáles serán sus efectos.

Examen de colores

Este es probablemente el menos importante y, aunque IM ofrece métodos para hacer un examen, los usuarios rara vez lo hacen con fines de reducción de color. Dejaré el resto de la explicación para la sección correspondiente, Extraer los colores de una imagen.

Selección de color (cuantización)

Para una buena visión general inicial, consulta Wikipedia, Cuantización de color. Hay cuatro métodos básicos para seleccionar colores. Estos cuatro métodos de control del color —Cuantización, Mapa de color predefinido, Colores uniformes y Umbral— tienen todos sus limitaciones, como verás. Aquí tienes un ejemplo de cada uno de estos cuatro métodos...

  magick colorwheel.png +dither    -colors 32          color_quantize.gif
  magick colorwheel.png +dither -remap colortable.gif  color_predefined.gif
  magick colorwheel.png +dither   -posterize 3         color_uniform.gif
  magick colorwheel.png \
                  -separate -threshold 50% -combine     color_threshold.gif

[IM Output] [IM Output] [IM Output] [IM Output] [IM Output]

El número de colores de cada una de las imágenes finales es solo un conjunto representativo, pero de aproximadamente 32 colores en cada caso (salvo el de umbral, que solo tiene 8). A partir de esto puedes hacerte una idea de qué esperar de cada uno. Todos los demás métodos tienen un conjunto fijo de colores (según el argumento del operador), independientemente de la imagen cuyos colores se reducen. Solo el primer método («[-colors](https://imagemagick.org/command-line-options/#colors)») elige realmente los colores en función del contenido de la imagen actual. Como la imagen de prueba es predominantemente blanca, se selecciona una gran cantidad de colores claros. Examina los colores de una imagen mediante una técnica conocida como «subdivisión espacial adaptativa» con árboles octales (oct-trees). Después intenta elegir un conjunto concreto de colores que se ajuste lo mejor posible a una imagen determinada, dentro de los límites indicados. Consulta más abajo el operador de cuantización de color. «[-remap](https://imagemagick.org/command-line-options/#remap)» permite dar a IM tu propio conjunto de colores predefinidos (consulta Mapas de color definidos por el usuario). El mapa de color «[colortable.gif](../static/img/images/colortable.gif)» usado arriba es un conjunto de 32 colores elegidos específicamente para una antigua biblioteca de iconos de X Window y está pensado para iconos de estilo caricaturesco. (Consulta AIcon Library, selección de colores de iconos de X para más detalles). Con «[-posterize](https://imagemagick.org/command-line-options/#posterize)» también se puede dividir matemáticamente cada canal de color en un conjunto de niveles o intensidades de color, produciendo un «mapa de color uniforme». Es decir, un mapa de color con cada canal fijado a un conjunto constante de valores o intensidades. Y por último, se puede aplicar «[-threshold](https://imagemagick.org/command-line-options/#threshold)» a todos los canales de color de la imagen o a canales concretos, haciendo que cada canal de color sea esencialmente booleano (activado/desactivado). Es decir, a cada canal de color se le puede dar un valor de cero o de MaxRGB (según el nivel «Q» de IM). Sin embargo, esto solo produce un conjunto mínimo de unos 8 colores. Un conjunto de colores muy limitado. El umbral también equivale a un nivel «1» de «[-posterize](https://imagemagick.org/command-line-options/#posterize)», que elige 2 colores.

Aplicar un conjunto de colores

Una vez que tienes un conjunto de colores, el siguiente problema es aplicar el color a una imagen de modo que los colores existentes se sustituyan por el conjunto de colores seleccionado. Esto se conoce como «tramado» (dithering), y recibe ese nombre por su naturaleza de disyuntiva: «¿elijo este o elijo aquel?». En esencia, la idea del tramado es colocar píxeles de distintos colores cerca unos de otros de tal forma que engañen al ojo para que perciba en la imagen más colores de los que realmente se usan. Es decir, el color de esa zona de la imagen se aproxima más al color original, por la forma en que el ojo humano «mezcla» los colores vecinos. Una de las mejores introducciones al tramado está en Wikipedia, aunque tendrás que saltarte la sección «Audio Dithering» del principio. Presenta un excelente conjunto de ejemplos de las ventajas de usar un patrón de píxeles tramado cuando se dispone de un conjunto limitado de colores. Los estilos básicos de sustitución de color incluyen...

  • Asignación directa de color (umbral y posterización)
  • Tramado aleatorio (colocación de píxeles puramente aleatoria)
  • Tramados por corrección de error (patrones de píxeles pseudoaleatorios)
  • Tramado ordenado de píxeles difundidos (patrones regulares de píxeles)
  • Semitono digital (puntos de distintos tamaños)

La asignación directa al color más cercano de un conjunto dado es lo que se mostró arriba. En esencia, obtienes zonas bien diferenciadas de colores sólidos e invariables. Cuando esto se aplica a una imagen de color que varía suavemente, como una foto real del cielo, obtienes bandas de color a lo largo de la imagen, sobre todo en lo que de otro modo sería un degradado de colores suave, como las zonas de cielo. Por lo general, el resultado no se considera muy bueno. La asignación directa de color solo suele considerarse aceptable para logotipos, símbolos, iconos e imágenes de estilo caricaturesco. En realidad rara vez es una opción. Por eso, normalmente hay que desactivar el método de tramado habitual si no quieres asignar los colores de forma directa en tus imágenes. El tramado, sin embargo, tiene su propio problema. Una vez que se trama una imagen, un patrón de colores pasa a formar parte de ella. Una vez presente, ese patrón es extremadamente difícil de eliminar. Además, por lo general es mala idea volver a aplicar el tramado a una imagen varias veces, ya que eso solo la degrada. Por ello, la mayoría de los ejemplos de cuantización de más abajo te mostrarán cómo crear versiones sin tramado de cada técnica. Se hace así para que puedas ver qué selecciones de color se realizan antes de que el tramado oculte esa información. El tramado aleatorio es el método de tramado más sencillo que se ha creado. También se considera el peor método de tramado posible. Aun así, tiene algunos usos especiales. Dentro de IM solo funciona con dos colores, por lo que normalmente se restringe al caso especial del tramado de mapas de bits. Para más información, consulta Tramado aleatorio con umbral más abajo. El tramado por corrección de error suele considerarse el mejor método general para tramar colores en las imágenes, ya que produce la aproximación más fiel al color original de las zonas de la imagen. Además, actualmente es el único método capaz de tramar cualquier conjunto de colores y, por tanto, puede usarse para las cuatro técnicas de reducción de color. Consulta Cómo funcionan los E-Dither más abajo para más detalles. Sin embargo, el tramado por corrección de error tiene algunos problemas serios, sobre todo en lo relativo a las animaciones de imágenes. Las dos últimas técnicas de tramado, píxeles difundidos ordenados y semitono digital, también se consideran un buen método que funciona bien para animaciones, pero actualmente no pueden usar cualquier conjunto de colores, solo un conjunto fijo de colores uniformes. Sí ofrecen un medio de colorear una imagen mediante patrones, lo que permite producir efectos interesantes que de otro modo no son fáciles de conseguir.
Todos estos aspectos de la reducción de color son técnicas importantes y, si las entiendes, puedes mejorar los resultados de tus operaciones con imágenes más allá de los valores predeterminados generales que ofrece IM. Bien vale la pena estudiarlas.


Los colores de una imagen

La información sobre las imágenes, como el número de colores usados y su distribución general, puede ser muy importante para los programas y scripts que intentan decidir cuáles son las mejores técnicas a usar. Aquí veo algunos de los métodos que puedes usar para determinar este tipo de información, y no solo para la reducción de color.

Extraer los colores de una imagen

Extraer la tabla de colores

Para extraer una paleta de colores de una imagen se usa un «[identify](basics.html#identify)» detallado (verbose), con cualquiera de estos métodos, que básicamente hacen exactamente lo mismo.

  magick identify -verbose  image.png
  magick image.png miff:- | identify -verbose -
  magick image.png  -verbose -identify null:
  magick image.png  -verbose info:

| La salida de cualquiera de las identificaciones detalladas anteriores no devolverá las tablas de color ni el histograma si hay más de 1024 colores. Por eso, para imágenes grandes y con muchos colores esto es una cuestión de suerte y no se recomienda, aunque aún puede ser útil.
---|---
Sin embargo, la mejor manera es generar un «[histogram:](files.html#histogram)» de la imagen y extraer el comentario que se incluye en el resultado. | |

  magick tree.gif  -format %c  -depth 8  histogram:info:-

[IM Output]
| [IM Text]


| El formato de salida «info:» se añadió en IM v6.2.4. Para versiones de IM anteriores, usa... |

  magick tree.gif histogram:- | identify -depth 8 -format %c -

El problema de estos métodos es que obtienes una salida de los colores en texto plano, que tendrás que analizar según tus necesidades. Sin embargo, a partir de IM v6.2.8-8, el operador «[-unique-colors](https://imagemagick.org/command-line-options/#unique-colors)» convierte una imagen en otra más pequeña que contiene un solo píxel por cada color único encontrado en la imagen original, todos en una única fila. Esto significa que puedes convertir una imagen en una imagen de tabla de colores más sencilla, que enumera cada color presente. El ancho de la imagen indica el número de colores y, si necesitas listar realmente los colores, puedes generar la salida en formato de imagen «[txt:](files.html#txt)». Por ejemplo, esta es la tabla de colores de la imagen del árbol. |

  magick tree.gif -unique-colors -scale 1000%  tree_colors.gif
  magick tree.gif -unique-colors -depth 16  txt:-

[IM Output]

[IM Text]

Esta tabla de colores reducida también es muy importante como forma de almacenar en un archivo muy pequeño un mapa de los colores generados. Estos mapas son especialmente importantes para el operador de reducción de color «[-remap](https://imagemagick.org/command-line-options/#remap)». (Consulta Mapas de color predefinidos más abajo). Si quieres obtener una imagen que contenga no solo los colores de una imagen, sino también sus recuentos, aquí tienes una solución de histograma de color desarrollada a partir de una discusión en el foro de IM.

  magick rose: -colors 256 -format %c histogram:info:- |
    sed 's/:.*#/ #/' |
      while read count color colorname; do
        magick -size 1x$count xc:$color miff:-
      done |
        magick - -alpha set -gravity south -background none +append \
                unique_color_histogram.png

[IM Output] [IM Output]

Ten en cuenta que tuve que reducir el color de la imagen, ya que la imagen integrada «rose:» contiene 3020 colores únicos, lo que tardaría mucho y generaría una imagen muy larga. La imagen GIF de la rosa mostrada arriba contiene la misma reducción de color. La imagen resultante sigue teniendo el mismo número de píxeles, aunque rellenada con píxeles transparentes adicionales y, como puedes ver, muestra un predominio de grises verdosos, rojos intensos, así como un pico muy marcado de blanco puro. Puede que este no sea el mejor método general de histograma de color, pero funciona bien para esta imagen. El orden de los colores, tanto para «[histogram:](files.html#histogram)» como para el operador «[-unique-colors](https://imagemagick.org/command-line-options/#unique-colors)», no está definido, pero parece ordenarse por el valor del canal rojo, luego el verde y por último el azul. Puede que no sea la mejor forma para una imagen concreta, pero es imposible ordenar de forma general colores tridimensionales en un orden unidimensional.

Extraer el color medio

El color medio de una imagen se puede hallar muy rápido usando «[-scale](https://imagemagick.org/command-line-options/#scale)» para reducir una imagen a un solo píxel. Por ejemplo, este es el color medio de la imagen integrada «rose:». Genero la salida del color con el formato de escape FX, que devuelve una cadena de color que puede usarse directamente en IM sin cambios.

  magick rose: -scale 1x1\! -format '%[pixel:s]' info:-

[IM Text]

El problema de usar el escape FX «%[pixel:...]» es que puede devolver un nombre de color como «white» o «silver» en lugar de un valor RGB. Sin embargo, puedes simularlo usando tres escapes FX para devolver los valores RGB reales en la profundidad de bits deseada. Por ejemplo...

  magick rose: -scale 1x1\! \
     -format '%[fx:int(255*r+.5)],%[fx:int(255*g+.5)],%[fx:int(255*b+.5)]' info:-

[IM Text]

A partir de IM v6.3.9 hay varios escapes nuevos de «[-format](https://imagemagick.org/command-line-options/#format)» que pueden ser útiles para extraer información más específica sobre las imágenes sin necesidad de analizar una salida detallada de «[identify](basics.html#identify)» o «[info:](files.html#info)». Por ejemplo, puedes obtener el color medio del canal rojo tomando el valor de gris «%[mean]» de la imagen del canal rojo.

  magick rose: -channel R -separate -format '%[mean]' info:

[IM Text]

Extraer un color concreto

Desde la línea de comandos hay dos formas básicas de extraer el color de un píxel concreto de una imagen. Una es usar un escape FX como «%[pixel:...]» o «%[fx:...]» (ver arriba) en una posición de píxel concreta...

  magick rose: -format '%[pixel:p{40,30}]' info:-

[IM Text]

Otra opción es simplificar la imagen usando «[-crop](https://imagemagick.org/command-line-options/#crop)» para recortar un único píxel que te interese y usar cualquiera de los métodos anteriores. Por ejemplo...

  magick rose: -crop 1x1+40+30 -depth 8 txt:-

[IM Text]

Recuento de un color concreto (o cercano)

Esto puede usarse para obtener el recuento de píxeles o el porcentaje de un color concreto. Lo que haces es poner en negro todo lo que no sea ese color y luego poner en blanco ese color. Por ejemplo, obtengamos el número de píxeles del sol «yellow» en la imagen del árbol («tree»).

  magick tree.gif -fill black +opaque yellow \
                   -fill white -opaque yellow \
                   -print "yellow sun pixels = %[fx:w*h*mean]\n"   null:

[IM Text]

Hay una salvedad: no funcionará si el color que se examina es el propio negro. Para tratar el negro (o colores muy oscuros), invierte los rellenos para asignar el blanco a los colores no negros y luego niega el resultado para generar la máscara blanca de todos los píxeles negros. Recuerda que la opción «[-print](https://imagemagick.org/command-line-options/#print)» equivale a usar «-format ... -write info:» y puede emplearse en cualquier punto del procesamiento de la imagen. Después descarté la imagen no deseada usando el formato de archivo especial «[null:](files.html#null)». También puedes guardar la imagen para usarla como máscara en trabajos posteriores. Ten en cuenta que, aunque esto funciona bien con imágenes pequeñas, con imágenes mucho más grandes (como fotos digitales de alta resolución) la «media» no será lo bastante precisa para obtener un recuento exacto de píxeles. En esencia, el uso anterior de la «media» sirve para generar una proporción, pero no para recuentos exactos de píxeles. Para obtener un recuento exacto es mejor usar una salida de «comentario» del histograma, que tiene recuentos exactos de píxeles (ver arriba). En lo anterior también se puede usar la opción de factor de tolerancia «[-fuzz](https://imagemagick.org/command-line-options/#fuzz)» antes del operador «[-opaque](https://imagemagick.org/command-line-options/#opaque)» para especificar también colores «cercanos».

Comparar dos colores

Así que tienes dos colores concretos y quieres compararlos. Puedes usar «magick compare » para obtener el RMSE (error estándar)...

  magick compare -metric RMSE xc:Navy xc:blue null:

[IM Text]

Esto está bien porque te da la distancia entre los dos colores, tanto en términos de valores como en forma de porcentaje normalizado de la distancia del negro al blanco. Sin embargo, este método no maneja correctamente la transparencia. Por ejemplo, al comparar «negro totalmente transparente» con «blanco totalmente transparente».

  magick compare -metric RMSE xc:'#0000' xc:'#FFF0' null:

[IM Text]

En realidad, los colores transparentes deberían tener una distancia nula, ya que lo totalmente transparente es igual con independencia del color subyacente. En cambio, obtuvimos una distancia de hipercubo en 4 dimensiones). Por eso, el método de distancia de color anterior solo sirve para comparar colores totalmente opacos.
En lugar de obtener una distancia real, también puedes usar un factor de tolerancia para comprobar si dos colores son cercanos.

  magick compare -fuzz 20% -metric AE xc:Navy xc:Blue null:
  magick compare -fuzz 30% -metric AE xc:Navy xc:Blue null:

[IM Text]

Recuerda, no obstante, que el resultado será «1» si los píxeles no coinciden (número de píxeles erróneos). Para obtener la distancia real del factor «fuzz» que separa los valores, puedes usar la métrica «FUZZ».

  magick compare -metric FUZZ xc:Navy xc:Blue null:

[IM Text]

El valor «normalizado» muestra que la distancia real es del 28,7 %. Usar el factor de tolerancia es distinto de calcular el RMSE cuando interviene la transparencia. Esto se debe a que el factor de tolerancia está diseñado para que dos colores totalmente transparentes cualesquiera se traten como iguales. Por eso, «negro totalmente transparente» y «blanco totalmente transparente» son exactamente equivalentes (producen un valor de 0, es decir, ningún píxel erróneo)...

  magick compare -metric FUZZ xc:'#0000' xc:'#FFF0' null:

[IM Text]

Otro método de comparación de colores es intentar sustituir colores con un porcentaje de factor de tolerancia adecuado. Por ejemplo...

  magick xc:Navy  -fuzz 20% -fill Blue -opaque Blue txt:

[IM Text]

Como «Navy» no cambió a «Blue», difiere de «Blue» en más de un 20 %. Mientras que

  magick xc:Navy  -fuzz 30% -fill Blue -opaque Blue txt:

[IM Text]

Aquí sí cambió el color a «Blue», así que ahora sabemos que «Navy» está a una distancia de entre el 20 % y el 30 %. Para hacer esto en un script, usa algo como...

  fuzz=%1
  color1="red"
  color2="#e00"

  color2=`magick xc:"$color2" -format '%[pixel:s]' info:`
  result=`magick xc:"$color1" -alpha set -channel RGBA -fuzz $fuzz \
            -fill $color2 -opaque $color2 -format '%[pixel:s]' info:`
  if [ "$result" = "$color2" ]; then
    echo "Colors match according to Fuzz Factor"
  else
    echo "Colors DO NOT match"
  fi

Las opciones especiales «-alpha set -channel RGBA» son importantes para permitirnos la coincidencia aproximada (fuzzy) de colores transparentes y casi transparentes.


Cuantización de color

El operador de cuantización de color

El principal caballo de batalla de la cuantización de color, y lo que se usa internamente para toda la reducción de color automática, es el operador «[-colors](https://imagemagick.org/command-line-options/#colors)». Este implementa un algoritmo de reducción de color de «subdivisión espacial adaptativa» y es un algoritmo de reducción de color extremadamente bueno. Aquí tienes un ejemplo típico: tengo una imagen de una «rueda de color» (colorwheel) que contiene muchos colores y le pedimos a IM que reduzca el número de colores a solo 64, usando varios métodos de tramado.

  magick colorwheel.png  -dither None       -colors 64  colors_64_no.gif
  magick colorwheel.png  -dither Riemersma  -colors 64  colors_64_rm.gif
  magick colorwheel.png  -dither FloydSteinberg \
                                             -colors 64  colors_64_fs.gif

[IM Output] [IM Output] [IM Output] [IM Output]

IM usa por defecto un «tramado» para difuminar los colores por toda la imagen. Esto evita los cambios bruscos de color en degradados que varían suavemente. Si desactivas el tramado (con «None» o un ajuste «[+dither](https://imagemagick.org/command-line-options/#dither)») puedes ver claramente qué colores se fusionaron para generar lo que IM consideró el mejor conjunto de colores para esta imagen concreta. También puedes ver los cambios bruscos de color que producirían los degradados si no se hiciera el tramado. Por supuesto, esta imagen usa muchos más colores de los que usan la mayoría de las imágenes. Por eso, aunque un límite de 64 colores suele ser aceptable para muchas imágenes, resulta del todo inaceptable para esta. En otras palabras, la cuantización de color intenta encontrar el mejor conjunto de colores para una imagen concreta. Aquí tienes un ejemplo de cuantización de color de una parte del logotipo de IM, usando un número de colores extremadamente reducido.

  magick logo: -resize 40% -crop 100x100+105+50\! -normalize  logo.png
  magick logo.png  +dither             -colors 8  colors_8_no.gif
  magick logo.png  -dither Riemersma   -colors 8  colors_8_rm.gif
  magick logo.png  -dither FloydSteinberg \
                                        -colors 8  colors_8_fs.gif

[IM Output] [IM Output] [IM Output] [IM Output]

Compara eso con algunos resultados de la imagen fotográfica integrada «rose:».

  magick rose: +dither             -colors 16 colors_16_no.gif
  magick rose: -dither Riemersma   -colors 16 colors_16_rm.gif
  magick rose: -dither FloydSteinberg \
                                     -colors 16 colors_16_fs.gif

[IM Output] [IM Output] [IM Output] [IM Output]

Como puedes ver, las imágenes de estilo caricaturesco requieren muchos menos colores que una fotografía real para producir un resultado razonable. | _Actualmente solo hay implementado en IM un algoritmo de cuantización de color, la «subdivisión espacial adaptativa» y, como funciona muy bien, ha habido poca necesidad de añadir otros. No obstante, con las aportaciones recibidas, este algoritmo se mejora de forma continua.

ASIDE: A modo de referencia, el programa «[Gifsicle](http://www.lcdf.org/gifsicle/)» enumera otros métodos de cuantización de color (mediante su opción «--color-method»). No tengo ni idea de cómo se comparan estos métodos de cuantización de color con los de IM. Si encuentras una buena referencia sobre los distintos métodos de cuantización de color, escríbeme._
---|---

Interioridades de la cuantización de color

El proceso de seleccionar el número limitado de colores que se usarán en una imagen se denomina cuantización de color, y es un proceso muy complejo en el que intervienen varios factores. En el sitio web de ImageMagick se ofrece una descripción técnica completa: Algoritmo de reducción de color. No obstante, intentaré explicar aquí algunos de sus aspectos más importantes. Probablemente el factor más determinante sean los colores reales que se usan en una imagen. No tiene sentido elegir un color concreto para una imagen si hay muy pocos píxeles «cercanos» a ese color. Por eso, la elección del color no depende solo de los colores usados en una imagen, sino también del número de píxeles «cercanos» al color. Puedo demostrarlo con bastante facilidad intentando reducir dos imágenes distintas de dos colores a un único color común.

  magick -size 4x1 xc:blue -draw 'fill red   point 0,0' \
                                                -scale 20 colors_rb.gif
  magick -size 4x1 xc:red   -draw 'fill blue point 3,0' \
                                                -scale 20 colors_br.gif
  magick colors_rb.gif  -colors 1  colors_rb2.gif
  magick colors_br.gif  -colors 1  colors_br2.gif

[IM Output] [IM Output]
[IM Output] [IM Output]

Como puedes ver, el único color final depende no solo de los colores presentes, sino también de la cantidad de cada color en la imagen.

  magick -size 20x640  gradient: -rotate 90  gradient.png
  magick gradient.png   +dither  -colors 5   colors_gradient.gif

[IM Output]

Ten en cuenta que la cuantización de color es uniforme dentro del espacio de color actual.

FUTURE: ¿Cuáles son exactamente los efectos del ajuste "[-treedepth](https://imagemagick.org/command-line-options/#treedepth)"?
Escríbeme si lo sabes

Cuantización de color y espacio de color

La otra gran influencia sobre qué colores se seleccionan es definir exactamente qué entendemos por colores «cercanos» o «próximos». Esto lo define el espacio de color usado para la cuantización (selección de color) y se controla (desde IM v6.2.8-6) con el ajuste de espacio de color «[-quantize](https://imagemagick.org/command-line-options/#quantize)». El ajuste «[-quantize](https://imagemagick.org/command-line-options/#quantize)» cobra especial importancia cuando se elige un número muy reducido de colores. Para demostrarlo, reduzcamos una imagen estándar de «rueda de color» usando varios espacios de color distintos y definiendo distintas «distancias de color».

  for S in    RGB CMY sRGB GRAY \
              XYZ LAB LUV  \
              HSL HSB HWB  \
              YIQ YUV OHTA ; do \
     magick colorwheel.png   -quantize $S   +dither -colors 16 \
             -fill black -gravity SouthWest -annotate +2+2 $S \
             colors_space_$S.gif; \
  done

[IM Output] [IM Output] [IM Output] [IM Output]
[IM Output] [IM Output] [IM Output]
[IM Output] [IM Output] [IM Output]
[IM Output] [IM Output] [IM Output]

Como puedes ver, los colores elegidos dependen en gran medida de cómo está organizado el espacio de color. El cubo de color sRGB (rojo, verde, azul) por lo general hará que se elijan al menos los colores cercanos al color primario. El espacio de color sRGB es especialmente bueno eligiendo colores para imágenes de estilo caricaturesco e iconos, pero en realidad es un mal espacio de color para fotos de aspecto realista. El espacio de color CMY es exactamente igual que el sRGB, ya que los canales de color simplemente se niegan para convertir entre los espacios sRGB y CMY. Por eso, los colores de la cuantización acaban con prácticamente la misma solución. | _El espacio de color CMYK (no mostrado) también produce lo mismo, pero por razones distintas. Como internamente el canal «K» y el «mapa de color» de una imagen usan el mismo puntero de datos (consulta Canal de paleta), IM lo convierte de nuevo a CMY antes de la cuantización.


---|---
El espacio de color sRGB, como cabía esperar, produce un resultado similar al RGB, pero está deformado para reducir el número de colores casi negros del espacio de color. Por eso hay menos colores para elegir en el centro de la rueda de color, lo que produce una mancha «no del todo negra» más grande. El espacio de color XYZ también es muy muy similar al espacio RGB lineal. La gran diferencia aquí es que el eje de color se ha desplazado para contener mejor TODOS los colores posibles que podemos ver (e incluso colores que normalmente no podemos), de modo que los datos de color de la rueda de color quedan algo más comprimidos y, como resultado, las cuantizaciones parecen quedar más dispersas. Los espacios de color LAB y LUV se basan en ejes de color distintos pero similares entre sí. Eso da lugar a una disposición distinta de las cuantizaciones de color. Los espacios de color especiales que incluyen un canal de «matiz» (Hue), como HSL (matiz, saturación, luminosidad), HSB (matiz, saturación, brillo) y HWB (matiz, blanco, negro), tienen todos una representación cíclica del color en forma de rueda como parte de su espacio de color. De hecho, esta rueda de color se generó usando precisamente un espacio de color HSL. Consulta Generar una rueda de color. | _En el momento de escribir esto, el algoritmo de distancia de color que usa IM no tiene en cuenta la naturaleza cíclica del «matiz» del espacio de color. El algoritmo para esto es muy distinto. Por ello se produce una fuerte discontinuidad a lo largo de la trayectoria del «rojo», donde el «matiz» da la vuelta, lo que hace que se seleccionen muy pocos colores rojos en el proceso de cuantización de color.

---|---
Los espacios YIQ e YUV están diseñados para producir tonos de color más naturales, «pastel» y de «medio tono», mucho más adecuados para fotografías e imágenes del mundo real con matices sutiles de color, y especialmente para los tonos de piel. Helmut Dersch señala en su sitio web que conviene plantearse usar un espacio de color LAB para las distorsiones. | _En versiones antiguas de IM (concretamente IM versión 5) el espacio de color usado para la cuantización se fijaba con la opción «[-colorspace](https://imagemagick.org/command-line-options/#colorspace)». Sin embargo, en IM versión 6 este operador se usa para modificar cómo se almacenan las imágenes en memoria y, por tanto, no es un ajuste para la cuantización de color.

Por eso, en IM v6.2.8-6 se introdujo el ajuste «[-quantize](https://imagemagick.org/command-line-options/#quantize)» para hacer este trabajo. Sin embargo, solo es un ajuste para el proceso de cuantización de color de «[-colors](https://imagemagick.org/command-line-options/#colors)». No hace nada para la sustitución y el tramado de colores con operadores como «[-remap](https://imagemagick.org/command-line-options/#remap)» y «[-posterize](https://imagemagick.org/command-line-options/#posterize)», ni para las distintas técnicas de tramado._
---|---
Para ver una lista completa de los espacios de color disponibles, consulta el operador «[-colorspace](https://imagemagick.org/command-line-options/#colorspace)». Puedes ver más efectos del espacio de color sobre la selección de colores en los ejemplos de Manchas aleatorias de color sólido. Allí se usa la cuantización de color para reducir el número de colores de una imagen aleatorizada con varios espacios de color. La cuantización NO conserva los colores. Observa que en todas las imágenes anteriores la cuantización de color nunca elige realmente un color negro puro. Eso sí, en cualquier caso solo hay un píxel negro puro, y no muchos colores casi negros en la imagen. Como resultado, el único negro que aparece en la imagen final se añadió después como parte del etiquetado de la imagen. Ni siquiera la imagen del espacio de color «GRAY» produjo un negro puro. De hecho, ninguna de las imágenes contiene ninguno de los colores primarios o secundarios, como rojo, azul, verde, cian o magenta. La única excepción es el blanco, ya que las imágenes sí contenían bastante blanco puro, lo que lo convierte en un «color preferido» (ver más abajo). Sin embargo, esta situación no es un error. En primer lugar, por lo general no se seleccionó un color «black» en los ejemplos anteriores, normalmente porque hay muy poco negro en la imagen original, así que la cuantización de color no se preocupó demasiado por los colores oscuros. De hecho, generó más colores claros, ya que son más comunes en la imagen. Consulta la sección anterior para ver un ejemplo concreto. En segundo lugar, como la cuantización intenta elegir colores cercanos al máximo número de píxeles de color existentes en una imagen, esto se consigue mejor NO eligiendo un color primario o secundario «puro», ya que estos están siempre en los extremos del espacio de color utilizado. Un color «desviado» tiende a coincidir con más colores que un color «primario», por lo que se seleccionan con más frecuencia. Así que dejémoslo claro... La cuantización de color (" -colors") por lo general evitará elegir colores primarios.

A partir de IM versión 6.3 se modificó la función de cuantización de color para intentar incluir los colores que son muy comunes en la imagen original. Por eso, si una imagen contiene una zona de un único color (como el «white» del ejemplo anterior), ese color se incluirá por lo general en el mapa de color final. Esto mejora algo la situación, sobre todo en imágenes de estilo «caricatura» o imágenes sobre un fondo de color sólido. El color «sólido» se elige por lo general para ayudar a evitar el moteado de tramado que veremos más abajo. Soluciones para incluir un color concreto en el mapa de color. Por el momento solo hay unas pocas formas de garantizar que un «color concreto» se incluya en los colores seleccionados para el tramado posterior. Una forma es cuantizar la imagen de forma normal, pero después generar el mapa de color resultante (con «[-unique-colors](https://imagemagick.org/command-line-options/#unique-colors)»). Ahora puedes ajustar ese mapa de color para que tu color concreto sea realmente ese color. Por último, puedes usar el operador Remapear colores para tramar la imagen con el mapa de color proporcionado. Puede que el mapa de color ya no sea el MEJOR para la imagen, y probablemente también haya que ajustar algunos otros colores, pero estará cerca del mapa de color que querías. Otra opción es añadir (ampliando la imagen) grandes parches de los colores concretos que quieres conservar en la imagen, antes de usar «[-colors](https://imagemagick.org/command-line-options/#colors)». La adición de la gran «muestra» de un color concreto hará que sea más probable que ese color se elija en el mapa de color final. Además, todos los demás colores se ajustarán entonces automáticamente para encajar mejor en ese mapa de color. Si funciona, las muestras de colores que añadiste deberían permanecer sin cambios (sin tramar). Después puedes recortar la imagen para eliminar las muestras añadidas. Si no funciona, IM debería haber añadido al menos un color cercano al «color concreto» deseado, de modo que solo haga falta un ligero ajuste del mapa de color generado antes de usar Remapear colores sobre la imagen original. Si lo pruebas, tanto si tienes éxito como si no, hazme saber cómo te fue. Lo ideal sería contar con una forma de especificar un pequeño número de colores concretos que deban formar parte del mapa de color final, y luego pedirle de algún modo a IM que elija los mejores colores para el resto de los colores del mapa, para una imagen concreta.

Cuantización de color y transparencia

ImageMagick, por defecto, no solo genera colores totalmente opacos, sino que también intenta generar colores semitransparentes. De este modo, las imágenes que contienen sombras transparentes u otros efectos superpuestos no pierden esos efectos. Sin embargo, a partir de IM v6.2.6 se modificó la cuantización de color que implica transparencia para tratar todos los colores totalmente transparentes como un mismo color. Es una modificación lineal, por lo que los colores que solo son semitransparentes también se consideran más cercanos entre sí de lo que estarían si fueran totalmente opacos. Por esta modificación, la cuantización de color de IM seguirá generando colores semitransparentes, pero se concentrará más en los colores opacos y menos en los colores totalmente transparentes de la imagen. Por ejemplo, aquí genero un degradado arcoíris de colores, con la imagen totalmente opaca arriba y totalmente transparente abajo. He mostrado las imágenes sobre un patrón de fondo para que puedas ver lo transparente que es la imagen.

  magick xc:red xc:yellow xc:green1 xc:cyan xc:blue \
          +append -filter Cubic -resize 100x100\!  -size 100x100 \
          gradient: -alpha off -compose CopyOpacity -composite alpha_gradient.png
  magick alpha_gradient.png  +dither  -colors 256  alpha_colors_256.png
  magick alpha_gradient.png  +dither  -colors 64   alpha_colors_64.png
  magick alpha_gradient.png  +dither  -colors 15   alpha_colors_15.png

[IM Output] [IM Output] [IM Output] [IM Output]

Como puedes ver, cuando le pedimos a IM que reduzca el número de colores necesarios para esta imagen, creó muchos más colores opacos y usó menos colores muy transparentes para las partes más translúcidas. El resultado es una muy buena distribución de los colores seleccionados, sobre todo cuando el número de colores es muy reducido. Sin embargo, tal como señalé antes, no solo no se eligen los colores primarios, sino que el color totalmente transparente tampoco se elige, exactamente por las mismas razones. De hecho, ¡ni siquiera se eligen colores totalmente opacos! En otras palabras, todos los colores de las imágenes cuantizadas del ejemplo anterior son semitransparentes. Deja que lo deje claro.

Cuando interviene la transparencia, la cuantización de color de IM
¡puede no seleccionar ningún color totalmente opaco ni siquiera totalmente transparente!

Por supuesto, a partir de IM v6.3 y con la corrección del error del «color común» (consulta La cuantización NO conserva los colores más arriba), eso es menos probable que ocurra si la imagen contiene muchos colores opacos y totalmente transparentes, que es lo habitual. Como algunas imágenes pueden contener muchos colores semitransparentes, como las que incluyen efectos de humo o sombras, quizá te convenga hacer una prueba para asegurarte de que se selecciona un color totalmente transparente para incluirlo en la imagen resultante. Luego puedes asignar el color más transparente a totalmente transparente y hacer tú mismo el Remapeo de colores. Si realmente quieres asegurarte de obtener en la imagen resultante tanto colores totalmente opacos como totalmente transparentes, puedes normalizar O ajustar el contraste del canal alfa. Por ejemplo, aquí me aseguro de que las principales selecciones de color sean opacas usando «[-contrast-stretch](https://imagemagick.org/command-line-options/#contrast-stretch)». Aunque esto probablemente sea un poco excesivo para una situación más normal.

  magick alpha_gradient.png  +dither  -colors 15 \
          -channel A -contrast-stretch 10%  alpha_colors_15n.png

[IM Output] [IM Output] [IM Output]

Esto NO es un problema para las imágenes GIF, que no admiten colores semitransparentes, ni para JPG, que no admite transparencia, ni siquiera para PNG, que no necesita cuantización para guardarse correctamente. Solo se convierte en un problema en casos especiales en los que fuerzas una reducción de color en una imagen con muchos colores semitransparentes. Recuerda que, para el formato GIF, guardar colores semitransparentes es un esfuerzo inútil. Por eso, si piensas hacer tú mismo la cuantización de color para un formato de imagen así, debes indicarle a IM que ignore la transparencia de la imagen al generar su conjunto reducido de colores. Puedes hacerlo usando el ajuste especial de espacio de color «[-quantize](https://imagemagick.org/command-line-options/#quantize)» con el valor «transparent».

  magick alpha_gradient.png -quantize transparent \
                            +dither  -colors 15   alpha_colors_15qt.png

[IM Output] [IM Output]

Observa cómo la cuantización de color ignoró por completo la transparencia de los colores y no tocó en absoluto el canal alfa de la imagen. Esto significa que puedes procesar el canal alfa de una forma más adecuada para tu imagen, totalmente al margen de los demás colores. De hecho, puedes hacerlo antes o después de usar «[-colors](https://imagemagick.org/command-line-options/#colors)» sin problemas. No habrá diferencia en el resultado. Por tanto, este espacio de color de cuantización es recomendable al reducir el número de colores de una imagen que pienses guardar en un formato con transparencia booleana o sin transparencia, como los formatos de imagen GIF o XPM. Si cuentas el número de colores generados, también verás que generó exactamente el número de colores solicitado. Por eso, si además necesitas un color totalmente transparente (probable), tienes que reducir el argumento de «[-colors](https://imagemagick.org/command-line-options/#colors)» en al menos uno, para dejar sitio en la tabla de colores final de la imagen. Así, para gestionar el límite de 256 colores de la tabla de colores del formato GIF, tendrás que reducir los colores a 255, y no a 256, dejando el hueco extra para el índice de color totalmente transparente, según lo define el ajuste «[-transparent-color](https://imagemagick.org/command-line-options/#tranparent-color)». Ajusta esto para tablas de color más pequeñas. Este comportamiento de cuantización es automático cuando IM guarda en formato GIF, pero es importante cuando necesitas hacer tú mismo la cuantización al generar tablas de color globales o compartidas. Por supuesto, sigues necesitando gestionar los píxeles semitransparentes para que sean correctos según el aspecto que quieras que tenga tu imagen.

FUTURE: Esta última parte probablemente se trasladará a una nueva sección sobre el
«tramado del canal alfa» que se creará en un futuro próximo. Y aquí se añadirá una
referencia a esa sección.

Aquí tienes algunos ejemplos de cómo tramar solo el canal alfa hasta un ajuste booleano (activado/desactivado), sin afectar al resto de los canales de color de la imagen.

  magick alpha_gradient.png \
          -channel A   -threshold 50%       alpha_dither_threshold.gif
  magick alpha_gradient.png \
          -channel A -ordered-dither checks alpha_dither_checks.gif
  magick alpha_gradient.png \
          -channel A -ordered-dither o8x8   alpha_dither_ordered.gif
  magick alpha_gradient.png \
          -channel A -ordered-dither h8x8a  alpha_dither_halftone.gif

  magick alpha_gradient.png -channel RGBA -separate \
          \( +clone -monochrome \) \
          +swap +delete -combine alpha_dither_monochrome.gif
  magick alpha_gradient.png -channel RGBA -separate \
          \( +clone -dither FloydSteinberg -monochrome \) \
          +swap +delete -combine alpha_dither_monochrome_fs.gif
  magick alpha_gradient.png -channel RGBA -separate \
          \( +clone -remap pattern:gray50 \) \
          +swap +delete -combine  alpha_dither_map.gif
  magick alpha_gradient.png -channel RGBA -separate \
          \( +clone -dither FloydSteinberg -remap pattern:gray50 \) \
          +swap +delete -combine  alpha_dither_map_fs.gif

[IM Output] [IM Output] [IM Output] [IM Output]
[IM Output] [IM Output] [IM Output] [IM Output]

| _Al tramar una copia del canal alfa para poder tramarlo con «[-monochrome](https://imagemagick.org/command-line-options/#monochrome)» o «[-remap](https://imagemagick.org/command-line-options/#remap)», asegúrate de que la imagen sea una imagen en escala de grises pura y no una máscara de forma con transparencia. Si no lo haces, probablemente acabes con efectos no lineales por la presencia del canal alfa.

Hay varias formas de extraer y restaurar el canal alfa de una imagen como máscara en escala de grises para poder tramarlo. Lo anterior usa la separación de canales y la combinación para hacerlo. Otros métodos usan la extracción de alfa con la composición CopyOpacity._
---|---


Tramado por corrección de error

Como se comentó en la introducción, un tramado por corrección de error suele considerarse la mejor opción para producir la representación más fiel de la imagen original con un conjunto reducido de colores. Además, se limita a cualquier paleta de colores predefinida, ya sea proporcionada por el usuario o determinada por las rutinas de cuantización de color de IM. Por ello, es la opción predeterminada lógica para la reducción de color general que ofrecen los operadores de IM «[-colors](https://imagemagick.org/command-line-options/#colors)», «[-remap](https://imagemagick.org/command-line-options/#remap)», «[-posterize](https://imagemagick.org/command-line-options/#posterize)» y «[-monochrome](https://imagemagick.org/command-line-options/#monochrome)».

Métodos de E-Dither

A partir de la versión 6.4.2-9, IM ofrece más de un tipo o método de tramado, que puede seleccionarse con el ajuste «[-dither](https://imagemagick.org/command-line-options/#dither)». Antes de esto, IM se limitaba a una variante del tramado de Riemersma o tramado de curva de Hilbert, que puedes activar con «-dither Riemersma». Ahora también puedes seleccionar un tramado de Floyd-Steinberg con «-dither FloydSteinberg». Puedes ver qué tipos de métodos de tramado se han implementado en tu versión de IM usando...

  magick -list dither

[IM Text]

Por ejemplo, aquí tienes la rueda de color tramada con distintos métodos de tramado.

  magick colorwheel.png -dither Riemersma      -colors 16 dither_riemersma.gif
  magick colorwheel.png -dither FloydSteinberg -colors 16 dither_floyd.gif

[IM Output] [IM Output]

Como puedes ver, el tramado de Floyd-Steinberg produce un patrón de tramado mucho más uniforme que el tramado de Riemersma predeterminado. La mayor diferencia entre ellos está en cómo distribuye cada uno el «error de color» entre los píxeles vecinos. Así que veamos cómo funciona realmente un E-Dither.

Cómo funciona un E-Dither

Reescritura en curso

El método concreto que usa IM para el tramado general es una variante del «tramado por corrección de error de curva de Hilbert». En realidad es una técnica de tramado muy buena, muy bien definida y razonablemente rápida. Para una descripción completa (y una variante muy similar), consulta Tramado de Riemersma. Básicamente, cada píxel de la imagen se examina siguiendo una trayectoria muy compleja conocida como «curva de Hilbert». Al píxel se le asigna el color más cercano a su valor, y cualquier diferencia entre el color original del píxel y el color seleccionado se guarda y se suma a los valores de color del siguiente píxel (que siempre es un píxel vecino) antes de elegir de nuevo un nuevo color. De este modo, cualquier variación de color entre los colores seleccionados y el color original de la imagen se distribuye a los demás píxeles de la misma zona. El resultado es que, aunque solo se asignan colores concretos a la imagen final, el color general básico de esa zona coincidirá de cerca con la imagen original. Por ejemplo, aquí tienes una pequeña imagen gris que le pedí a IM que tramara usando un conjunto de colores que no incluye el color original. La imagen resultante está ampliada para que puedas ver cada píxel de color asignado.

  magick -size 10x10 xc:'#999999' -scale 80x80  dither_not.gif
  magick -size 10x10 xc:'#999999' \
          -remap colortable.gif   -scale 80x80  dither.gif

[IM Output] [IM Output]

Como puedes ver, dado que el color de la imagen original no estaba en el mapa de color especificado, el color original se aproxima usando un patrón de los tres colores más cercanos que sí estaban en la tabla de colores indicada. Si promediáramos el color generado por el patrón de tramado anterior, obtendríamos el color [IM Text], que es muy parecido al color medio original de la imagen, [IM Text], y ese es todo el sentido del patrón de tramado que se produjo. Sin embargo, como la «trayectoria» usada para asignar los colores es compleja (aunque por lo general se mantiene en la zona local), las asignaciones de color producen un patrón esencialmente aleatorio. Técnicamente no es aleatorio, ya que la misma imagen producirá el mismo patrón, pero los resultados bien podrían ser aleatorios, o al menos pseudoaleatorios. El tramado «F-S» en realidad es solo uno (el primero) de varios «E-Dither rasterizados» que se han desarrollado desde su aparición a principios de la década de 1970. Probablemente sea también el más implementado, aunque no se considera el mejor. Consulta el artículo Algoritmos de tramado para un resumen más completo de tales algoritmos. A partir de IM v6.4.3 también está disponible directamente en IM, y está implementado para seguir una trayectoria «serpenteante» fila a fila desde la parte superior de la imagen hasta la inferior.

  magick -size 10x10 xc:'#999999'  -dither FloydSteinberg \
          -remap colortable.gif   -scale 80x80  dither_fs.gif

[IM Output] [IM Output]

El tramado de «Floyd-Steinberg» en concreto, a mi parecer, produce un patrón de píxeles más «entrecruzado» que el «tramado de curva de Hilbert», y de hecho se diseñó así. Un patrón tan regular puede facilitar mucho la limpieza manual de bajo nivel de pequeñas imágenes de iconos de color. Esto era algo que hacía mucho antes para la biblioteca de iconos de Anthony, pero ese tipo de cosa ya no se necesita a menudo, salvo quizá para imágenes monocromas pequeñas.

Problema del E-Dither: sensibilidad a los cambios

Uno de los mayores problemas que se afrontan al usar un tramado por corrección de error es que se obtiene un patrón de píxeles esencialmente aleatorio que, además, es muy sensible a los cambios. Por ejemplo, toma la imagen gris original y sustituye un píxel por un color distinto antes de volver a tramarla. El resultado es un cambio completo del patrón de tramado en cada píxel que esté más adelante en la trayectoria que sigue el tramado de curva de Hilbert.

  magick -size 10x10 xc:'#999999' -draw 'fill #C28 point 2,2' \
          -remap colortable.gif   -scale 80x80   dither_modified.gif
  magick compare dither.gif dither_modified.gif dither_difference.gif

[IM Output]
tramado original | [IM Output]
cambio de un píxel |
| [IM Output]
comparación de los cambios
---|---|---|---

Como puedes ver, ¡basta con añadir un único píxel a la imagen para que el patrón de tramado cambie de forma drástica! Solo hace falta el cambio de un único bit para que la imagen resultante sea distinta, aunque el aspecto general de una imagen (cuando no está ampliada) siga siendo básicamente el mismo (que es, al fin y al cabo, el propósito de un buen algoritmo de tramado). La imagen de «magick compare» también muestra la magnitud del cambio en el patrón de tramado. En este caso, a aproximadamente el 80 % de los píxeles se les asignó un color completamente distinto. En un tramado de curva de Hilbert, el cambio de un único píxel hará que cada píxel posterior pueda ser distinto, lo que significa que entre el 0 % y el 100 % del patrón de tramado podría cambiar. Depende de dónde se produjo el cambio en la compleja curva de Hilbert. El tramado de Floyd-Steinberg, sin embargo, solo avanza por la imagen en una dirección, por lo que el cambio de un único píxel modificará el patrón solo hacia un lado del cambio.

  magick -size 10x10 xc:'#999999' -draw 'fill #C28 point 2,2' \
          -dither FloydSteinberg -remap colortable.gif \
          -scale 80x80   dither_fs_modified.gif
  magick compare dither_fs.gif dither_fs_modified.gif dither_fs_difference.gif

[IM Output]
Tramado FS | [IM Output]
cambio de un píxel |
| [IM Output]
comparación de los cambios
---|---|---|---

Como puedes ver, tiene exactamente el mismo problema. El cambio de un único píxel provoca un cambio casi completo del patrón de tramado en las zonas de la imagen procesadas después de ese píxel. Es decir, de esa fila hacia abajo. Para una sola imagen, el patrón resultante de los colores tramados no importa. El color medio del patrón debería dar a la imagen el color apropiado para esa zona. Pero cuando tienes una animación en la que una imagen va seguida de otras muy parecidas, con grandes zonas de color constante, el patrón de tramado cambiante se vuelve muy visible y molesto, como un «ruido» de fondo de bajo nivel. Por ejemplo, aquí genero una animación de 3 imágenes del mismo color tramado pero con el cambio de un único píxel en cada fotograma. También amplío una región central para que puedas ver más claramente este patrón cambiante.

  magick -size 80x80 xc:'#999999' \
          \( +clone -draw 'fill #C28 point 2,2' \) \
          \( +clone -draw 'fill #28C point 2,2' \) \
          -remap colortable.gif  -set delay 50 -loop 0   dither_anim.gif
  magick dither_anim.gif -crop 10x10+40+40 +repage \
                              -scale 80x80     dither_anim_magnify.gif

[IM Output] [IM Output]

Como puedes ver, obtienes una especie de fondo en agitación en la imagen, causado por la pseudoaleatoriedad que genera el E-Dither. En la mayoría de los casos, los colores usados están lo bastante próximos como para no hacer visible este «ruido de tramado». Pero cuando los colores del tramado son visiblemente distintos (en este caso forzados por el uso de un mapa de color), sin duda se convierte en un problema. Consulta Optimización de color de vídeo para ver un ejemplo más práctico de una animación que muestra este «ruido de tramado». El cambio de patrón también causa problemas al optimizar animaciones. Es decir, un patrón distinto significa que la simple optimización de fotogramas no consigue reducir el tamaño de las superposiciones de fotogramas. Para ver una solución, consulta optimización de color difusa, aunque solo funciona cuando la agitación usa colores muy parecidos. A diferencia de otros métodos de tramado (como el umbral y el tramado ordenado), el ajuste «[-channel](https://imagemagick.org/command-line-options/#channel)» no afecta a la cuantización de color ni a los tramados por corrección de error. Básicamente, no tiene cabida en el funcionamiento de estas operaciones de imagen.
Los tramados ordenados no tienen ninguno de estos problemas, ya que contienen los cambios a la zona local inmediata del cambio. Por desgracia, también suelen estar limitados a usar un conjunto de colores derivado matemáticamente. (Consulta Tramado ordenado con un mapa de color uniforme).

Moteado de píxeles del E-Dither

Otro problema de los E-Dither es que pueden producir algún que otro píxel de color extraño en zonas que, de otro modo, serían bastante uniformes en color. Por ejemplo, algún píxel verde aislado en una imagen en escala de grises. O, como en los ejemplos de abajo, un píxel blanco en una zona de un azul liso y uniforme. Esto ocurre especialmente en imágenes grandes que contienen objetos con un gran número de colores junto a otras zonas de colores lisos, sólidos e invariables. Es especialmente típico de objetos de color superpuestos sobre fondos de color liso, como suele ocurrir en diagramas y dibujos. Puedes ver uno de esos píxeles de color extraño en la ampliación de los ejemplos de prueba de arriba, donde se añadió un píxel violeta claro de más a bastante distancia del pequeño cambio de un único píxel. Sin embargo, los píxeles de color extraño añadidos arriba no son muy visibles y el mapa de color cubre la imagen bastante bien, por lo que los píxeles extraños quedan razonablemente cerca de los tres colores normales usados para tramar la imagen. Para un ejemplo más extremo, aquí tengo un fondo de degradado difuminado, cuyos colores reduje drásticamente a 64 para forzar de verdad el tramado por corrección de error. |

  magick -size 100x60 xc:SkyBlue \
          -fill DodgerBlue -draw 'circle 50,70 15,35' \
          -fill RoyalBlue  -draw 'circle 50,70 30,45' \
          -blur 0x5  -colors 64     speckle_gradient.gif

[IM Output]
Como puedes ver con este mapa de color tan reducido, el tramado por corrección de error hizo un trabajo razonablemente bueno representando el degradado original. Pero si añadimos un parche de blanco puro a lo anterior... |

  magick -size 100x60 xc:SkyBlue \
          -fill DodgerBlue -draw 'circle 50,70 15,35' \
          -fill RoyalBlue  -draw 'circle 50,70 30,45' -blur 0x5 \
          -fill white -draw 'rectangle 40,40 60,55' \
          -colors 64   speckle_problem.gif

[IM Output]
Puedes ver que el E-Dither empezó de repente a producir un rociado de píxeles blancos en la zona superior de la imagen, donde antes no había ninguno. Aquí tienes una ampliación de una pequeña sección para que puedas ver estos píxeles con más claridad... |

  magick speckle_problem.gif -crop 15x15+75+0 +repage \
          -scale 90x90    speckle_prob_mag.gif

[IM Output]
El píxel de color extraño se debe a dos factores. En primer lugar, la cuantización de color se vio obligada a incluir un único blanco puro (pero ningún otro color de antialiasing blanco-azul) en el mapa de color final de la imagen, lo que permite al proceso de tramado usar ese color de más. Pero como los E-Dither acumulan errores poco a poco, sobre todo en zonas de colores extremos como la sección superior de la imagen anterior, con el tiempo los errores sumarán un valor lo bastante grande como para que ese color adicional sea la coincidencia más cercana. Por eso, de vez en cuando se emite un píxel blanco de fuerte contraste para «corregir el error», en una posición pseudoaleatoria. El resultado es un moteado muy ligero de píxeles blancos. Cuanto más lenta es la acumulación de error, más dispersos quedan esos píxeles blancos y más fuera de lugar parecen. La mejor solución es cambiar a otro formato de imagen que no tenga una tabla de colores limitada. Por ejemplo, convierte tu imagen en formato GIF a PNG. Esto evitará la necesidad de cuantización (reducción) de color y, por tanto, la necesidad de tramar los colores reducidos. La siguiente solución es sustituir el uso del E-Dither por algún otro método de tramado que «localice» los errores, como el tramado ordenado. Sin embargo, actualmente eso no es fácil de aplicar en IM. Consulta Mejores resultados con el tramado ordenado para ver uno de esos métodos hasta que se encuentre uno más general. Si cambiar a otro formato de imagen o usar un método de tramado distinto no es práctico (y a menudo no lo es), entonces solo te queda intentar arreglar la situación para esa imagen concreta. El mejor arreglo para esto es asegurarte de algún modo de tener otros colores justo fuera del gran grupo de colores que provoca la acumulación de error del E-Dither. Sin embargo, la cuantización de color normal no hace esto. Tiende a elegir un conjunto de colores promedio que representan grupos de color. Lo que hace falta son colores adicionales que «vallen» los bordes de un gran grupo de color, en lugar de un simple color promedio. Aquí, por ejemplo, usé un círculo en lugar de un cuadrado, de modo que no solo se añade un blanco puro, sino también varios colores blanco-azul. Estos se añadieron automáticamente por el antialiasing de los bordes del círculo, para suavizar su aspecto. |

  magick -size 100x60 xc:SkyBlue \
          -fill DodgerBlue -draw 'circle 50,70 15,35' \
          -fill RoyalBlue  -draw 'circle 50,70 30,45' -blur 0x5 \
          -fill white -draw 'circle 50,45 40,40' \
          -colors 64  speckle_fixed.gif

[IM Output]
Y una ampliación de la misma zona que antes. |

  magick speckle_fixed.gif -crop 15x15+85+0 +repage \
          -scale 90x90    speckle_fix_mag.gif

[IM Output]
Como puedes ver, los colores adicionales aportan los colores extra, justo fuera del degradado azul-cian. Ahora bien, aunque estos colores adicionales hacen que haya menos colores disponibles para el degradado en sí, sí aportan otros colores azul-blanco que permiten al E-Dither corregirse antes y con más frecuencia, antes de que el error acumulado pueda crecer demasiado. Es decir, no es que hayamos evitado el moteado del E-Dither, simplemente hemos aportado mejores colores para que el algoritmo de tramado trabaje con ellos. Si estudias la parte ampliada de la imagen, seguirás viendo un patrón de moteado, pero los colores están más cerca del color de fondo y hay muchos más, lo que produce una distribución del moteado más uniforme. Otra forma es generar nuestra propia tabla de colores, quizá basada en la que generó IM, y añadir los colores apropiados para evitar la acumulación de error. Sin embargo, esto no es fácil de hacer, sobre todo con un espacio de color tridimensional. Para este ejemplo de imagen concreto, una forma de evitar el «moteado» es generar y tramar el fondo por separado, con algo menos de colores de los necesarios, y luego superponer el recuadro blanco y su color adicional. |

  magick -size 100x60 xc:SkyBlue \
          -fill DodgerBlue -draw 'circle 50,70 15,35' \
          -fill RoyalBlue  -draw 'circle 50,70 30,45' -blur 0x5 \
          -colors 63 \
          -fill white -draw 'rectangle 40,40 60,55'  speckle_perfect.gif

[IM Output]
Esto añadirá un color «blanco» a la imagen, pero el fondo no tendrá ningún efecto de moteado, ya que el blanco no estaba disponible cuando se usó el tramado por corrección de error. El resultado es una imagen con exactamente 64 colores y sin moteado alguno. Sin embargo, esto depende mucho de la imagen y de lo que intentes conseguir, por lo que no es una solución general al problema del moteado.
Una alternativa más general a añadir colores extra es intentar eliminar el moteado de la imagen tramada final. Es decir, limpiar la imagen de algún modo. Sin embargo, esto es en sí un problema delicado, ya que no quieres eliminar píxeles que forman parte del patrón de tramado normal. Lo que necesitamos es encontrar píxeles de color que sean de algún modo muy distintos de todos los colores que los rodean, pero que además estén bien aislados, a cierta distancia, de todos los demás colores similares. ¿Tienes una solución de filtrado de imagen mejor? Resumen. Para mí, el moteado es un problema muy molesto, sobre todo en imágenes de iconos de escritorio que usan una tabla de colores muy limitada. Yo mismo suelo editar imágenes de «icono» más pequeñas para eliminar el moteado o corregir algunos de los demás efectos del tramado, como las bandas verticales. Si conoces otra solución mejor, házmelo saber.

Imágenes de mapa de bits monocromas con tramado

El operador «[-monochrome](https://imagemagick.org/command-line-options/#monochrome)» es una forma especializada del operador «[-colors](https://imagemagick.org/command-line-options/#colors)» para generar una imagen de mapa de bits. Por ello es un operador ideal para mostrar no solo el «tramado de curva de Hilbert», sino también para examinar más de cerca la selección de color. Aquí tienes un ejemplo típico. |

  magick logo.png  -monochrome     monochrome.gif

[IM Output]
El operador tramó la imagen basándose únicamente en su «intensidad» o «nivel» de brillo en escala de grises; sin embargo, no trama todo el rango de la escala de grises directamente, sino que aplica un umbral a los valores más extremos para llevarlos a sus valores máximos. Podemos verlo pidiéndole a IM que trame una imagen de degradado.

  magick -size 15x640 gradient: -rotate 90 \
                   -monochrome     monochrome_gradient.gif

[IM Output]

Como puedes ver, el degradado solo tiene tramado aproximadamente el 50 % central de sus colores por parte del operador «[-monochrome](https://imagemagick.org/command-line-options/#monochrome)». Un agradecimiento especial a Ivanova flamingivanova@punkass.com por señalar este curioso hecho sobre cómo funciona IM. Si quieres tramar usando todo el rango de la escala de grises, puedes usar el operador «[-remap](https://imagemagick.org/command-line-options/#remap)» con un mapa de color de blanco y negro puros (proporcionado por una imagen de patrón integrada). |

  magick logo.png  -remap pattern:gray50  mono_remap.gif
  magick -size 15x640 gradient: -rotate 90 \
                   -remap pattern:gray50     mono_remap_gradient.gif

[IM Output]

[IM Output]

Mediante una selección más cuidadosa de los colores con «[-remap](https://imagemagick.org/command-line-options/#remap)» puedes producir efectivamente el mismo rango de «umbral» que usa el operador «[-monochrome](https://imagemagick.org/command-line-options/#monochrome)», o cualquier otro rango de umbral que quieras. |

  magick xc:gray20  xc:white  +append   ctrl_colors.gif
  magick logo.png -colorspace Gray \
          -remap ctrl_colors.gif  -normalize  mono_remap_ctrl.gif
  magick -size 15x640 gradient: -rotate 90 \
          -remap ctrl_colors.gif  -normalize  mono_remap_grad_ctrl.gif

[IM Output]

[IM Output]

Lo que «[-monochrome](https://imagemagick.org/command-line-options/#monochrome)» hace en realidad es convertir primero la imagen dada en una imagen en escala de grises y, después, realizar una cuantización de color de dos colores para decidir los colores de umbral con los que tramar la imagen. Esto es lo que explorará la siguiente sección de ejemplos. El ajuste «[+dither](https://imagemagick.org/command-line-options/#dither)» actualmente no tiene efecto sobre el resultado de «[-monochrome](https://imagemagick.org/command-line-options/#monochrome)». Sin embargo, esto podría cambiar en el futuro, así que asegúrate de no tenerlo desactivado en tus scripts cuando uses este operador.

Cuantización a dos colores

En lugar de elegir tú mismo los dos colores de control, puedes usar la cuantización de color para elegir los dos mejores colores de la imagen con el operador «[-colors](https://imagemagick.org/command-line-options/#colors)». |

  magick logo.png   -colors 2 -colorspace gray  -normalize \
                                                 colors_monochrome.gif

[IM Output]
Sin embargo, el resultado no será el mismo que usar «[-monochrome](https://imagemagick.org/command-line-options/#monochrome)», ya que no convertimos primero la imagen a escala de grises. En su lugar, la imagen se tramó directamente entre los dos valores de color no grises elegidos. Es decir, se selecciona la mejor pareja de colores para tramar la imagen, en lugar de dos niveles de brillo en escala de grises. En consecuencia, producirá un resultado mejor para, por ejemplo, una imagen que solo use colores de aproximadamente el mismo «nivel» en escala de grises. Aquí, por ejemplo, usamos «[-colors](https://imagemagick.org/command-line-options/#colors)», así como un operador de tramado de mapa de bits «[-monochrome](https://imagemagick.org/command-line-options/#monochrome)», sobre un degradado rojo-azul. Como puedes comprobar, los resultados no son iguales.

  magick -size 20x640 gradient:red-blue -rotate 90    gradient_rb.png
  magick gradient_rb.png   -colors 2 -colorspace gray \
                                -normalize        colors_threshold.gif
  magick gradient_rb.png       -monochrome       mono_threshold.gif

[IM Output] [IM Output] [IM Output]

El operador «[-monochrome](https://imagemagick.org/command-line-options/#monochrome)» en el ejemplo anterior no logró encontrar ninguna diferencia para tramar como mapa de bits, ya que tanto el azul como el rojo tienen casi la misma intensidad. El método de cuantización «[-colors](https://imagemagick.org/command-line-options/#colors)», en cambio, no tuvo problema en encontrar colores aceptables entre los que tramar. También puedes ver que solo se tramó la parte central de los colores. Esto se debe a que la cuantización de color elige colores en el centro de los dos «grupos» de color que seleccionó. Los colores situados «fuera» de los colores seleccionados quedan, por tanto, sometidos a un umbral directo hacia ese color, sin tramado. Esto demuestra que los colores situados fuera del espacio de color de la cuantización no se traman, aunque este hecho es difícil de aprovechar de forma práctica. Si estableces el «[-colorspace](https://imagemagick.org/command-line-options/#colorspace)» en escala de grises antes de la cuantización, reproducirás el funcionamiento interno del operador «[-monochrome](https://imagemagick.org/command-line-options/#monochrome)». |

  magick logo.png -colorspace gray   -colors 2  -normalize \
                                                 monochrome_equivelent.gif

[IM Output]
Y por último, al desactivar el tramado, puedes producir una separación de los colores de la imagen más automática que la que se obtiene con un ajuste «[-threshold](https://imagemagick.org/command-line-options/#threshold)» fijo. |

  magick logo.png  -colorspace gray  +dither  -colors 2  -normalize \
           threshold_two_grays.gif

[IM Output]
| Recuerda que «[-monochrome](https://imagemagick.org/command-line-options/#monochrome)» actualmente ignora el ajuste «[+dither](https://imagemagick.org/command-line-options/#dither)», así que no puedes usar ese operador para hacer un «umbral inteligente».
---|---
Si eliminas el «[-colorspace](https://imagemagick.org/command-line-options/#colorspace)» de la fase de cuantización de color del procesamiento de la imagen, puedes aplicar un umbral a una imagen basándote en la mejor separación de colores posible (en lugar de la separación en escala de grises) para esa imagen. |

  magick logo.png  +dither  -colors 2  -colorspace gray -normalize \
           threshold_two_color.gif

[IM Output]

Tramar con mapas de color predefinidos

Como se mostró arriba, «[-colors](https://imagemagick.org/command-line-options/#colors)» intenta elegir un conjunto limitado óptimo de colores con el que representar una imagen. Con «[-remap](https://imagemagick.org/command-line-options/#remap)» le proporcionas a IM el conjunto final de colores que quieres usar para la imagen, ya sea que pienses tramar esos colores o simplemente sustituir los existentes por sus vecinos más cercanos. El argumento se da como una imagen que contiene todos los colores que te gustaría usar. Si quieres reducir una imagen grande con muchos colores a solo su lista de colores, puedes usar «[-unique-colors](https://imagemagick.org/command-line-options/#unique-colors)» antes de guardarla, para usarla luego con «[-remap](https://imagemagick.org/command-line-options/#remap)». | _Ten en cuenta que, aunque el operador «[-remap](https://imagemagick.org/command-line-options/#remap)» acepta cualquier imagen, no uses una imagen JPEG para esta imagen, o acabarás con muchos colores de más por culpa de su «compresión con pérdidas», que genera colores adicionales.

Por otro lado, ¡usar JPEG para generar colores adicionales puede ayudar a resolver el problema del «moteado» visto antes!_
---|---
Por ejemplo, aquí limito los colores usados en el logotipo de IM a un mapa predefinido de colores con nombre de X Window. El valor predeterminado es el tramado «Riemersma», pero a partir de IM v6.4.4 se amplió «[-dither](https://imagemagick.org/command-line-options/#dither)» para permitir la selección de otros métodos de tramado, como «FloydSteinberg». Por supuesto, todavía puedes desactivar el tramado con la opción «[+dither](https://imagemagick.org/command-line-options/#dither)».

  magick logo.png  -dither None       -remap colortable.gif  remap_logo_no.gif
  magick logo.png  -dither Riemersma  -remap colortable.gif  remap_logo_rm.gif
  magick logo.png  -dither FloydSteinberg \
                                       -remap colortable.gif  remap_logo_fs.gif

[IM Output] [IM Output] [IM Output] [IM Output] [IM Output]

Como puedes ver, IM intentó hacer un trabajo razonable representando la imagen usando solo los colores dados, aunque el resultado no se acerca ni de lejos al que obtienes si dejas que IM seleccione el conjunto de colores. Eso sí, esta imagen «[colortable.gif](../static/img/images/colortable.gif)» nunca se diseñó para tramar imágenes, sino como un conjunto de colores para diseñar iconos de color de estilo caricaturesco para las pantallas de color de X Window, más primitivas y antiguas (consulta Biblioteca de iconos de X Window de Anthony y Selección de colores de AIcons para más detalles). Observa también que la imagen final no usó los 32 colores que ofrece este mapa, aunque se usarán más colores del mapa cuando se active alguna forma de tramado ( y respectivamente) que cuando se desactiva (). Este último ejemplo muestra lo importante que es seleccionar un buen mapa de color. Por eso recomiendo que dejes que IM optimice la selección de colores de una imagen con el operador «[-colors](https://imagemagick.org/command-line-options/#colors)» y la modifiques según tus necesidades, salvo que tengas razones de mayor peso para no hacerlo. Un último apunte: aunque puedes especificar un espacio de color en el que «[-colors](https://imagemagick.org/command-line-options/#colors)» encontrará el mejor conjunto de colores, actualmente NO puedes definir un espacio de color para la fase de asignación o tramado de color. Todos mis experimentos parecen mostrar que el conjunto de colores se aplica (tanto el tramado por corrección de error como la sustitución por el color más cercano) basándose en el espacio RGB. El ajuste de espacio de color «[-quantize](https://imagemagick.org/command-line-options/#quantize)» solo se usa para la selección de colores, no para su asignación. Entonces, si usar un mapa de color es tan mala idea, ¿por qué querrías usarlo? Hay varias razones comunes, normalmente porque necesitas más control sobre la paleta concreta de colores usada en una imagen. Otro usuario también separó el mapa de color para poder usarlo en una Risograph (un sistema de impresión digital). Si conoces otra razón para usar el operador «[-remap](https://imagemagick.org/command-line-options/#remap)» que no haya presentado más abajo, escríbeme.

Mapa de color común u «óptimo»

La otra técnica, al manejar varias imágenes, es generar una tabla de colores común para todas las imágenes implicadas. Básicamente, añades todas las imágenes juntas en una gran imagen y luego usas el operador «[-colors](https://imagemagick.org/command-line-options/#colors)» para determinar un buen mapa de color que sea común a todas las imágenes. Una vez que tienes esa imagen de mapa de color, puedes usarla para recolorear cada una de las imágenes originales con este mapa de color predefinido recién generado. Otra opción es usar el operador especial «[+remap](https://imagemagick.org/command-line-options/#remap)», que hace lo mismo con un mapa de color de 255 colores. Cuenta los colores, realiza la cuantización de color para formar un buen mapa de color común y luego trama las imágenes para que usen ese mapa, si es necesario. Sin embargo, tanto la forma «[-remap](https://imagemagick.org/command-line-options/#remap)» como la «[+remap](https://imagemagick.org/command-line-options/#remap)» tienen una característica muy importante para las animaciones GIF. Convierten todas las imágenes a un «[-type](https://imagemagick.org/command-line-options/#type)» de imagen «Palette», con todas las imágenes usando la misma paleta de colores. La razón es que, al escribir una imagen GIF, la paleta de colores de la primera imagen se usará como «mapa de color global» del formato de archivo. Luego, a medida que se escribe cada imagen, IM observa que esas imágenes usan el mismo conjunto de colores, por lo que NO crea un «mapa de color local». Esto puede ahorrar hasta 256 × 3, es decir, 768 bytes de espacio de mapa de color por cada imagen del archivo GIF final. Solo los operadores «[-remap](https://imagemagick.org/command-line-options/#remap)» pueden hacer esto. Así que, al manejar GIF y en particular animaciones GIF, puede ser un punto importante a recordar. Para más detalles, y un ejemplo, consulta Animaciones GIF, tabla de colores global.

Colores seguros para web

Cuando la WWW se creó por primera vez, las pantallas de los ordenadores disponían de una gama limitada de colores, y los navegadores web solían usar un conjunto de colores más sencillo para las imágenes. Por eso era habitual recolorear las imágenes a este conjunto de colores, para hacerlas más pequeñas y asegurarse de que se vieran bien en los navegadores de los usuarios. Para más detalles, consulta Web Style Guide, Dithering. Para ayudar con esto, IM ofrecía una imagen de mapa de color integrada de esta tabla especial de 216 colores, llamada «netscape:». Así que veamos cómo se vería nuestra imagen de prueba en la pantalla de un navegador web antiguo usando estos colores.

  magick logo.png         -remap netscape:  remap_netscape.gif
  magick logo.png +dither -remap netscape:  remap_netscape_nd.gif

[IM Output] [IM Output] [IM Output] [IM Output]

Este conjunto de colores era una paleta determinada matemáticamente, diseñada por ingenieros de pantallas y ordenadores, no por artistas gráficos y, aunque es lo bastante general como para funcionar razonablemente bien con imágenes reales como las fotos, es muy mala para imágenes que contienen grandes zonas lisas de color, como logotipos, fondos, imágenes generadas por ordenador (como gráficas) e imágenes de estilo caricaturesco. Básicamente, funciona en zonas de colores muy variables, pero en las zonas lisas más grandes de colores constantes se aplica un tramado de tres colores (por lo general), como en la camisa azulada del logotipo de prueba de IM (arriba). En otras palabras, si estuvieras diseñando una imagen o un logotipo para usar en la web, por lo general intentarías usar los colores de esta paleta para las grandes zonas lisas y solo tener colores tramados en las zonas con tonos de color variables. Los comandos anteriores te permiten probar tus imágenes para ver cómo se verían en pantallas de ordenador más primitivas y editar la imagen para que use estos colores, de modo que funcionen bien. Esto es especialmente importante para los símbolos y las imágenes de navegación. Por supuesto, hoy en día, gracias a las exigencias de los usuarios de juegos y de la web, puedes estar bastante seguro de que la mayoría de los usuarios tienen una pantalla de ordenador moderna que no tiene aquellas antiguas limitaciones de color; no obstante, el uso de esta «paleta segura para web» sigue presente, ya que tiene otras ventajas, como la compresión de imagen. Para un debate sobre el uso de los colores seguros para web en el mundo moderno, consulta ¿Muerte de la paleta de colores segura para web? y, probablemente más importante, la opinión de la diseñadora gráfica que identificó por primera vez este mapa de color, Lynda Weinman.

Generar mapas de color

Determinar un buen mapa de color para cualquier imagen, o para un conjunto concreto de imágenes, puede ser muy importante. Esto cobra especial importancia cuando trabajas con una secuencia de imágenes que se usarán para una animación GIF. Básicamente, quieres que solo necesiten una tabla de colores para todos los fotogramas de la animación, en lugar de una tabla de colores distinta para cada fotograma. En otras palabras, quieres un único mapa de color para todas las imágenes. En este caso solo tienes dos opciones. Puedes intentar crear un mapa de color que funcione bien con cualquier imagen, o puedes intentar optimizar un mapa de color para el conjunto concreto de imágenes al que se lo vas a aplicar.

Mapa de color seguro para web

[IM Output] El primer método suele ser un mapa de color generado matemáticamente, como el mapa de color «netscape:» integrado en IM. Este ofrece un conjunto de 216 colores, que encaja perfectamente en el límite de 256 colores del formato GIF y aún deja espacio para gestionar la transparencia de la imagen, o incluso para añadir algunos colores extra con fines especiales, como sombras o superposiciones de texto. Este mapa de color se generó creando 6 niveles de color para cada uno de los tres canales de color, produciendo 6×6×6 colores, es decir, 216 colores. El número de la bestia. Como solo se usan 216 colores, aún queda espacio (para imágenes GIF) para añadir más colores al mapa con fines concretos. Por ejemplo, un color transparente, así como más tonos de escala de grises. Una antigua versión para Macintosh del mapa seguro para web hacía exactamente esto para intentar mejorar su resultado general, pero solo se usaba en los clientes web de Macintosh. Este es probablemente el mapa de color «uniforme» (o derivado matemáticamente) de uso más común, gracias a su sencillez y a su uso general en la World Wide Web.

Mapa de color uniforme 332

Otra asignación de color uniforme de uso común es el «mapa de color RGB 332». El número se refiere al número de bits usados para representar cada color dentro de un índice de color de 8 bits. Es decir, 3 bits (u 8 niveles) de rojo, 3 de verde y 2 bits (o 4 niveles de color) de azul, dado que nuestros ojos no responden bien al azul. Esto da 3+3+2 bits, es decir, un índice de color de 8 bits, o 256 colores. Perfecto para la limitada tabla de colores GIF. Sin embargo, no dejará espacio para un color de transparencia GIF ni para otros colores de uso especial. Aquí tienes una forma de hacer que IM genere este mapa de color... |

  magick -size 16x16 xc: -channel R -fx '(i%8)/7' \
                          -channel G -fx '(j%8)/7' \
                          -channel B -fx '((i>>3&1)|(j>>2&2))/3' \
          -scale 600% colormap_332.png

[IM Output]
| Los operadores de desplazamiento de bits «>>» y «<<» faltaban en el operador «[-fx](https://imagemagick.org/command-line-options/#fx)» hasta IM versión 6.2.9-2.
---|---
Una forma más sencilla de hacer lo mismo es usar el tramado ordenado con niveles de color uniformes mediante la operación «-ordered-dither threshold,8,8,4» (consulta esa sección de ejemplos). Una técnica mucho más fácil y rápida que el método FX casero anterior, y que además te permite usar otros mapas de tramado integrados para una mejor gestión de los degradados. El único inconveniente de este mapa es que en realidad no ofrece ningún color «gris». Sin embargo, este inconveniente puede ser una ventaja cuando se usa el tramado, ya que las ligeras diferencias de color reducen el efecto de los cambios de límite de color en un degradado en escala de grises, haciéndolo parecer algo más suave.

Mapa de color TrueColor de 16 bits

X Window usa un mapa de color uniforme similar al «mapa de color 332» anterior en una clase visual de 16 bits que rara vez se utiliza. En este caso se usan 16 bits para el índice de color, que se divide en 5 bits para el rojo, 5 para el verde y 6 para el azul. En otras palabras, este mapa de color se parece más a un «mapa de color 556» y se consigue mejor usando un tramado ordenado con niveles de color uniformes con un mapa de tramado «threshold». En concreto, la operación «-ordered-dither threshold,32,32,64». Sin embargo, los mapas de color de 16 bits rara vez se ven, ya que las imágenes que usan mapas de color suelen necesitar una tabla de colores de 8 bits. Por eso no lo mencionaré más.

Mapas de color uniformes con corrección gamma

Por el momento, IM no genera directamente mapas de color con corrección gamma. En su lugar, lo que deberías hacer es convertir tu imagen (suponiendo que tengas una versión de IM compilada con calidad Q16 o superior) desde sRGB, o el nivel de gamma que tenga la imagen, a un modelo RGB lineal, antes de hacer el tramado. Esto también vale para muchas otras operaciones de procesamiento de imágenes, como redimensionar, difuminar, etc. Consulta Redimensionar con corrección gamma para ver un ejemplo.

Posterizar: recolorear con un mapa de color uniforme

El propósito original del operador (usando un argumento de «2») es recolorear imágenes usando solo 8 colores básicos, como si la imagen se hubiera generado con un método de impresión de pósteres sencillo y barato que usa solo los colores básicos. De ahí el nombre del operador. El operador «[-posterize](https://imagemagick.org/command-line-options/#posterize)» es en realidad un operador especial de reducción de color que genera un mapa de color basado en el número de «niveles» de color dado, para cada canal de color de la imagen, tramando la imagen con un tramado por corrección de error.

  magick netscape: -scale 50%  +dither  -posterize 2   posterize_2_ns.gif
  magick netscape: -scale 50%  +dither  -posterize 3   posterize_3_ns.gif
  magick netscape: -scale 50%  +dither  -posterize 6   posterize_6_ns.gif

[IM Output] [IM Output] [IM Output] [IM Output]

Como puedes ver, un argumento «[-posterize](https://imagemagick.org/command-line-options/#posterize)» de «2» significa proporcionar solo 2 colores por canal de color, produciendo un mapa de solo 8 colores para una imagen RGB de 3 canales, como la anterior. Básicamente, recoloreará las imágenes usando el conjunto de umbral de 8 colores. Un argumento de «3» asignará los colores de la imagen basándose en un mapa de color de 27 colores, incluidos los colores de medio tono. Un argumento de «4» generará una tabla de 64 colores, y «5» genera un mapa de color de 125 colores. Por supuesto, como se mencionó arriba, un argumento de «6» reproducirá el mismo conjunto de 216 colores que ofrece la imagen «netscape:» integrada. Ten en cuenta que un argumento «[-posterize](https://imagemagick.org/command-line-options/#posterize)» de «0» o «1» no tiene sentido y, con las últimas versiones de IM, simplemente convierte las imágenes a negro puro (lo cual, aunque lógico, es bastante inútil). El resultado es que la imagen se ha recoloreado usando un mapa de color derivado matemáticamente o «uniforme». Puedes verlo con más claridad en una imagen de degradado, que produce una distribución uniforme de niveles de gris posterizados.

  #magick -size 20x640  gradient: -rotate 90  gradient.png
  magick gradient.png  +dither  -posterize 5   posterize_gradient.gif

[IM Output]

Por ejemplo, posericemos la imagen del logotipo de IM a varios niveles...

  magick logo.png  +dither -posterize 2  posterize_logo.gif
  magick logo.png          -posterize 2  posterize_logo_dither.gif
  magick logo.png          -posterize 6  posterize_6_logo.gif

[IM Output] [IM Output] [IM Output] [IM Output]

Como mejor prueba, posericemos la imagen sombreada de la «rueda de color».

  magick colorwheel.png  +dither  -posterize 2   posterize_2_cw.gif
  magick colorwheel.png  +dither  -posterize 3   posterize_3_cw.gif
  magick colorwheel.png  +dither  -posterize 6   posterize_6_cw.gif

[IM Output] [IM Output] [IM Output] [IM Output]

Y aquí está lo mismo con el tramado activado...

[IM Output] [IM Output] [IM Output] [IM Output]

Por supuesto, muchos de los tramados de mapa de bits que veremos en la siguiente sección también pueden generar tramados ordenados de nivel 2, usando distintos estilos de tramado. Sin embargo, pocos pueden usar un número mayor de niveles de gris. El tramado ordenado, a partir de IM v6.2.9, también es un método de posterización, debido a su limitación actual de tramar usando mapas de color uniformes. No obstante, el patrón de tramado es más uniforme, con una selección de estilos más amplia, que el tramado pseudoaleatorio que produce «[-posterize](https://imagemagick.org/command-line-options/#posterize)». Compara estos con las versiones de «[-posterize](https://imagemagick.org/command-line-options/#posterize)» con tramado de arriba.

  magick colorwheel.png  -ordered-dither o8x8,2   posterize_2_od.gif
  magick colorwheel.png  -ordered-dither o8x8,3   posterize_3_od.gif
  magick colorwheel.png  -ordered-dither o8x8,6   posterize_6_od.gif

[IM Output] [IM Output] [IM Output] [IM Output]

El mapa de tramado «threshold» (en lugar del «o8x8» usado arriba) convierte efectivamente «[-ordered-dither](https://imagemagick.org/command-line-options/#ordered-dither)» en un método de posterización sin tramado. Por último, el tramado ordenado sí te permite especificar un número distinto de niveles de color para cada canal de color individual. Algo que el operador «[-posterize](https://imagemagick.org/command-line-options/#posterize)» actualmente no permite.


Métodos de tramado por umbral

Imágenes por umbral

El método más sencillo de convertir una imagen en una imagen de mapa de bits en blanco y negro (a partir de color) es usar «[-threshold](https://imagemagick.org/command-line-options/#threshold)». En realidad es un sencillo operador matemático que solo proporciona un valor de corte. Todo lo que sea igual o inferior a ese valor pasa a negro, mientras que todo lo que sea mayor pasa a blanco.

  magick logo.png     -threshold   -1   threshold_0.gif
  magick logo.png     -threshold  25%   threshold_25.gif
  magick logo.png     -threshold  50%   threshold_50.gif
  magick logo.png     -threshold  75%   threshold_75.gif
  magick logo.png     -threshold 100%   threshold_100.gif

[IM Output] [IM Output] [IM Output] [IM Output] [IM Output]

Como puedes ver, un valor de «-1» convierte todos los colores en blanco, mientras que «100%» convierte todos los colores en negro. «50%» es, por supuesto, el valor más usado. Un valor de «0» es un caso especial que convierte en blanco todos los colores que no sean negro puro. Por supuesto, si la imagen no tiene colores negro puro, ¡solo obtendrás una imagen blanca sólida! |

  magick logo.png  -threshold   0    threshold_black.gif

[IM Output]
Si lo que quieres es convertir en negro todos los colores que no sean blanco puro, te recomiendo aplicar el umbral a la imagen negada en lugar de intentar calcular el valor de umbral correcto a usar (uno menos que el «MaxRGB» actual de IM), un valor que depende del ajuste de calidad, o «Q» de tu compilación concreta de IM. |

  magick logo.png  -negate -threshold 0 -negate threshold_white.gif

[IM Output]
El operador «[-threshold](https://imagemagick.org/command-line-options/#threshold)» puede considerarse el operador de «contraste» definitivo, que maximiza las diferencias de color según el nivel de umbral. No obstante, es un operador de escala de grises, lo que significa que el ajuste «[-channel](https://imagemagick.org/command-line-options/#channel)» puede usarse para ajustar a qué canal de color se aplica el operador. Por ejemplo, puedes aplicar un umbral a cada canal individual de la imagen para producir el mismo efecto que una operación «[-posterize](https://imagemagick.org/command-line-options/#posterize)» de nivel 2 sin tramado. |

  magick logo.png  -channel R -threshold 50% \
                     -channel G -threshold 50% \
                     -channel B -threshold 50%   threshold_posterize.gif

[IM Output]
| Ten en cuenta que «[-threshold](https://imagemagick.org/command-line-options/#threshold)» trata cualquier transparencia de una imagen como un canal de mate (matte), no como un canal alfa (tal como se almacena internamente en IM). Por eso hay que tener cuidado si piensas aplicar este operador al canal alfa. Consulta Canal de mate para más detalles.
---|---
Para una técnica de umbral más automática, puedes usar la técnica de cuantización a dos colores que mostramos antes. Por ejemplo, esto aplicará un umbral a la imagen basándose en los dos mejores colores encontrados en ella. Estos colores no tienen por qué ser de escala de grises, ni siquiera opuestos, solo los dos colores que mejor representan toda la imagen. Luego, los dos colores se asignan (con «[-normalize](https://imagemagick.org/command-line-options/#normalize)») a negro y blanco puros. |

  magick logo.png  +dither  -colors 2  -colorspace gray -normalize \
             threshold_two_color.gif

[IM Output]

Tramado aleatorio y umbral

El operador «[-random-threshold](https://imagemagick.org/command-line-options/#random-threshold)» es una forma especial de conversor de imágenes a mapa de bits. En este caso usa un «tramado aleatorio» muy sencillo para decidir si un píxel concreto pasa a ser un píxel blanco o negro. A diferencia de los operadores «[-threshold](https://imagemagick.org/command-line-options/#threshold)» o «[-monochrome](https://imagemagick.org/command-line-options/#monochrome)», o incluso de las variantes de la sección anterior, los canales seleccionados (definidos con «[-channels](https://imagemagick.org/command-line-options/#channels)») no se fusionan en un único canal de escala de grises ni se traman como una sola unidad. En cambio, «[-random-threshold](https://imagemagick.org/command-line-options/#random-threshold)» trabaja sobre cada canal seleccionado de forma totalmente independiente. Por supuesto, usar el operador directamente producirá una posterización de 2 niveles de la imagen con un tramado aleatorio. |

  magick logo.png  -random-threshold  0x100%  random_posterize.gif

[IM Output]
Convertir a escala de grises igualará todos los canales de la imagen antes de tramarlos. Pero como cada canal se trama de forma independiente y aleatoria, el resultado no es una imagen de mapa de bits como cabría esperar. En su lugar, obtendrás una salpicadura de píxeles de color, sobre todo en los colores de medio tono. |

  magick logo.png  -colorspace Gray -random-threshold  0x100% \
                                                   random_greyscale.gif

[IM Output]
Esta es la forma correcta de generar una imagen de mapa de bits con tramado aleatorio adecuada. |

  magick logo.png  -colorspace Gray -channel B \
          -random-threshold 0x100%    -separate   random_monochome.gif

[IM Output]
Básicamente, lo que hizo fue tramar solo un canal de la imagen en escala de grises y luego usar el operador de canal «[-separate](https://imagemagick.org/command-line-options/#separate)» para extraer ese canal como imagen de mapa de bits final. Ingenioso pero eficaz. Como característica especial de este operador, IM garantizará la generación de una imagen de mapa de bits si se usa el valor especial «All» de la opción «[-channels](https://imagemagick.org/command-line-options/#channels)». |

  magick logo.png  -channel All -random-threshold 0x100% random_all.gif

[IM Output]
No obstante, ten en cuenta que con este método se ignorará y perderá cualquier canal alfa, por lo que normalmente no se recomienda. Yo mismo descubrí esta antigua característica por accidente, a partir del código fuente. Ahora que sabes cómo usar el operador para generar correctamente mapas de bits a partir de una imagen en color, veamos cómo afecta el argumento al rango del tramado. Esto también muestra con claridad el «apelmazamiento» de píxeles que produce este tramado.

  #magick -size 20x640  gradient: -rotate 90  gradient.png
  magick gradient.png  -channel All \
                        -random-threshold 0x100%  random_grad_0x100.gif
  magick gradient.png  -channel All \
                        -random-threshold 10x90%  random_grad_10x90.gif
  magick gradient.png  -channel All \
                        -random-threshold 25x75%  random_grad_25x75.gif
  magick gradient.png  -channel All \
                        -random-threshold 50x50%  random_grad_50x50.gif

[IM Output] [IM Output] [IM Output] [IM Output]

Un ajuste «[-random-threshold](https://imagemagick.org/command-line-options/#random-threshold)» de «0x100%» producirá un «tramado aleatorio» puro de la imagen. Si los dos límites se fijan al mismo valor (o incluso se cruzan entre sí), simplemente producirá una imagen de «[-threshold](https://imagemagick.org/command-line-options/#threshold)» pura. Usar cualquier otro conjunto de límites (normalmente especificado con un porcentaje) aplicará un umbral al mapa de bits fuera del rango dado, mientras produce un patrón de tramado aleatorio para los valores dentro de ese rango. Los mejores resultados se obtienen usando un rango algo más reducido, igual que con el operador «[-monochrome](https://imagemagick.org/command-line-options/#monochrome)». Un valor de aproximadamente «30x80%» es probablemente el mejor resultado para la mayoría de los casos. |

  magick logo.png  -channel All -random-threshold 30x80%  random_30x80.gif

[IM Output]
Por supuesto, el resultado sigue sin ser muy bueno. Pero es que esta es la forma de tramado más sencilla y peor que existe. Lo que ocurre en realidad es que el patrón de tramado aleatorizado tiende a producir «grumos» de píxeles en lugar de un patrón de tramado suave. Esto se debe al «ruido» de alta frecuencia del generador de números aleatorios. Sin embargo, se ha demostrado que a resoluciones muy altas un tramado aleatorio produce un resultado extremadamente bueno, si es lo bastante aleatorio. IM usa un nivel de aleatoriedad de tipo criptográfico, por lo que probablemente sea muy aleatorio, aunque las imágenes rara vez se usan a una resolución lo bastante alta como para que resulte útil de este modo. Un «arreglo» que se ha propuesto para este tramado es usar un generador de «ruido azul» aleatorio (un filtro de alta frecuencia, frente al filtro de «ruido rosa» de baja frecuencia usado en la producción de sonido). Esto debería eliminar el apelmazamiento de los píxeles, pero es muy difícil de implementar digitalmente. No se ha encontrado ninguna implementación conocida de «tramado aleatorizado de ruido azul», y es poco probable que llegue a crearse.


Tramado ordenado

Mientras que un tramado aleatorio produce grumos aleatorios de píxeles, y los distintos tramados por corrección de error producen un patrón de puntos esencialmente aleatorio, el tramado ordenado es básicamente lo contrario. Está diseñado para ser lo más determinista posible desde el punto de vista matemático. Tan determinista que de hecho tienes que especificar el patrón que debe usar para tramar la imagen. El operador «[-ordered-dither](https://imagemagick.org/command-line-options/#ordered-dither)» tramará cada uno de los «[-channels](https://imagemagick.org/command-line-options/#channels)» seleccionados de la imagen con un patrón predefinido dado. El argumento define el patrón (conocido como mapa de umbral) a usar. Estos mapas de umbral se dividen en tres estilos básicos. Tramados de píxeles difundidos, donde los píxeles se colocan lo más lejos posible unos de otros para evitar el «apelmazamiento» y los artefactos de mosaico. O bien para agruparlos en puntos compactos que facilitan su impresión mecánica, en una técnica conocida como semitono digital. También hay algunos mapas de umbral artísticos especializados que veremos, e incluso diseñaremos nuestro propio patrón de tramado o mapa de umbral. En cada caso, el número de píxeles activados o desactivados en el mapa de umbral depende de la intensidad de nivel de gris de la imagen (o del canal de color individual) que se trama a mapa de bits. El mapa añade niveles de umbral de píxel de forma coherente, de modo que, una vez que un píxel se activa en un «umbral» concreto, permanece activado para cualquier gris más claro. Esta coherencia es muy importante; de lo contrario, se producen artefactos a lo largo de los límites de los cambios del patrón de tramado. Lo importante de esto es que el resultado de cada píxel de una imagen se determina de forma puramente matemática, con independencia de cualquier otro píxel de la imagen. Por eso, cualquier pequeño cambio en la imagen original no tendrá ningún efecto sobre la imagen en ninguna otra zona, un problema que sí tienen los tramados por corrección de error, como vimos antes. Este punto es vital para un tramado coherente de imágenes de vídeo y animaciones optimizadas.

Tramado de píxeles difundidos

El propósito original del tramado ordenado, y lo que la mayoría de los programadores gráficos esperan obtener al usar un tramado ordenado, a veces se denomina con más propiedad «tramado ordenado de píxeles difundidos». Esto significa que los píxeles se añaden al mapa en mosaico a medida que aumenta la intensidad de umbral, de modo que queden lo más alejados unos de otros y distribuidos de la forma más uniforme posible. Esto produce un patrón muy coherente que parece bastante suave y casi invisible en la mayoría de las pantallas modernas. Estos patrones se han calculado para tamaños de mosaico que son potencia de 2, es decir, tamaños de mosaico de 2, 4 y 8. Aunque IM también ofrece un patrón de umbral razonable para un mosaico de mapa de umbral de 3 por 3. Aquí tienes el conjunto actual de tramados ordenados integrados que ofrece IM. Recuerda que el argumento refleja el tamaño de mosaico del tramado ordenado.

  magick logo.png    -ordered-dither o2x2    logo_o2x2.gif
  magick logo.png    -ordered-dither o3x3    logo_o3x3.gif
  magick logo.png    -ordered-dither o4x4    logo_o4x4.gif
  magick logo.png    -ordered-dither o8x8    logo_o8x8.gif

[IM Output] [IM Output] [IM Output] [IM Output]

Observa cómo un tamaño de mosaico mayor permite simular más «niveles de color», pero también genera defectos más perceptibles o matrices rectangulares de píxeles en ciertos niveles. | _El tramado ordenado «o8x8» formó parte del código base de IM durante mucho tiempo, pero no se usaba. Solo se añadió como opción al operador «[-ordered-dither](https://imagemagick.org/command-line-options/#ordered-dither)» en IM v6.2.9, cuando IM Examples empezó a detallar el uso de este operador.

En ese momento se dieron a los mapas nombres más definitivos para permitir una mayor expansión del operador «[-ordered-dither](https://imagemagick.org/command-line-options/#ordered-dither)», aunque los antiguos nombres de «tamaño de mosaico», compatibles con versiones anteriores, se conservaron como alias de los nuevos nombres.

Además, los «mapas» que producían el «o3x3» y el «o4x4» se revisaron por completo para producir un mejor patrón de tramado de «píxeles difundidos». Antes de esto, los mapas producían «grumos» distintos de píxeles.

Consulta la página de notas Mejora del tramado ordenado para ver ejemplos de los patrones antiguos antes de corregirse, así como otros cambios realizados durante el desarrollo para la publicación oficial de las mejoras en IM v6.3.0._
---|---
Por supuesto, hay que convertir primero la imagen a escala de grises para producir un mapa de bits adecuado de todos los canales de la imagen; no obstante, como el proceso no es aleatorio, no necesitas posprocesar la imagen como sí hace falta con el operador «-random-threshold», lo que simplifica enormemente las cosas.

  magick logo.png -colorspace Gray  -ordered-dither o2x2  logo_bw_o2x2.gif
  magick logo.png -colorspace Gray  -ordered-dither o3x3  logo_bw_o3x3.gif
  magick logo.png -colorspace Gray  -ordered-dither o4x4  logo_bw_o4x4.gif
  magick logo.png -colorspace Gray  -ordered-dither o8x8  logo_bw_o8x8.gif

[IM Output] [IM Output] [IM Output] [IM Output]

A modo de referencia, aquí tienes cada uno de los patrones de «píxeles difundidos» de «[-ordered-dither](https://imagemagick.org/command-line-options/#ordered-dither)» aplicados a un degradado en escala de grises, para que puedas ver claramente cómo son.

  # Umbral sin tramado / tramado mínimo de tablero de ajedrez
  magick gradient.png   -ordered-dither threshold  od_threshold.gif
  magick gradient.png   -ordered-dither checks     od_checks.gif
  # Tramado de píxeles difundidos
  magick gradient.png   -ordered-dither o2x2       od_o2x2.gif
  magick gradient.png   -ordered-dither o3x3       od_o3x3.gif
  magick gradient.png   -ordered-dither o4x4       od_o4x4.gif
  magick gradient.png   -ordered-dither o8x8       od_o8x8.gif

[IM Output] [IM Output]


[IM Output] [IM Output] [IM Output] [IM Output]

El número de patrones de nivel efectivos o pseudoniveles que produce un tramado ordenado concreto suele ser (aunque no siempre) igual al número de píxeles del patrón más uno. Por eso, un tramado ordenado «o3x3» producirá 3×3+1, es decir, 10 niveles de gris efectivos por canal (negro, blanco y 8 patrones de gris artificiales) en la imagen resultante. También se muestran arriba dos mapas de umbral de tramado mínimo especiales:

  1. un «umbral al 50 %» directo sin tramado, que no produce ningún nivel de gris adicional, y
  2. un patrón de tramado «checks» o de tablero de ajedrez, que solo inserta un único patrón para añadir un «pseudonivel» extra al degradado resultante.

Tramados de semitono digital

El operador «[-ordered-dither](https://imagemagick.org/command-line-options/#ordered-dither)» se amplió en IM v6.2.8-6 con un conjunto de patrones de tramado de semitono digital (gracias a Glenn Randers-Pehrson). Todos ellos producían un sencillo patrón de puntos a 45 grados. Con IM v6.3.0 esto se amplió aún más con un conjunto similar de semitonos más grandes sin ángulo. Antes de la publicación de IM v6.3.0, las tramas de semitono se seleccionaban usando un argumento con la forma «{número}x1». Con la reescritura del tramado ordenado se eliminó esta limitación, se eligieron mejores nombres y se añadieron tramas de semitono adicionales (formas ortogonales) (consulta los argumentos de ejemplo más abajo).
Ten en cuenta que el semitono digital no es estrictamente una verdadera trama de semitono, que está diseñada para manejar puntos redondos de tinta depositados mecánicamente sobre un medio como el papel, el cartón o incluso el metal. Esos puntos pueden solaparse y emborronarse durante la impresión, lo que requiere cierto ajuste de nivel no lineal. Esto no hace falta para producir efectos de semitono puramente digitales. Para más detalles del proceso, consulta el documento Tramado y semitono (PDF). Dicho esto, los patrones de semitono digital del tramado ordenado sí ofrecen el mismo efecto básico que se ve en los periódicos y las revistas impresas de forma barata.
  # Trama de semitono (ángulo de 45 grados)
  magick logo.png   -ordered-dither h4x4a    logo_h4x4a.gif
  magick logo.png   -ordered-dither h6x6a    logo_h6x6a.gif
  magick logo.png   -ordered-dither h8x8a    logo_h8x8a.gif
  # Trama de semitono (ortogonal)
  magick logo.png   -ordered-dither h4x4o    logo_h4x4o.gif
  magick logo.png   -ordered-dither h6x6o    logo_h6x6o.gif
  magick logo.png   -ordered-dither h8x8o    logo_h8x8o.gif

[IM Output] [IM Output] [IM Output] [IM Output] [IM Output] [IM Output]

De nuevo, usa el operador «[-colorspace](https://imagemagick.org/command-line-options/#colorspace)» para generar un verdadero tramado de mapa de bits de una imagen.

  # Trama de semitono (ángulo de 45 grados)
  magick logo.png -colorspace Gray  -ordered-dither h4x4a logo_bw_h4x4a.gif
  magick logo.png -colorspace Gray  -ordered-dither h6x6a logo_bw_h6x6a.gif
  magick logo.png -colorspace Gray  -ordered-dither h8x8a logo_bw_h8x8a.gif
  # Trama de semitono (ortogonal)
  magick logo.png -colorspace Gray  -ordered-dither h4x4o logo_bw_h4x4o.gif
  magick logo.png -colorspace Gray  -ordered-dither h6x6o logo_bw_h6x6o.gif
  magick logo.png -colorspace Gray  -ordered-dither h8x8o logo_bw_h8x8o.gif

[IM Output] [IM Output] [IM Output] [IM Output] [IM Output] [IM Output]

Y por último, otra imagen de degradado de referencia para mostrar con claridad el patrón de tramado de semitono y cómo los grumos de píxeles dentro del patrón crecen hasta fusionarse entre sí a medida que cambia el nivel de gris.

  # Trama de semitono (ángulo de 45 grados)
  magick gradient.png   -ordered-dither h4x4a      od_h4x4a.gif
  magick gradient.png   -ordered-dither h6x6a      od_h6x6a.gif
  magick gradient.png   -ordered-dither h8x8a      od_h8x8a.gif
  # Trama de semitono (ortogonal)
  magick gradient.png   -ordered-dither h4x4o      od_h4x4o.gif
  magick gradient.png   -ordered-dither h6x6o      od_h6x6o.gif
  magick gradient.png   -ordered-dither h8x8o      od_h8x8o.gif
  magick gradient.png   -ordered-dither h16x16o    od_h16x16o.gif
  # Semitonos circulares (blanco y negro)
  magick gradient.png   -ordered-dither c7x7b      od_c7x7b.gif
  magick gradient.png   -ordered-dither c7x7w      od_c7x7w.gif

[IM Output] [IM Output] [IM Output]


[IM Output] [IM Output] [IM Output] [IM Output]


[IM Output] [IM Output]

Hasta la versión 6.2.9 de ImageMagick, todos los mapas de tramado ordenado por umbral anteriores eran lo único posible con IM. Esto ha cambiado, lo que permite a los usuarios añadir sus propios patrones e incluso aportarlos a la comunidad de IM. Los umbrales de semitono «circulares» los añadió Glenn Randers-Pehrson, en IM v6.6.5-6.

Tramado de semitono con desfase

El único problema del tramado de semitono anterior es que el mismo mapa de umbral (mosaico) se aplica a todos los canales de color de la misma manera. Eso significa que el mismo conjunto de color primario se dispone en puntos con el mismo «centro». Para conseguir lo que se conoce como «impresión con desfase» (offset printing), el patrón de umbral se rota según un patrón concreto, de modo que los colores forman «rosetas» a pequeña escala que destruyen los desagradables patrones de interferencia (muaré) que de otro modo podrían aparecer. Este diagrama explica básicamente el proceso, que se detalla con gran profundidad en la página de Wikipedia Semitono.

[IM Output]

No obstante, ten en cuenta que las tramas rotadas no se disponen bien en mosaico, por lo que lo mejor es generar directamente el patrón rotado, en lugar de usar un patrón de umbral en mosaico. Aquí tienes una forma de dar a una imagen un aspecto de impresión de semitono con desfase, usando un pequeño patrón de tablero de ajedrez rotado de 2x2 píxeles, que es más o menos la «trama» más pequeña que puede usarse. |

  magick colorwheel.png  -set option:distort:viewport '%wx%h+0+0' \
          -colorspace CMYK -separate null: \
          \( -size 2x2 xc: \( +clone -negate \) \
                +append \( +clone -negate \) -append \) \
          -virtual-pixel tile -filter gaussian \
          \( +clone -distort SRT 60 \) +swap \
          \( +clone -distort SRT 30 \) +swap \
          \( +clone -distort SRT 45 \) +swap \
          \( +clone -distort SRT 0 \)  +swap +delete \
          -compose Overlay -layers composite \
          -set colorspace CMYK -combine -colorspace RGB \
          offset_colorwheel.png

[IM Output]
Ten en cuenta que las cuatro «tramas» rotadas se aplican a la imagen en su conjunto; es solo el paso «-combine» en el espacio de color CMYK el que extrae realmente los 4 canales de color distintos de las imágenes con trama. Además, la distorsión «sin operación» (no-op) del último canal «negro» es importante, ya que difuminará el patrón de tablero de entrada según el filtro gaussiano que se usó en los demás canales durante sus rotaciones, aunque esa trama en sí no se rote. Y aquí uso la función de escalado de la distorsión SRT empleada para generar los mosaicos rotados, a fin de crear un «patrón de trama» algo más grande y borroso.

  magick parrots_med.png  -set option:distort:viewport '%wx%h+0+0' \
          -colorspace CMYK -separate null: \
          \( -size 2x2 xc: \( +clone -negate \) \
                +append \( +clone -negate \) -append \) \
          -virtual-pixel tile -filter gaussian \
          \( +clone -distort SRT 2,60 \) +swap \
          \( +clone -distort SRT 2,30 \) +swap \
          \( +clone -distort SRT 2,45 \) +swap \
          \( +clone -distort SRT 2,0  -blur 0x0.7 \) +swap +delete \
          -compose Overlay -layers composite \
          -set colorspace CMYK -combine -colorspace RGB \
          offset_parrots.png

[IM Output]

Observa que el patrón sigue siendo muy «cuadriculado», sobre todo la trama negra de la que se derivan todas las demás. POSIBILIDAD FUTURA: Sustituir el tablero de ajedrez de 2 píxeles anterior por un patrón de tablero de ajedrez a nivel de píxel «pattern:gray50». Las opciones del filtro gaussiano pueden usarse para ajustar el desenfoque del patrón escalado. Otra opción es escalar el patrón de forma borrosa y aplicarle un umbral, para obtener puntos más redondos. Esto puede luego rotarse como antes para crear las 4 tramas de color. También sería mejor si se pudiera usar una trama más grande con un patrón de puntos hexagonales, en lugar del patrón de tablero de ajedrez que usé arriba.
Es importante señalar que esto no genera realmente puntos de color como la verdadera impresión con desfase, sino que lo finge multiplicando simplemente las tramas de color contra la imagen original. Puedes ver que es así por el brusco cambio de color a lo largo de los bordes del loro rojo contra el fondo verde. La verdadera impresión con desfase, que usa solo puntos de color puro, no tendrá ningún cambio de color en el centro del punto. Es el tamaño del punto de color puro lo que debería cambiar, en función de la media de los colores de esa zona representada por el punto en la imagen de origen. Generar realmente una imagen de impresión con desfase verdadera, que contenga solo puntos redondos en cada canal de color del tamaño apropiado, requeriría mucho más trabajo. Habría que determinar el color medio de cada punto en cada canal de color y, a partir de ahí, generar el punto de color del tamaño apropiado (un círculo con antialiasing). ¿Alguien quiere intentarlo? Lo anterior procede de una discusión en el foro de IM, Efecto de semitono CMYK, que examina cómo lo «finge» Photoshop y cómo ImageMagick podría conseguir el mismo efecto. Esta discusión también está relacionada con Tramado de semitono en B/N, que analiza más de cerca la generación de verdaderas tramas de semitono usando puntos reales de tamaño apropiado. Sin embargo, esa discusión no llegó al siguiente paso de usar tramas con desfase (rotadas). Esas tramas probablemente requerirían rotar la imagen para generar los puntos y luego volver a rotar el patrón de puntos para ese canal de color concreto.

Mapas de umbral XML

Desde la versión 6.3.0 de IM, en lugar de usar un conjunto fijo de mapas incrustados en el código fuente de IM (mostrados antes), los mapas se leen ahora de un conjunto de archivos de datos XML externos al propio programa. Como parte de este cambio, ahora puedes listar los «mapas de umbral» disponibles que puede usar el operador «[-ordered-dither](https://imagemagick.org/command-line-options/#ordered-dither)».

  magick identify -list threshold

[IM Output]

La lista anterior muestra no solo los mapas de umbral disponibles, sino también los alias proporcionados por compatibilidad con versiones anteriores o por nomenclatura alternativa, y los definidos en mi propio archivo de datos XML personal «thresholds.xml» (guardado en el subdirectorio «.magick» de mi directorio personal). Cuando «[-ordered-dither](https://imagemagick.org/command-line-options/#ordered-dither)» busca un mapa, se usará el primero que encuentre en la lista anterior. Por eso no puedes anular un patrón de umbral definido por el sistema. El archivo del sistema «thresholds.xml» (cuya ruta indica la opción «[-list](https://imagemagick.org/command-line-options/#list)» anterior) contiene un resumen completo del formato del archivo XML. Un formato lo bastante sencillo (con comprobaciones de error por parte de IM) como para permitir a los usuarios definir y crear sus propios mapas de umbral para el tramado ordenado. Por ejemplo, aquí tienes una copia del mapa de umbral «diag5x5» que definí en mi archivo «threshold.xml» personal.

[IM Output]

Si te fijas, crea un sencillo mapa de 5x5 de una única línea diagonal que se vuelve más gruesa a medida que aumenta el nivel de umbral. Los números de nivel del mapa van de 0 a 5, uno menos que el divisor, que declara en cuántos «grises» necesita dividir el degradado de color. Aquí tienes un degradado tramado con este mapa de umbral personal.

  magick gradient.png   -ordered-dither diag      od_diag.gif

[IM Output]

Y aquí tienes un ejemplo de uso de ese umbral para tramar el canal alfa de una sencilla imagen con sombra, propósito para el que lo diseñé.

  magick -size 70x60 xc:none -font Candice -pointsize 50 \
          -fill black -annotate +10+45 'A' -channel RGBA  -blur 0x5 \
          -fill white -stroke black -draw "text 5,40 'A'"   shadow.png

  magick shadow.png  -channel A  -ordered-dither diag   shadow_diag.gif

[IM Output] [IM Output]

¡Bastante chulo! Más sobre el tramado de canales alfa más adelante. Primero necesito mostrar también cómo usar las capacidades de coloreado del operador «[-ordered-dither](https://imagemagick.org/command-line-options/#ordered-dither)» ampliado.

Tramado ordenado con niveles de color uniformes

Con la publicación de IM v6.3.0, no solo se cambiaron los mapas de umbral usados por «[-ordered-dither](https://imagemagick.org/command-line-options/#ordered-dither)» para que se leyeran de archivos externos, sino que también se mejoraron las operaciones internas para permitir el uso de mapas de color «posterizados» definidos matemáticamente. Esto significa que puedes generar un tramado de imágenes más determinista de lo que puedes lograr con el «tramado por corrección de error». Esto es especialmente importante para las reducciones de color que implican animaciones, ya que no tendrás problemas por las diferencias de color entre fotogramas. Los niveles de posterización se pasan al argumento de «[-ordered-dither](https://imagemagick.org/command-line-options/#ordered-dither)» mediante una lista adicional de números separados por comas, añadida al nombre del mapa de umbral a usar. Si no se indican números, el operador vuelve al mapa de color normal de 2 colores (o nivel 1 de posterización). Por ejemplo, un argumento de «checks,6» usará un clásico mapa de color seguro para web (nivel 6 de posterización) (también definido por la imagen de mapa de color integrada «netscape:»). Sin embargo, como se usa el mapa de tramado mínimo «checks», se añade un único nivel extra de tramado entre cada uno de los 6 niveles de color, creando 11 pseudoniveles de colores en cada canal de la imagen. En otras palabras, aunque solo se usan 6 niveles de color por canal (que producen 6^3, es decir, 216 colores), el único patrón de tramado entre niveles aumenta el tramado a 11 niveles efectivos (que producen 11^3, es decir, 1331 colores efectivos). Por ejemplo, aquí tienes un degradado en escala de grises tramado usando 6 niveles de gris y varios mapas de umbral. El primer mapa, «threshold», es un mapa de umbral de tramado ordenado especial sin tramado, que muestra solo los colores usados.

  magick gradient.png   -ordered-dither threshold,6  od_threshold_6.gif
  magick gradient.png   -ordered-dither checks,6     od_checks_6.gif
  magick gradient.png   -ordered-dither o2x2,6       od_o2x2_6.gif
  magick gradient.png   -ordered-dither o4x4,6       od_o4x4_6.gif
  magick gradient.png   -ordered-dither o8x8,6       od_o8x8_6.gif

[IM Output] [IM Output] [IM Output] [IM Output] [IM Output]

Como puedes ver, aunque solo se usan 6 colores, con el tramado ordenado aumentas el número efectivo de colores usados para definir el degradado, hasta un punto en el que cuesta notar lo pocos colores que se usaron en realidad. No solo puedes definir el número de niveles de posterización para todos los canales, sino que, a diferencia de la opción de tramado por corrección de error «[-posterize](https://imagemagick.org/command-line-options/#posterize)», puedes especificar los niveles de cada canal. Los números se asignan a los canales según el ajuste «[-channels](https://imagemagick.org/command-line-options/#channels)». Por ejemplo, aquí tramamos el degradado usando un mapa de color 332 especial (8 niveles de rojo y verde, 4 de azul) que define un total de 256 colores.

  magick gradient.png   -ordered-dither o8x8,8,8,4   od_o8x8_884.gif

[IM Output]

Debido al distinto número de niveles de color por canal, la imagen anterior no contiene solo grises puros, sino que incluye algunos píxeles azulados y amarillentos que se cancelan entre sí para producir niveles extra de gris. Ahora compara la versión con tramado ordenado frente a la versión con tramado por corrección de error usando niveles de posterización de 2 y 6, y un «mapa de color 332» (8 niveles de rojo y verde, 4 de azul).

  magick logo.png  -ordered-dither o8x8        logo_o8x8_2.gif
  magick logo.png  -posterize 2                logo_posterize_2.gif
  magick logo.png  -ordered-dither o8x8,6      logo_o8x8_6.gif
  magick logo.png  -posterize 6                logo_posterize_6.gif
  magick logo.png  -ordered-dither o8x8,8,8,4  logo_o8x8_332.gif
  magick logo.png  -remap colormap_332.png     logo_remap_332.gif

[IM Output] [IM Output] [IM Output] [IM Output] [IM Output] [IM Output]

La primera imagen de cada par anterior tiene tramado ordenado matemáticamente, mientras que la segunda tiene tramado pseudoaleatorio «por corrección de error». El último par usa el «mapa de color 332» especial (consulta Generar mapas de color), que se considera probablemente el mejor mapa de color de posterización para imágenes generales con un límite de 256 colores. La diferencia desigual en los niveles de canal produce un sombreado de colores algo mejor para esta imagen de estilo caricaturesco. Fue para permitir la producción del «mapa de color 332» por lo que el operador «[-ordered-dither](https://imagemagick.org/command-line-options/#ordered-dither)» incluyó la capacidad de especificar niveles distintos para cada canal de color.

Mejores resultados con el tramado ordenado

Examinemos más de cerca el tramado ordenado de nivel 6 que acabamos de generar.

  magick logo.png -ordered-dither o8x8,6 -format %k info:

[IM Text]

Como puedes ver, en el caso de esta imagen ni siquiera nos acercamos a llenar la tabla de colores GIF (límite de 256). Básicamente, como la imagen se compone en su mayoría de colores azules, apenas se usaron tonos de rojo o de verde de un mapa de color uniforme de nivel 6. Sin embargo, al aumentar el número de niveles de posterización podemos llenar mejor la tabla de colores GIF, para producir una imagen con tramado ordenado mejor.

  magick logo.png -ordered-dither o8x8,13 -format %k info:

[IM Text]

Esto produce suficientes colores para quedar solo ligeramente por debajo de los límites de la tabla de colores GIF. Con el aumento del número de colores, el resultado se ve mucho mejor que el de un simple mapa de color uniforme estándar. |

  magick logo.png -ordered-dither o8x8,13    logo_o8x8_13.gif

[IM Output]
Como puedes ver, con un valor de «niveles» alto, «[-ordered-dither](https://imagemagick.org/command-line-options/#ordered-dither)» puede producir imágenes comparables a las cuantizadas por color, a la selección de colores concreta que genera la cuantización de color con un tramado por corrección de error. Lo importante de estas imágenes no es que sean de alta calidad. Al fin y al cabo, una cuantización de color completa puede producir más fácilmente un mejor mapa de color para la imagen. Lo importante es que el patrón de tramado de bajo nivel dentro de la imagen es fijo, con independencia de los pequeños cambios que puedan producirse. Solo las zonas que cambian cambiarán en la imagen con tramado ordenado. Es decir, no tienen la sensibilidad del E-Dither a los cambios que causa problemas para la optimización de fotogramas en las animaciones GIF. (consulta Problema de optimización). Por supuesto, para una animación tendrás que «[-append](https://imagemagick.org/command-line-options/#append)» todas las imágenes juntas antes de comprobar cuántos colores se usan en realidad. Y tendrás que usar la opción especial «[+remap](https://imagemagick.org/command-line-options/#remap)» después de usar «[-ordered-dither](https://imagemagick.org/command-line-options/#ordered-dither)» para forzar a IM a generar un «mapa de color global común» para TODAS las imágenes, aunque ya hayas realizado la reducción de color y el tramado. Este método de determinar el número de niveles de color no es sencillo de calcular, pero funciona. Espero idear una forma de que IM determine el mejor nivel automáticamente, sobre todo para las animaciones GIF.


Patrones de tramado y mapas de umbral caseros

Antes te mostré que el nuevo operador «[-ordered-dither](https://imagemagick.org/command-line-options/#ordered-dither)» puede aceptar un patrón de tramado definido por el usuario. Aquí te voy a mostrar cómo puedes crear tu propio patrón de tramado. En concreto, un patrón especial que me resultó útil para generar sombras formadas por líneas horizontales.

Patrones de tramado multiimagen

Lo primero que tienes que hacer es crear un conjunto de imágenes que definan el patrón que quieres crear. El patrón debería empezar con una imagen negra sólida del tamaño adecuado como primera imagen (todos los píxeles desactivados) y una imagen blanca sólida en el otro extremo (todos los píxeles activados). La siguiente imagen debería ser el patrón de gris al 50 % central, que define el estilo básico del tramado que intentas conseguir. Por ejemplo, aquí tienes mi patrón de tramado casero inicial. Lo guardo en un archivo GIF multiimagen (no una animación GIF)...

  magick -size 2x2 xc:black \
          \( +clone -draw 'fill white line 0,0 1,0' \) \
          xc:white     dpat_hlines2x2.gif
  montage dpat_hlines2x2.gif    -tile x1 -background none -frame 2 \
          -filter box  -geometry 32x32+5+0    dpat_hlines2x2_imgs.gif

[IM Output]

Este es más o menos el conjunto de imágenes de patrón de tramado más sencillo que puedes obtener, y es muy parecido al tramado «checks» o de tablero de ajedrez, pero con líneas horizontales en lugar de un patrón de damero. Para que puedas ver cómo sería este patrón de tramado, aquí tienes un tramado ordenado casero bastante sencillo que hace uso directo del conjunto de imágenes de tramado por umbral.

  magick gradient.png   dpat_hlines2x2.gif \
          -virtual-pixel tile  -fx 'u[(floor((n-1)*u)+1) % n]' dgrad_hlines2x2.gif

[IM Output]

Como puedes ver, el patrón de tramado no tiene nada del otro mundo. La función «[-fx](https://imagemagick.org/command-line-options/#fx)» es una variante de la función de tablas de consulta de color, es decir, una función de tipo «patrones de consulta de tramado de IM». Y con un ajuste «[-virtual-pixel](https://imagemagick.org/command-line-options/#virtual-pixel)» de «tile», la función ni siquiera necesita conocer el tamaño de la imagen de patrón de tramado que estás usando. El uso de «[-virtual-pixel](https://imagemagick.org/command-line-options/#virtual-pixel)» por parte del operador «[-fx](https://imagemagick.org/command-line-options/#fx)» con índices calculados como este estaba roto antes de IM versión 6.2.9-2.
Probemos de nuevo este conjunto de patrones de tramado, pero usando una sencilla imagen con sombra...
  magick shadow.png dpat_hlines2x2.gif  -channel A \
          -virtual-pixel tile  -fx 'u[floor((n-1)*u)+1].g' \
          shadow_dpat_hlines2x2.gif

[IM Output] [IM Output]

Mapas de umbral caseros para tramado ordenado

El patrón de tramado casero anterior es más o menos el patrón de tramado más sencillo que puedes obtener y, por eso, podemos convertirlo directamente en un mapa de umbral XML, para que el rápido operador integrado «[-ordered-dither](https://imagemagick.org/command-line-options/#ordered-dither)» pueda usarlo. Aquí tienes la definición XML final, que guardé en mi propio archivo de mapas de umbral personal «~/.magick/thresholds.xml» de mi directorio «$HOME».

[IM Output]

El formato XML es muy sencillo y define un mapa de 2x2 píxeles. A la primera imagen, la negra, se le da un valor de cero y no tiene píxeles, así que no hay ningún valor cero presente. A los píxeles activados (puestos en blanco) en la imagen central se les da el valor «1», y a los píxeles de la imagen restante (la segunda) se les da el valor «2». El «divisor=» define el número de imágenes, o pseudoniveles de color (niveles de color falsos), que representa este patrón de tramado, por lo que tiene un valor de «3». Divide los valores de los píxeles para definir el nivel de color en el que ese píxel debe activarse. Por eso, los dos píxeles superiores se activan para colores mayores que 1/3, mientras que los dos inferiores se activan para valores de color mayores que 2/3. Es decir, cada valor de píxel representa un nivel de «umbral», y por eso los patrones de tramado también se llaman mapas de umbral. El resto de la definición define los nombres (y el alias opcional) por los que puedes referirte al mapa de umbral para el operador de tramado ordenado. Así que probémoslo...

  magick gradient.png  -ordered-dither hlines2x2  od_hlines2x2.gif
  magick shadow.png  -channel A \
          -ordered-dither hlines2x2   shadow_hlines2x2.gif

[IM Output]
[IM Output] [IM Output]

Como puedes ver, el resultado es razonablemente bueno, pero podemos hacer otras cosas para mejorarlo. Ajustando los valores de umbral del mapa, podemos cambiar los límites para que no divida el espacio de color en 3 zonas iguales...

[IM Output]

Observa cómo aumenté el divisor a «10», para dividir los niveles de color en diez secciones iguales. Luego cambié los ajustes de umbral para que el patrón empiece en un umbral del 30 % en el extremo transparente (negro), hasta el 90 % para totalmente opaco (blanco). Y aquí tienes los resultados de cambiar el mapa de umbral.

  magick gradient.png  -ordered-dither hlines2x2a  od_hlines2x2a.gif
  magick shadow.png -channel A \
          -ordered-dither hlines2x2a  shadow_hlines2x2a.gif

Como puedes ver, esto amplió el rango de píxeles semitransparentes que usan líneas horizontales puras como patrón de tramado. Esto da un mejor efecto de sombra, aunque probablemente solo debería usarse con una sombra menos difusa que la del ejemplo usado aquí. No obstante, ten en cuenta que este tipo de cambio en un umbral es muy poco común. Aunque está justificado para el uso previsto en este caso. Básicamente, no define correctamente un degradado, ni permite tonos más claros y más oscuros de los patrones. Para eso necesitamos crear un mapa de umbral mucho más complejo, con más píxeles y más patrones.

Tramado casero de líneas horizontales

Aquí amplié el sencillo patrón de tramado de líneas horizontales que creé arriba a un conjunto de patrones, para producir un degradado más suave de «desactivado» a «activado». Este fue el resultado.

  montage dpat_hlines.gif   -filter box   -geometry 60x20+2+0 \
          -tile x1 -background none  -frame 2   dpat_hlines_images.gif
  magick gradient.png  dpat_hlines.gif  \
          -virtual-pixel tile  -fx 'u[(floor((n-1)*u)+1) % n]' \
          dgrad_dpat_hlines.gif
  magick shadow.png dpat_hlines.gif  -channel A \
          -virtual-pixel tile  -fx 'u[floor((n-1)*u)+1].g' \
          shadow_dpat_hlines.gif

[IM Output]
[IM Output]
[IM Output] [IM Output]

Como puedes ver, ahora consta de 9 imágenes de 12x4 píxeles. No representa todos los patrones de píxeles que podrías tener, pero esto realza el efecto de las líneas. Además, dupliqué su altura para escalonar adecuadamente los huecos de las líneas. Aquí tienes otro ejemplo de uso de este patrón de tramado...

  magick -size 120x55 xc:white  -draw 'fill #777 ellipse 50,43 30,5 0,360' \
          -motion-blur 0x15+180   -blur 0x2      sphere_shadow.png
  magick sphere_shadow.png dpat_hlines.gif \
          -virtual-pixel tile  -fx 'u[(floor((n-1)*u)+1) % n]' \
          sphere_shadow_dither.gif
  magick sphere_shadow_dither.gif   -fill red  -stroke firebrick \
          -draw 'circle 35,25 35,5'     sphere_shadow_hlines.gif

[IM Output] [IM Output] [IM Output]

El siguiente paso es convertir este conjunto de patrones de tramado en una única imagen de mapa de umbral, en lugar de un conjunto de varias imágenes. Esto se consigue usando algunas manipulaciones de imagen ingeniosas para fusionar todas las imágenes. [IM Output]
[IM Output]


|

  magick -size 1x10 gradient: -flip -crop 1x1 +repage -delete 0,-1 \
          -scale 12x4\! null: \( dpat_hlines.gif -delete 0 \) \
          -alpha off -compose CopyOpacity -layers Composite \
          -reverse -compose Over -flatten -alpha off dmap_hlines.png

[IM Output]
El valor «10» es uno más que el número de imágenes del patrón de tramado, mientras que «-scale 12x4\!» es el tamaño de los patrones de tramado que se convierten en un mapa de umbral. El resultado es un mapa en escala de grises, sin colores negro ni blanco puros. El nivel de gris usado para un píxel significa que, si el nivel de color es ese valor de gris o superior, ese píxel debe activarse. Es decir, cada nivel de gris es el nivel de «umbral» en el que el valor de color pasa de negro a blanco. Si quieres verlo de otra forma, los píxeles oscuros suelen hacer que esos píxeles se activen para más niveles de color. Mientras que los píxeles claros solo se activan cuando el color de la imagen se vuelve muy brillante. Esto es casi una negación de lo que la imagen parece en realidad, pero si lo piensas tiene sentido. También usé una imagen PNG en lugar de GIF para el mapa, ya que solo hay que guardar una imagen y, lo más importante, para intentar conservar los niveles de calidad de 16 bits de los valores de umbral. GIF solo puede manejar niveles de color de 8 bits. Ahora podemos tramar nuestras imágenes usando una sola imagen y una comparación de umbral mucho más sencilla de cada píxel directamente contra la imagen (o mapa) de umbral de tramado.

  magick gradient.png dmap_hlines.png \
          -virtual-pixel tile  -fx 'u>=v'   dgrad_dmap_hlines.gif

[IM Output] [IM Output]

Mira cuánto más sencillo es un mapa de umbral. Solo tienes una imagen, y una única comparación directa por píxel, para cada canal que se trama. Esto hace que tramar con un mapa de umbral sea muy muy rápido. Mucho más rápido que una cuantización de color completa. Esta sencillez es la razón por la que ImageMagick y la mayoría del software gráfico usan un mapa de umbral para almacenar los distintos patrones de tramado. La prueba mayor o igual («>=») no se añadió al operador «[-fx](https://imagemagick.org/command-line-options/#fx)» hasta IM versión 6.2.9-2. Si esto es un problema, usa la prueba invertida «v<u» en lo anterior.
Sin embargo, esta sencillez se complica bastante más si el usuario quiere tramar usando varios niveles de color. La prueba de concepto de esto se elaboró primero en los ejemplos de la página Tramado ordenado posterizado antes de incorporarse a las funciones del núcleo de IM. Ahora que tenemos una imagen de umbral fusionada, lo siguiente que necesitamos es convertir la imagen anterior en un mapa de umbral XML que IM pueda leer directamente y que el operador «[-ordered-dither](https://imagemagick.org/command-line-options/#ordered-dither)» pueda usar. Para ello necesitamos generar la salida de nuestra imagen como números que representen los 9 niveles de gris que contiene. Esto se hace mejor usando el formato de imagen NetPBM o PBMplus, con un ajuste de profundidad mediante el software de procesamiento de imágenes «NetPbm». Este paquete suele venir instalado de serie en Linux, así que la mayoría de la gente ya lo tendrá, o podrá instalarlo desde su distribución de software habitual. El número de «pnmdepth» es de nuevo el número de niveles de gris que contiene la imagen de umbral.
  magick dmap_hlines.png pgm:- | pnmdepth 9 | pnmnoraw > dmap_hlines.pgm

[IM Text]

Todos los números (salvo el identificador mágico de imagen «P2») de lo anterior son los números necesarios para generar el «mapa de umbral» apropiado, que puedes añadir a tu archivo «thresholds.xml» personal. Por ejemplo, aquí tienes la entrada de mapa de umbral resultante creada a partir de lo anterior.

[IM Output]

Y aquí tienes un ejemplo de uso de este mapa de umbral.

  magick shadow.png  -channel A  -ordered-dither hlines   shadow_hlines.gif

[IM Output] [IM Output]

Y así es como puedes generar un mapa de umbral complejo a partir de una progresión de imágenes.

Tramado con patrones de símbolos

Ahora bien, aunque para la mayoría de las operaciones de tramado puedes usar un único mapa de umbral o imagen de umbral en lugar de un conjunto de patrones multiimagen, eso no significa que los mapas multiimagen no tengan sus propios usos. Puedes usar un conjunto de imágenes de consulta para teselar varias zonas a la vez, en lugar de una por una. Por ejemplo, escalando una imagen sencilla y luego sustituyendo cada píxel de una imagen por un símbolo concreto. Por ejemplo, aquí tomo la diminuta imagen de «ojos» [IM Output] y sustituyo cada píxel por distintos símbolos, para producir un patrón así por cada píxel de la imagen original.

  montage dpat_symbols.gif   -geometry +5+0 \
          -tile x1 -background none -mattecolor blue  -frame 3 \
          dpat_syms_images.gif
  magick eyes.gif -alpha off -colorspace sRGB -grayscale Average \
          -alpha off -scale 1600% -negate  \
          dpat_symbols.gif -virtual-pixel tile -fx 'u[floor(15.9999*u)+1]' \
          eyes_syms.gif

[IM Output]
[IM Output]

El montage se usa para expandir la imagen GIF multiimagen de modo que puedas ver su contenido, sin que esté «animada». Puedes ajustar qué método de intensidad de «[-grayscale](https://imagemagick.org/command-line-options/#grayscale)» quieres usar, desde el normal «Rec709Luminance» a un «Rec709Luma» más oscuro, o usar un «average» de un espacio de color «sRGB» no lineal o de un espacio «RGB» lineal. Incluso puedes ajustar el escalado «[-gamma](https://imagemagick.org/command-line-options/#gamma)» de los valores para obtener la mejor distribución de colores. Hay muchas posibilidades, y lo que es bueno depende más de la disposición de tus símbolos que del método concreto elegido. La clave de lo anterior es asegurarte de algún modo de que cada color de la imagen de entrada produzca un símbolo único, y eso puede ser muy difícil de lograr. Este ejemplo puede usarse para crear guías de punto de cruz o de tejido que los aficionados puedan seguir, generando una obra a mayor escala a partir de imágenes de ordenador más pequeñas. Puedes usar esta técnica para teselar imágenes en escala de grises con un conjunto de imágenes de color en mosaico. El resultado se parece un poco a los mapas de paisaje que se ven en muchos juegos de guerra antiguos de ordenador.

  montage dpat_map.gif   -geometry +5+0 -tile x1  -background none  \
          dpat_map_images.gif
  magick -seed 100 \
          -size 200x200 plasma:'gray(50%)-gray(50%)' -blur 0x15 \
          -channel G -auto-level +channel -set colorspace sRGB \
          dpat_map.gif -virtual-pixel tile  -fx 'u[floor(5.999*u.g)+1]' \
          map.gif

[IM Output]
[IM Output]

Ten en cuenta que tuve que asegurarme de que IM considerara la imagen en escala de grises como si ya estuviera en el espacio de color sRGB final (como lo están las imágenes de mosaico), aunque en realidad son datos RGB lineales los que se usan para las consultas de índice FX. Sin esto, el «mapa» resultante se inclina hacia paisajes boscosos, con pocas probabilidades de zonas de agua. Como puedes ver, se puede usar cualquier conjunto de imágenes para los mosaicos; las imágenes ni siquiera necesitan alinearse entre sí, ni ser del mismo tamaño de mosaico. Por supuesto, si los mosaicos son del mismo tamaño y están estrechamente relacionados entre sí, como en el caso de los 3 mosaicos azules de «mar», el patrón en mosaico puede «fluir» de una zona teselada a otra. Sustituyendo el mosaico por imágenes de números, también puedes generar una especie de guía de pintar por números. Sin embargo, puede que se necesite algún procesamiento extra para delimitar las distintas zonas. Esto se deja como ejercicio; envíame tus soluciones y podrás aparecer en los ejemplos de IM como autor de esta técnica.


Tramado ordenado: notas varias y posibilidades futuras

En construcción

Tramado ordenado con un número reducido de colores.

Al usar un número reducido de colores para una imagen pequeña, un tramado pseudoaleatorio como el tramado por corrección de error de curva de Hilbert de IM, o incluso un tramado por corrección de error de Floyd-Steinberg más sencillo (consulta Tramado por corrección de error más arriba), produce un resultado de aspecto horrible. Lo ideal sería usar un tramado ordenado con imágenes de pocos colores y tipo icono pequeño para producir un resultado de aspecto mucho mejor. Sin embargo, por el momento el tramado ordenado en IM solo puede usar tablas de color «fijas» generadas matemáticamente, y no simplemente una colección de los «mejores» colores.

Tramado ordenado con un mapa de colores cualesquiera

Existe algún algoritmo que permite usar un conjunto de colores concretos para el tramado ordenado. Básicamente, añadiendo los «pseudocolores» que un algoritmo de tramado ordenado puede generar (lo que podría implicar un tramado de tres colores) al mapa de color dado, para «completarlo». Luego puedes «asignar» los píxeles individuales de una imagen a este «mapa de color ampliado». A partir de esa asignación inicial a un pseudocolor concreto, el color real puede elegirse del mapa de umbral que genera ese pseudocolor y, así, tramar de forma ordenada las zonas de ese color y, por tanto, toda la imagen a un conjunto de colores dado. Por mi experiencia con los iconos, y ahora con las animaciones GIF, sin duda me gustaría ver implementado un tramado ordenado de cualquier color, pero todavía no he encontrado una referencia práctica sobre cómo hacer tramados ordenados con un conjunto fijo de colores.