Desejo alterar o DPI com o ImageMagick sem alterar o tamanho real dos bytes dos dados da imagem

45

No GIMP, existe uma maneira muito simples de fazer o que eu quero. Eu só tenho o diálogo em alemão instalado, mas vou tentar traduzi-lo. Eu estou falando sobre ir Picture -> PrintingSizee depois ajustar os Valores X-Resolutione Y-Resolutionque são conhecidos por mim como chamados valores de DPI. Você também pode escolher o formato que, por padrão, é Pixel/Inch. (Em alemão, a caixa de diálogo é Bild -> Druckgrößee existe X-Auflösunge Y-Auflösung)

Ok, os valores geralmente existem 72por padrão. Quando eu as altero para, por exemplo, 300isso faz com que a imagem permaneça a mesma no computador, mas se eu imprimi-la, será menor se você olhar para ela, mas todos os detalhes ainda estão lá, apenas menores -> ela tem uma resolução mais alta no papel impresso (mas tamanho menor ... o que é bom para mim).

Costumo fazer isso quando estou trabalhando com o LaTeX, ou para ser exato com o comando pdflatexem uma recente máquina Ubuntu. Quando estou fazendo o processo acima com o GIMP manualmente, tudo funciona bem. As imagens aparecerão menores no PDF resultante, mas com alta qualidade de impressão.

O que estou tentando fazer é automatizar o processo de entrada no GIMP e ajustar os valores de DPI. Como o ImageMagick é conhecido por ser excelente e eu o usei para muitas outras tarefas, tentei alcançar meu objetivo com esta ferramenta. Mas isso simplesmente não faz o que eu quero.

Depois de tentar muitas coisas, acho que esse é realmente o comando que deve ser meu amigo:

convert input.png -density 300 output.png

Isso deve definir o DPI para 300, como posso ler em qualquer lugar da web. Parece funcionar. Mas quando eu verifico o arquivo, ele permanece o mesmo (EDIT: o que eu espero, como explicado acima).

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

Quando eu uso esse comando, parece que ele fez o que eu queria:

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

Engraçado o suficiente, a mesma saída vem para o input.pngque me confunde ... então, esses podem ser os parâmetros errados para assistir?

Mas quando agora renderizo meu TeX com pdflatexa imagem ainda é grande e embaçada. Além disso, quando abro a imagem com o GIMP novamente, os valores de DPI são definidos como em 72vez de 300. Portanto, na verdade não houve nenhum efeito.

Agora, qual é o problema aqui. Estou entendendo algo completamente errado? Não posso estar errado, pois tudo funciona bem com o GIMP.

Obrigado por qualquer ajuda nisso. Também estou aberto a outras soluções automatizadas que são facilmente executadas em um sistema Linux.

Boris Däppen
fonte
user1694803: Lembre-se de retornar à resposta de Martin Wilson e "votá-la" também (clique no pequeno ^ícone à esquerda da resposta), não apenas "aceite" assim que tiver reputação pessoal suficiente (acho que você precisa +15) ...
Kurt Pfeifle

Respostas:

76

Especifique as unidades - lembro-me de ter um problema ao omitir essa opção (embora o DPI deva ser o padrão), por exemplo:

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

Você sabe quais campos de dados incorporados o GIMP usa para ler a resolução - ele possui os seus próprios que substituem os padrões usados ​​pelo ImageMagick? Por exemplo, o Photoshop usa Photoshop:XResolutione, Photoshop:YResolutionportanto, você deve defini-las para que o Photoshop reconheça uma configuração de densidade (o ImageMagick não pode fazer isso - usamos o ExifTool).

Martin Wilson
fonte
2
Eu precisava colocar -density 300antes input.png. Eu estava convertendo PDFs. Obrigado mesmo assim.
Akostadinov
Para a conversão PNG para TIFF que eu precisava usar -set units PixelsPerInch -density 300, o simples -unitsnão funcionou, independentemente da ordem das opções.
Andrey
5

