Use mogrify para redimensionar arquivos grandes e ignorar arquivos pequenos


10

Estou executando o seguinte comando:

mogrify -resize '400x400>' *.png

Observe o ">". Supostamente ele ignorará arquivos menores, mas, embora não os redimensione, os edita (a data de modificação e o tamanho do arquivo são alterados).

Existe uma maneira de fazê-lo realmente apenas deixar os arquivos menores em paz? Eu gostaria de evitar vários milhares de operações de gravação desnecessárias.

Respostas:


15

Acho que mogrifyreescreve sistematicamente o arquivo, então sua única esperança é filtrar a lista primeiro, conforme sugerido por jippie . Eis como você pode fazer isso (não testado): imprima uma lista de arquivos de imagem com uma indicação de tamanho, mantenha apenas os nomes cujo tamanho associado esteja dentro do alcance e processe essa lista.

identify -format '%w %h %i\n' ./*.png |
awk '$1 > 400 || $2 > 400 {sub(/^[^ ]* [^ ]* /, ""); print}' |
tr '\n' '\0' |
xargs -0 mogrify -resize '400x400'

Explicação do script:

  • Para cada arquivo, imprima uma linha com a largura, um espaço, a altura, um espaço e o nome do arquivo. Dependendo da sua versão identify, a \nadição de uma nova linha final pode ser necessária (ImageMagick 6.6.0) ou supérflua, mas inofensiva (GraphicsMagick 1.1.11).
  • ( awk) Em cada linha, se a largura ( $1) e a altura ( $2) corresponderem às condições necessárias, então:
    • Remova todo o texto até o segundo caractere de espaço. Isso retira a largura e a altura.
    • Imprima o que resta da linha, que é o nome do arquivo.
  • Substitua as novas linhas por caracteres nulos.
  • Ligue xargs -0para executar o mogrifycomando nos nomes dos arquivos. (Não podemos usar plain xargsporque não pode lidar com entradas que contenham espaços em branco ou \'".)

Os nomes dos arquivos podem conter qualquer caractere, exceto novas linhas.


você pode explicar esse script? Especificamente a parte "sub". É imprimir os nomes dos arquivos sem espaço ou inserir uma nova linha. mogrify: não foi possível abrir o arquivo `22 553.png308 400 0134 2.png '@ error / png.c / ReadPNGImage / 2951. Não faço ideia de onde vem esse "308 400". Devo mencionar que os arquivos têm espaços em seus nomes. Obrigado.
1818 Mike

Estou recebendo o mogrify: não é possível abrir o arquivo `340 271 22 553.png308 400 0134 2.png '@ error / png.c / ReadPNGImage / 2951. Eu executei o comando usando 200x200 em dois arquivos de exemplo. Vejo que 308x400 é o tamanho de um dos arquivos
Mike

2
@ Mike Ah, entendi. Algumas versões de identifycolocar automaticamente uma nova linha após cada registro, outras precisam ter uma explicitamente. Adicione \nno final do argumento a -format(veja minha edição).
Gilles 'SO- stop be evil'

8

Eu enfrentei o mesmo problema que você descreveu. Aqui está a minha solução:

#!/bin/bash
files=*.jpg
minimumWidth=640
minimumHeight=640

for f in $files
do
    imageWidth=$(identify -format "%w" "$f")
    imageHeight=$(identify -format "%h" "$f")

    if [ "$imageWidth" -gt "$minimumWidth" ] || [ "$imageHeight" -gt "$minimumHeight" ]; then
        mogrify -resize ''"$minimumWidth"x"$minimumHeight"'' $f
    fi
done

Testei-o em várias imagens JPEG em uma máquina virtualizada do CentOS 6.5. O script apenas redimensionou e compactou as imagens cuja largura ou altura era maior que 640 pixels. Isso o fez trabalhar com imagens com dimensões como 800 x 600 (paisagem, redimensionando para 640 x 480) e dimensões como 600 x 800 (retrato, redimensionando para 480 x 640).

PS: Uma observação no 400x400parâmetro: mogrifyprocessará o arquivo mesmo que suas dimensões sejam iguais ou menores que 400x400, mas será redimensionado apenas se suas dimensões forem maiores que 400x400. É por isso que o tempo e o tamanho da modificação dos arquivos são alterados (no meu caso, mogrifyos tornamos ainda maiores do que eram).


5

Você também pode usar o fxoperador para filtrar imagens com base na altura / largura, por exemplo

identify -format '%[fx:(h>400 && w>400)]\n' image.png

será exibida 1se a imagem for maior que 400x400e 0se for igual ou menor que 400x400...


Assumindo nomes de arquivos sãos (sem novas linhas / espaços / guias, etc.), você pode usar identifypara imprimir nomes de imagens precedidos por qualquer um , 1:ou 0:processar a saída excluindo linhas que começam com 0:e removendo a liderança 1:no restante das linhas, para que apenas os nomes dos arquivos permaneçam. por linha, em seguida, canalize essa lista para mogrify ... @-(a @sintaxe foi adicionada imagemagick v6.5.2):

identify -format '%[fx:(h>400 && w>400)]:%i\n' ./*.png | \
sed '/^1:/!d;//s///' | mogrify -resize '400x400' -- @-

Caso contrário, findvocê poderá imprimir apenas os arquivos com tamanho> 400x400 e canalizar o resultado para xargs+ mogrify(é menos eficiente, pois executa um shell para cada arquivo, mas deve funcionar com todos os tipos de nomes de arquivos):

find . -maxdepth 1 -type f -name '*.png' -exec sh -c \
'identify -format "%[fx:(h>400 && w>400)]\n" "$0" | grep -q 1' {} \; -print0 \
| xargs -0 mogrify -resize '400x400'

Se você é um zshusuário, veja também esta resposta .


3

Que tal usar o identificador para encontrar o tamanho da sua imagem e decidir a partir de um pequeno script se você deseja editá-lo ou não:

identify -format "width=%w heigth=%h" bootchart.png 
width=3853 heigth=10092

Não deve ser muito difícil editar o formato de saída para usar em um script simples.


Considerando minhas habilidades limitadas e o fato de os tamanhos das imagens serem muito irregulares, preciso de um método mais simples. Prefiro processá-los todos com mogrify.
1818 Mike

0

Eu uso esse script PHP, ele usa o ImageMagick:

<?php
$dir = ".";
$exts = array('jpg', 'jpeg', 'png', 'gif');
$max_size = is_numeric($argv[1]) ? $argv[1] : 3000;
$morgify = "mogrify -verbose -scale \"${max_size}x${max_size}>\" -quality 85";
$identify = "identify -format \"%wx%h\"";

$dh = opendir($dir);
while (($file = readdir($dh)) !== false) {
    $path = "$dir/$file";
    // skip no images
    $dot = strrpos($file, '.');
    $ext = strtolower(substr($file, $dot + 1));
    if (!in_array($ext, $exts)) continue;
    // large size?
    $size = exec("$identify \"$path\"");
    list($width, $height) = explode('x', trim($size));
    if (max($width, $height) > $max_size) {
        // scale!
        print "scale $file ${width}x${height}";
        exec("$morgify \"$path\"");
        print "\n";
    }
}
closedir($dh);
?>

Ele dimensiona todas as imagens no diretório atual maiores que 3000 em alguma borda.

Executar comando: php scale.phpORphp scale.php 2000


0

Aqui está minha opinião, incorporando idéias de @ArionKrause e @don_crissti:

#!/bin/bash
# adapted from http://unix.stackexchange.com/a/157594/110635
# and http://unix.stackexchange.com/a/220619/110635
W=1024
H=768
SIZE_TEST="%[fx:(h>$H && w>$W)]"'\n'

for f in $*; do
  if [ $(identify -format "$SIZE_TEST" "$f") = 1 ]; then
    echo "Resize: $f"
    mogrify -resize ''"$W"x"$H"'' "$f"
  else
    echo "Do not resize: $f"
  fi
done

(Eu precisava disso porque meu processador em lote favorito Phatch não funciona com o Ubuntu 16.04.)


0

Minhas funções para redimensionar e otimizar

resize_and_optimize_images () {
  resize_images 700 $PWD
  optimize_images 85 $PWD
}

resize_images () {
  max="$1"
  dir="$2"

  echo "Resizing dir $dir, max size - $max"

  shopt -s globstar

  for f in $dir/**/*.jpg $dir/**/*.jpeg $dir/**/*.png ; do
    echo "Checking $f"
    s=`identify -format "%w" $f`

    if [ $s -gt $max ]; then
      echo "Resizing..."
      mogrify -verbose -resize $max $f
    fi
    echo
  done

  echo "Done resizing dir $dir"
}

optimize_images () {
  quality="$1"
  dir="$2"

  echo "Optimizing dir $dir, quality - $quality"

  docker run -it --rm --name optimize_images_foo \
    -v $dir:/usr/src/app \
    -w /usr/src/app ruby:2.4-stretch bash -c \
    "gem install image_optim image_optim_pack && \
    (curl -L \"http://static.jonof.id.au/dl/kenutils/pngout-20150319-linux.tar.gz\" | tar -xz -C /usr/bin --strip-components 2 --wildcards \"*/x86_64/pngout\") && \
    image_optim --verbose --allow-lossy --jpegoptim-allow-lossy true --jpegoptim-max-quality $quality --pngquant-allow-lossy true --pngquant-quality 0..$quality -r ."

  echo "Done optimizing dir $dir"
}
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.