Quiero cambiar DPI con ImageMagick sin cambiar el tamaño de byte real de los datos de imagen

45

En GIMP hay una manera muy simple de hacer lo que quiero. Solo tengo instalado el cuadro de diálogo alemán, pero intentaré traducirlo. Estoy hablando de ir Picture -> PrintingSizey luego ajustar los valores X-Resolutiony Y-Resolutionque yo conozco como los llamados valores DPI. También puede elegir el formato que por defecto es Pixel/Inch. (En alemán el diálogo es Bild -> Druckgrößey allí X-Auflösungy Y-Auflösung)

Ok, los valores a menudo son 72por defecto. Cuando los cambio a, por ejemplo, 300esto tiene el efecto de que la imagen permanece igual en la computadora, pero si la imprimo, será más pequeña si la miras, pero todos los detalles siguen ahí, solo que más pequeños -> tiene una resolución más alta en el papel impreso (pero de menor tamaño ... lo cual está bien para mí).

A menudo hago eso cuando estoy trabajando con LaTeX, o para ser exactos con el comando pdflatexen una máquina Ubuntu reciente. Cuando estoy haciendo el proceso anterior con GIMP manualmente, todo funciona bien. Las imágenes aparecerán más pequeñas en el PDF resultante pero con alta calidad de impresión.

Lo que intento hacer es automatizar el proceso de entrar en GIMP y ajustar los valores de DPI. Como se sabe que ImageMagick es excelente y lo usé para muchas otras tareas, traté de lograr mi objetivo con esta herramienta. Pero simplemente no hace lo que quiero.

Después de probar muchas cosas, creo que este es realmente el comando que debería ser mi amigo:

convert input.png -density 300 output.png

Esto debería establecer el DPI en 300, ya que puedo leer en cualquier parte de la web. Parece funcionar. Pero cuando reviso el archivo, permanece igual (EDITAR: que es lo que espero, como se explicó anteriormente).

file input.png output.png
     input.png: PNG image data, 611 x 453, 8-bit grayscale, non-interlaced
    output.png: PNG image data, 611 x 453, 8-bit grayscale, non-interlaced

Cuando uso este comando, parece que hizo lo que quería:

identify -verbose output.png | grep 300
    Resolution: 300x300
    PNG:pHYs                 : x_res=300, y_res=300, units=0

Curiosamente, viene la misma salida para lo input.pngque me confunde ... ¿entonces estos podrían ser los parámetros incorrectos para mirar?

Pero cuando ahora renderizo mi TeX con pdflatexla imagen todavía es grande y borrosa. Además, cuando abro la imagen con GIMP nuevamente, los valores de DPI se establecen en 72lugar de 300. Así que en realidad no hubo ningún efecto.

Ahora cuál es el problema aquí. ¿Me estoy poniendo algo completamente mal? No puedo estar tan equivocado ya que todo funciona bien con GIMP.

Gracias por cualquier ayuda en esto. También estoy abierto a otras soluciones automatizadas que se realizan fácilmente en un sistema Linux.

Boris Däppen
fuente
usuario1694803: debe recordar volver a la respuesta de Martin Wilson y 'votarla' también (haga clic en el pequeño ^icono a la izquierda de su respuesta), no solo 'aceptarla' tan pronto como tenga suficiente reputación personal (creo que necesita +15) ...
Kurt Pfeifle

Respuestas:

76

Especifique las unidades: parece que recuerdo haber tenido un problema cuando omití esta opción (aunque DPI debería ser el predeterminado), por ejemplo:

convert -units PixelsPerInch input.png -density 300 output.png

¿Sabe qué campos de datos incrustados utiliza GIMP para leer la resolución? ¿Tiene los suyos propios que anulan los estándares utilizados por ImageMagick? Por ejemplo, Photoshop usa Photoshop:XResolutiony, Photoshop:YResolutionpor lo tanto, debe configurarlos para que Photoshop reconozca una configuración de densidad (ImageMagick no puede hacer esto; usamos ExifTool).

Martin Wilson
fuente
2
Necesitaba poner -density 300antes input.png. Estaba convirtiendo archivos PDF. Gracias de cualquier manera.
akostadinov
Para la conversión de PNG a TIFF que necesitaba usar -set units PixelsPerInch -density 300, simple -unitsno funcionó independientemente del orden de las opciones.
Andrey
5

Tenga en cuenta que puede usar Exiftool para leer resoluciones. Por ejemplo, Exiftool '-*resolution*' c.jpgpodría mostrar

Unidad de resolución: pulgadas X Resolución: 300 Y Resolución: 300