Observe que você pode usar o Exiftool para ler as resoluções. Por exemplo, Exiftool '-*resolution*' c.jpgpode mostrar

Unidade de resolução: polegadas X Resolução: 300 Y Resolução: 300

O Exiftool também pode definir parâmetros, mas conforme observado na página de manual Image::ExifTool::TagNames, as Tags Extra XResolution e YResolution não podem ser gravadas pelo Exiftool.

Não sei se o ImageMagick tem opções de alteração de resolução, mas ficaria surpreso se não tiver. Além disso, é fácil escrever scripts do GIMP para automatizar tarefas como essa e também é possível alterar as resoluções com pequenos programas. Por exemplo, a seguir está um programa C (via compilável gcc setRes.c -O3 -Wall -o setRes) que lê os primeiros bytes de um arquivo jpeg, altera as resoluções para 300 e as reescreve. O programa, como mostrado, usa constantes para máquinas little-endian, como x86. Se executado em uma máquina big-endian, ele deve terminar com uma mensagem como Error: xyz may be not a .jpg file, mesmo se xyz for um arquivo jpeg. Observe que não testei as imagens resultantes via pdflatex; você provavelmente acha que vale a pena postar uma pergunta no 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
fonte
1
Isso não me ajuda muito, já que estou lidando com PNG e não tenho muita noção de JPG ou mesmo C. Isso é conhecimento "profundo" para que eu seja útil. Talvez alguém possa usá-lo.
Boris Däppen
Sim, eu deveria ter prestado mais atenção à pergunta! Relendo, JPG não é mencionado, PNG é claramente.
precisa saber é o seguinte
Sim, sou outra pessoa e posso usá-lo: abri meu arquivo .jpg em um editor hexadecimal e editei o nono e o décimo primeiro byte para a densidade vertical e horizontal. Por assim dizer, eu "executei" seu código manualmente.
u_Ltd.
2

Não consegui descobrir como convencer a conversão a adicionar apenas os metadados e não recodificar o meu bitmap [monocromático]; estava expandindo o arquivo> 50%.

Descobri que pngcrush (não uma ferramenta ImageMagick) também pode adicionar os metadados de densidade. Essa linha de comando marca 600dpi e permite outras otimizações, que reduziram o tamanho do arquivo em ~ 10%:

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

"Quero alterar o DPI com o Imagemagick sem alterar o tamanho real dos bytes dos dados da imagem."

Isso é completamente impossível!

Porque:

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

Além disso, você parece não entender o que é DPI na realidade:

  1. É um valor completamente abstrato que obtém valor prático apenas no contexto de saber também o tamanho absoluto da impressão ou renderização na tela ou no monitor:
    • Você pode 'imprimir' a mesma imagem de 72x72 pixels em um quadrado de 1 polegada de largura: a impressão terá uma resolução de 72dpi.
    • Você também pode 'imprimi-lo' em um quadrado de 1/4 de polegada de largura: a impressão terá uma resolução de 288dpi.
    • ( Nota: se você o imprimir 288dpiem um quadrado de 2,5 cm, não será mais a mesma imagem: será extrapolada pelo driver da impressora ou por algum outro mecanismo de filtragem e se tornará uma imagem de 288x288 pixels em vez de uma imagem de 72x72 pixels ... )
  2. Ambas as impressões terão as mesmas informações de imagem - a imagem de 288 dpi não terá mais de repente.