Exiftool también puede establecer parámetros, pero como se indica en la página de Image::ExifTool::TagNamesmanual, Exiftool no puede escribir las etiquetas adicionales XResolution e YResolution.

No sé si ImageMagick tiene opciones de cambio de resolución, pero me sorprendería si no lo hace. Además, es sencillo escribir scripts GIMP para automatizar tareas como esta, y también es posible cambiar resoluciones con pequeños programas. Por ejemplo, el siguiente es un programa en C (compilable mediante gcc setRes.c -O3 -Wall -o setRes) que lee los primeros bytes de un archivo jpeg, cambia las resoluciones a 300 y las reescribe. El programa como se muestra usa constantes para máquinas little-endian, como x86. Si se ejecuta en una máquina big-endian, debería terminar con un mensaje como Error: xyz may be not a .jpg file, incluso si xyz es un archivo jpeg. Tenga en cuenta que no he probado las imágenes resultantes a través de pdflatex; probablemente le resulte útil publicar una pregunta en el tex SE .

/* jiw -- 24 Sep 2012 -- Re: set resolution in a jpg -- Offered without
warranty under GPL v3 terms as at http://www.gnu.org/licenses/gpl.html
*/
#include <stdlib.h>
#include <stdio.h>
void errorExit(char *msg, char *par, int fe) {
  fprintf (stderr, "\n%3d Error: %s %s\n", fe, msg, par);
  exit (1);
}
// Note, hex constants are byte-reversed on little vs big endian machines
enum { JF=0x464a, IF=0x4649, L300=0x2c01, B300=0x012c, NEWRES=L300};
int main(int argc, char *argv[]) {
  FILE *fi;
  short int buf[9];
  int r, L=sizeof buf;
  if (argc<2) errorExit(argv[0], "requires a .jpg file name", 0);
  fi = fopen(argv[1], "r+b");
  if(!fi) errorExit("open failed for", argv[1], ferror(fi));
  r = fread(buf, 1, L, fi);
  if (r != L) errorExit("read failed for", argv[1], ferror(fi));
  if (buf[3] != JF || buf[4] != IF) // Check JFIF signature
    errorExit(argv[1], "may be not a .jpg file", 0);
  buf[7] = buf[8] = NEWRES;
  fseek(fi, 0, SEEK_SET);
  r = fwrite(buf, 1, L, fi);
  if (r != L) errorExit("write failed for", argv[1], ferror(fi));
  return 0;
}
James Waldby - jwpat7
fuente
1
Esto no me ayuda mucho, ya que estoy tratando con PNG y no tengo mucha idea de JPG o incluso C. Eso es un conocimiento "profundo" para que pueda ser útil. Quizás alguien más pueda usarlo.
Boris Däppen
¡Sí, debería haber prestado más atención a la pregunta! Al releerlo, JPG no se menciona, PNG claramente lo es.
James Waldby - jwpat7
Sí, soy otra persona y puedo usarlo: abrí mi archivo .jpg en un editor hexadecimal y edité el noveno y el undécimo byte para la densidad vertical y horizontal. Por así decirlo, "ejecuté" su código manualmente.
u_Ltd.
2

No pude descubrir cómo convencer a convertir para que solo agregue los metadatos y no vuelva a codificar mi mapa de bits [monocromo]; estaba expandiendo el archivo> 50%.

Descubrí que pngcrush (no es una herramienta ImageMagick) también puede agregar los metadatos de densidad. Esta línea de comando lo marca 600 ppp y permite otras optimizaciones, lo que redujo el tamaño del archivo en ~ 10%:

pngcrush -res 600 in.png out.png
Charles Boling
fuente
-1

"Quiero cambiar DPI con Imagemagick sin cambiar el tamaño de byte real de los datos de imagen".

¡Esto es completamente imposible!

Porque:

     more "Dots per Inch" 
<==> more pixels per area 
<==> more total pixels per image 
<==> more total bytes per image

Tampoco parece entender qué es DPI en realidad:

  1. Es un valor completamente abstracto que obtiene un valor práctico solo en el contexto de conocer también el tamaño absoluto de la impresión o representación en pantalla o monitor:
    • Puede 'imprimir' la misma imagen de 72x72 píxeles en un cuadrado de 1 pulgada de ancho: la impresión tendrá una resolución de 72dpi.
    • También puede 'imprimirlo' en un cuadrado de 1/4 de pulgada de ancho: entonces la impresión tendrá una resolución de 288dpi.
    • ( Nota: si lo 'imprime' en 288dpiun cuadrado de 1 pulgada, ya no es la misma imagen: habrá sufrido una extrapolación a través del controlador de la impresora o algún otro mecanismo de filtrado, y se habrá convertido en una imagen de 288x288 píxeles en lugar de una imagen de 72x72 píxeles ... )
  2. Ambas impresiones tendrán la misma información de imagen: la imagen de 288 ppp no ​​tendrá repentinamente más.