Se você deseja imprimir a imagem original de 72 x 72 pixels como um quadrado de 1 polegada de largura, mas em 288dpi, precisará redimensionar a imagem (nesse caso, ampliá-la). Para cada 1 pixel no original, você precisará de 4 pixels da nova imagem aprimorada. Agora, existem algoritmos diferentes que podem ser usados ​​para calcular quais valores de cores esses 4 pixels (3 deles são novos):

  • você pode dar a eles o mesmo que o pixel original (que é um algoritmo muito "bruto",
  • ou você pode fazer uma média do valor da cor do pixel original com os valores da cor dos pixels vizinhos.

De qualquer forma, você está criando uma imagem maior que consiste em 288 linhas de pixels, cada uma com 288 pixels de altura (288x288 pixels).

O que o Gimp faz por você quando você acessa "Imagem -> Tamanho da impressão": simplifica o processo de recalcular as alterações necessárias nos tamanhos absolutos de pixels, tornando-o mais fácil de usar. Para esse fim ...

  • ... pergunta primeiro sobre o DPI porque uma determinada impressora não pode alterar sua resolução de impressão arbitrariamente (algumas podem oferecer não apenas uma, mas talvez até 2 ou 3 resoluções diferentes). Por isso, pergunta em qual resolução você deseja imprimir. Essa é a primeira informação.
  • ... então ele também pede para o segundo pedaço de informação: em que tamanho (em cm, mmou inch) a impressão deve aparecer no papel.

De acordo com essas duas informações, o Gimp calcula o número total de pixels que ele deve usar (extrapolar do número original de pixels) para preencher o espaço solicitado na resolução solicitada.

No entanto, aumentar a escala de uma imagem raster, fazendo com que ela contenha mais pixels, não adiciona informações reais e apenas adiciona "qualidade" a ela, que é fictícia. Pode parecer melhor para o olho humano se o seu algoritmo de aumento de escala for "bom". E ficará feio se você dobrar, triplicar ou quadruplicar os pixels existentes, como fazem alguns algoritmos simples.

Para imagens rasterizadas,
a configuração de DPI é relevante apenas no contexto de impressão ou exibição . Como as impressoras ou monitores deram, resoluções fixas. Portanto, são informações que apenas ...

  • ... um driver de impressora ou
  • ... um aplicativo de processamento de imagem que suporta impressão

precisa saber.

E a documentação do ImageMagick está totalmente de acordo comigo:

-density width
-density widthxheight
Defina a resolução horizontal e vertical de uma imagem para renderização em dispositivos.

Para imagens vetoriais ou formatos de arquivo
(como PDF ou PostScript), a configuração de DPI é extremamente importante no contexto de rasterização . Um DPI mais alto transferirá mais informações da imagem para o formato raster e, portanto, preservará mais detalhes da qualidade original real. Quando a conversão de uma imagem de vector de um determinado tamanho emmm,cmouinchem quadrícula com um DPI mais elevado irá traduzir-se directamente em um maior número total de pixels na imagem.

Além disso, o ImageMagick não suporta 'impressão' como tal. Em vez disso, apenas o ImageMagick ...

  • ... converte arquivos de um determinado formato raster para outros formatos raster;
  • ... ou reduz ou amplia imagens raster;
  • ... ou altera os valores das cores de acordo com um algoritmo específico;
  • ... ou recorta imagens, sobrepõe-as, inverte-as, espelha-as;
  • ...e o que não....

... mas para imprimir as imagens manipuladas, você precisa usar um programa diferente.

Alguns formatos de imagem (TIFF, PNG, ...) suportam o armazenamento interno de uma configuração de DPI em seus metadados.

Mas isso não passa de um atributo 'dica' que não altera a imagem raster subjacente. Essa é a razão pela qual você fez essa descoberta:

"Quando eu checo o arquivo, ele permanece o mesmo."

Essa 'dica' pode ser avaliada automaticamente por drivers de impressora ou por programas de criação de páginas como o LaTeX. Na ausência de tais 'dicas' de DPI (ou se de alguma forma elas não se apresentarem da maneira que o LaTeX espera que sejam), o LaTeX ainda deve poder receber a ordem de renderizar qualquer imagem em uma página da maneira que se espera. para - ele precisa de um código LaTeX mais explícito ao redor da imagem!

Alguns outros formatos de imagem (JPEG (?), BMP, ...) nem mesmo suportam o armazenamento de uma dica de DPI em seus metadados internos.

Portanto, o Gimp suporta apenas o que você vê fazendo "Imagem -> Tamanho da impressão", porque deseja imprimir uma imagem. Com o ImageMagick, você não pode imprimir.

Continue fazendo o que você quer fazer com o Gimp ao imprimir. Não faz sentido com o ImageMagick.

Consulte também este trecho de documentação adicional de IM , que explica o mesmo tópico em palavras diferentes.


Então, o que resta é o seguinte:

  • Se você 'manipula' sua imagem com o Gimp e, em seguida, incorpora o resultado no LaTeX, a página parece que você espera.
  • Se você 'manipular' sua imagem com o ImageMagick e incorporar o resultado no LaTeX, a página não será como o esperado.

Forneça o seguinte para resolver o problema acima:

  • a versão exata da sua instalação do ImageMagick (saída completa de convert -versione convert -list configure);
  • (um link para uma) imagem de amostra original;
  • (um link para) mesma imagem manipulada pelo Gimp;
  • (um link para) mesma imagem manipulada pelo ImageMagick.

Desta forma, podemos ajudar a resolver o problema.

Mas observe: este é um problema diferente do que o assunto / título atual pergunta: "Quero alterar o DPI com o Imagemagick sem alterar o tamanho real dos bytes dos dados da imagem"


Atualizar

Como ainda não está claro para alguns leitores o que observei acima, aqui está mais uma tentativa ...

Tudo o que é anotado como 'Resolução' ou 'Densidade' dentro de um arquivo de imagem é um atributo de metadados . Não tem influência sobre o número de pixels reais descrito pelo arquivo e é completamente irrelevante a esse respeito. É apenas uma dica de que um dispositivo de impressão ou renderização ou um aplicativo pode ou não seguir ao imprimir, renderizar ou exibir a imagem.

Para esse fim, são apenas alguns números armazenados no arquivo de imagem. Esses números informam aos dispositivos de saída, como impressoras, e mostram quantos pontos (ou pixels) por polegada a imagem deve ser exibida. Para formatos vetoriais como PostScript, PDF, MWF e SVG, ele diz à escala de pixels para desenhar quaisquer coordenadas do mundo real usadas pela imagem.

Um exemplo, onde o valor da resolução observado pelo ImageMagick dentro dos metadados da imagem NÃO é respeitado por um aplicativo é o Adobe Photoshop. O Photoshop armazena suas dicas sobre a resolução de impressão ou exibição desejada em um perfil proprietário chamado 8bim . O ImageMagick não toca nesse perfil, mesmo quando solicitado a gravar uma alteração de resolução nos metadados de um arquivo de imagem. Por outro lado, o Photoshop ignorará todas as dicas de resolução armazenadas pelo ImageMagick no campo de metadados padrão que é definido para esse fim assim que ele vir seu próprio perfil 8bim .

O PO deveria ter escolhido o cabeçalho:

  • "Quero alterar o DPI (dica de resolução de metadados) com o ImageMagick sem alterar o número real de pixels na imagem"

a fim de evitar todos os mal-entendidos ...

Kurt Pfeifle
fonte
1
"Quando eu checo o arquivo, ele permanece o mesmo." É ISSO QUE EU QUERO. NÃO DIGO NO TEXTO QUE ISSO ME SURPREENDE. POR FAVOR, LEIA MINHA PERGUNTA NOVAMENTE ... LENTAMENTE ... ARGL
Boris Däppen
6
"Isso é completamente impossível!" Não, é possível ... é apenas que a imagem diminui quando impressa. Que eu expliquei muito detalhado na minha pergunta
Boris Dappen
5
Sobre o que é mesmo que você está falando. Eu expliquei meu caso de uso em detalhes dentro da pergunta. Se você responder perguntas apenas pelo título, não ajudará ninguém aqui.
Boris Däppen 26/09/12
4
Sua falha fatal foi a suposição inicial: "mais pixels por área <==> mais pixels totais por imagem" Isso só é verdade se a área for constante. Este não é o caso.
Leo Izen
1
Sim. O DPI só é significativo se renderizado nos dispositivos. Também é um campo que pode ser armazenado em um arquivo de imagem para quando esta resolução for relevante. A pergunta claramente perguntou como alterar esse campo sem alterar os dados de pixel.
Leo Izen 24/01