Si desea imprimir la imagen original de 72x72 píxeles como un cuadrado de 1 pulgada de ancho, pero a la vez 288dpi, tendrá que reescalar la imagen (en este caso, ampliarla). Por cada 1 píxel en el original, necesitará 4 píxeles de la nueva imagen mejorada. Ahora hay diferentes algoritmos que se pueden usar para calcular qué valores de color deben tener estos 4 píxeles (3 de ellos nuevos píxeles):

  • podría darles lo mismo que el píxel original (que es un algoritmo muy "en bruto",
  • o puede hacer un promedio del valor de color del píxel original con los valores de color de los píxeles vecinos.

En cualquier caso, está creando una imagen más grande que consta de 288 filas de píxeles que tienen 288 píxeles de alto cada uno (288x288 píxeles).

Lo que Gimp hace por usted cuando pasa por "Imagen -> Tamaño de impresión": simplifica el proceso de volver a calcular los cambios necesarios en los tamaños absolutos de píxeles, lo que lo hace más fácil de usar. Para este propósito...

  • ... primero le pregunta sobre el DPI porque una impresora determinada no puede cambiar su resolución de impresión de forma arbitraria (algunos pueden ofrecer no solo una, sino incluso 2 o 3 resoluciones diferentes). Por lo tanto, le pregunta a qué resolución desea imprimir. Esa es la primera información.
  • ... entonces también pide la segunda pieza de información: en la que el tamaño (en cm, mmo inch) la impresión debe aparecer en papel.

De acuerdo con estas dos piezas de información, Gimp calcula el número total de píxeles que debe usar (extrapolar a partir del número original de píxeles) para llenar el espacio solicitado en la resolución solicitada.

Sin embargo, ampliar una imagen ráster haciendo que contenga más píxeles no le agrega información real, y solo le agrega 'calidad', lo cual es ficticio. Puede parecer mejor para el ojo humano si su algoritmo de escalamiento es 'bueno'. Y se verá feo, si solo duplica, triplica o cuadruplica los píxeles existentes, como hacen algunos algoritmos simples.

Para imágenes ráster,
la configuración de DPI solo es relevante en el contexto de impresión o visualización . Debido a que las impresoras o monitores han dado resoluciones fijas. Por lo tanto, es información que solo ...

  • ... un controlador de impresora o
  • ... una aplicación de procesamiento de imágenes que admite la impresión

necesito saber.

Y la documentación de ImageMagick está totalmente de acuerdo conmigo:

-density width
-density widthxheight
Establezca la resolución horizontal y vertical de una imagen para renderizar en dispositivos.


Sin embargo, para imágenes vectoriales o formatos de archivo (como PDF o PostScript), la configuración de DPI es extremadamente importante en el contexto de rasterizarlos . Un DPI más alto transferirá más información de la imagen al formato ráster y, por lo tanto, conservará más detalles de la calidad original real. Al convertir una imagen vectorial de un tamaño dado enmm,cmoinchen una trama con un DPI más alto, se traducirá directamente en un mayor número de píxeles totales en la imagen.

Además, ImageMagick no admite 'impresión' como tal. En cambio, ImageMagick solo ...

  • ... convierte archivos de un formato ráster dado a otros formatos ráster;
  • ... o reduce o aumenta las imágenes ráster;
  • ... o cambia los valores de color de acuerdo con un algoritmo específico;
  • ... o recorta imágenes, las superpone, las invierte, las refleja;
  • ...Y qué no....

... pero para imprimir las imágenes manipuladas, debe usar un programa diferente.

Algunos formatos de imagen (TIFF, PNG, ...) admiten almacenar internamente una configuración de DPI en sus metadatos.

Pero esto no es más que un atributo 'pista' que no altera la imagen ráster subyacente. Esa es la razón por la que hiciste este descubrimiento:

"Cuando reviso el archivo, permanece igual".

Esta 'sugerencia' posiblemente puede ser evaluada automáticamente por controladores de impresora o por programas de creación de páginas como LaTeX. En ausencia de tales 'sugerencias' de DPI (o si de alguna manera no se presentan de la manera que LaTeX espera que lo hagan), LaTeX aún debería poder ordenar que renderice cualquier imagen dada en una página de la manera que uno espera a - solo necesita un código LaTeX más explícito alrededor de la imagen.

Algunos otros formatos de imagen (JPEG (?), BMP, ...) ni siquiera admiten almacenar una sugerencia de DPI en sus metadatos internos.

Por lo tanto, Gimp solo admite lo que ves que está haciendo con "Imagen -> Tamaño de impresión" porque quiere imprimir una imagen. Con ImageMagick no puede imprimir.

Siga haciendo lo que quiera hacer con Gimp cuando imprima. No tiene sentido con ImageMagick.

Consulte también este fragmento adicional de documentación de MI , que explica el mismo tema en diferentes palabras.


Entonces, lo que queda es esto:

  • Si 'manipula' su imagen con Gimp y luego incrusta el resultado en LaTeX, la página se verá como la esperaba.
  • Si 'manipula' su imagen con ImageMagick y luego incrusta el resultado en LaTeX, la página no se verá como esperaba.

Proporcione lo siguiente para resolver el problema anterior:

  • la versión exacta de su instalación de ImageMagick (salida completa de convert -versiony convert -list configure);
  • (un enlace a una) imagen de muestra original;
  • (un enlace a) la misma imagen manipulada por Gimp;
  • (un enlace a) la misma imagen manipulada por ImageMagick.

De esta manera podemos ayudar a resolver el problema.

Pero tenga en cuenta: este es un problema diferente de lo que pregunta su tema / título actual: "Quiero cambiar DPI con Imagemagick sin cambiar el tamaño de byte real de los datos de imagen"


Actualizar

Como todavía no está claro para algunos lectores lo que noté anteriormente, aquí hay un intento más ...

Cualquier cosa que se indique como 'Resolución' o 'Densidad' dentro de un archivo de imagen, es un atributo de metadatos . No tiene influencia sobre el número de píxeles reales descritos por el archivo y es completamente irrelevante a este respecto. Es solo una pista que un dispositivo de impresión o renderizado o una aplicación puede seguir o no al imprimir, renderizar o mostrar la imagen.

Para este propósito, es solo un número almacenado en el archivo de imagen. Estos números le indican a los dispositivos de salida, como impresoras, y muestran cuántos puntos (o píxeles) por pulgada debe mostrarse la imagen. Para formatos vectoriales como PostScript, PDF, MWF y SVG, le dice a la escala de píxeles que dibuje las coordenadas del mundo real utilizadas por la imagen.

Un ejemplo, donde una aplicación NO respeta el valor de resolución observado por ImageMagick dentro de los metadatos de la imagen , es Adobe Photoshop. Photoshop almacena sus sugerencias sobre la resolución de impresión o visualización deseada en un perfil propietario llamado 8bim . ImageMagick no toca este perfil, incluso cuando se le pide que escriba un cambio de resolución en los metadatos de un archivo de imagen. Photoshop, por otro lado, ignorará todas las sugerencias de resolución almacenadas por ImageMagick en el campo de metadatos estándar que se define para este propósito tan pronto como vea su propio perfil 8bim .

El OP debería haber elegido el título:

  • 'Quiero cambiar DPI (sugerencia de resolución de metadatos) con ImageMagick sin cambiar el número real de píxeles en la imagen'

para evitar todos los malentendidos ...

Kurt Pfeifle
fuente
1
"Cuando reviso el archivo, permanece igual". ESTO ES LO QUE QUIERO. NO DIGO EN EL TEXTO QUE ESTO ME SORPRENDA. POR FAVOR LEA MI PREGUNTA OTRA VEZ ... LENTAMENTE ... ARGL
Boris Däppen
66
"¡Esto es completamente imposible!" No, es posible ... es solo que la imagen se encoge cuando se imprime. ¿Qué he explicado muy detallado en mi pregunta
Boris Däppen
55
De qué estás hablando. He explicado mi caso de uso en detalle dentro de la pregunta. Si responde preguntas solo por título, no será de ayuda para nadie aquí.
Boris Däppen
44
Su defecto fatal fue la suposición inicial: "más píxeles por área <==> más píxeles totales por imagen" Eso solo es cierto si el área es constante. Este no es el caso.
Leo Izen el
1
Sí. DPI solo tiene sentido si se procesa en dispositivos. También es un campo que puede almacenarse en un archivo de imagen para cuando esta resolución sea relevante. La pregunta claramente preguntaba cómo cambiar este campo sin cambiar los datos de píxeles.
Leo Izen