Use mogrify para cambiar el tamaño de los archivos grandes mientras ignora los pequeños


10

Estoy ejecutando el siguiente comando:

mogrify -resize '400x400>' *.png

Observe el ">". Supuestamente ignorará los archivos más pequeños, pero aunque no los redimensiona, los edita (la fecha de modificación y el tamaño del archivo cambian).

¿Hay alguna manera de hacerlo realmente solo dejando los archivos más pequeños solos? Me gustaría evitar varios miles de operaciones de escritura innecesarias.

Respuestas:


15

Creo que mogrifyreescribe sistemáticamente el archivo, por lo que su única esperanza es filtrar la lista primero, como lo sugiere jippie . Así es como puede hacerlo (sin probar): imprima una lista de archivos de imagen con una indicación de tamaño, mantenga solo los nombres cuyo tamaño asociado esté dentro del rango y procese esa lista.

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

Explicación del guión:

  • Para cada archivo, imprima una línea con el ancho, un espacio, la altura, un espacio y el nombre del archivo. Dependiendo de su versión de identify, \nagregar una nueva línea final puede ser necesario (ImageMagick 6.6.0) o superfluo pero inofensivo (GraphicsMagick 1.1.11).
  • ( awk) En cada línea, si el ancho ( $1) y la altura ( $2) coinciden con las condiciones requeridas, entonces:
    • Elimine todo el texto hasta el segundo carácter de espacio. Esto elimina el ancho y la altura.
    • Imprima lo que queda de la línea, que es el nombre del archivo.
  • Reemplazar nuevas líneas por caracteres nulos.
  • Llame xargs -0para ejecutar el mogrifycomando en los nombres de archivo. (No podemos usar plain xargsporque no puede manejar entradas que contienen espacios en blanco o \'").

Los nombres de los archivos pueden contener cualquier carácter, excepto las nuevas líneas.


¿Puedes explicar ese guión? Específicamente la parte "sub". Está imprimiendo los nombres de archivo sin espacio o insertando una nueva línea. mogrify: no se puede abrir el archivo `22 553.png308 400 0134 2.png '@ error / png.c / ReadPNGImage / 2951. No tengo idea de dónde viene ese "308 400". Debo mencionar que los archivos tienen espacios en sus nombres Gracias.
Mike

Me estoy volviendo loco: no puedo abrir el archivo `340 271 22 553.png308 400 0134 2.png '@ error / png.c / ReadPNGImage / 2951. Ejecuté el comando usando 200x200 en dos archivos de muestra. Veo que 308x400 es del tamaño de uno de los archivos
Mike

2
@ Mike Ah, lo tengo. Algunas versiones de identifyponen automáticamente una nueva línea después de cada registro, otras necesitan tener una explícitamente. Agregue \nal final del argumento a -format(vea mi edición).
Gilles 'SO- deja de ser malvado'

8

Me enfrenté al mismo problema que describiste. Aquí está mi solución:

#!/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

Lo probé en varias imágenes JPEG en una máquina virtualizada CentOS 6.5. El script solo redimensionó y comprimió las imágenes cuyo ancho o alto era mayor que 640 píxeles. Esto lo hizo funcionar para imágenes con dimensiones como 800 x 600 (horizontal, redimensionándolo a 640 x 480) y dimensiones como 600 x 800 (vertical, redimensionándolo a 480 x 640).

PD: Una nota sobre el 400x400parámetro: mogrifyprocesará el archivo incluso si sus dimensiones son iguales o menores que 400x400, pero cambiará de tamaño solo si sus dimensiones son mayores que 400x400. Es por eso que el tiempo y el tamaño de modificación de los archivos cambian (en mi caso, mogrifyestos archivos fueron aún más grandes de lo que eran).


5

También puede usar el fxoperador para filtrar imágenes en función de la altura / anchura, p. Ej.

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

saldrá 1si la imagen es más grande que 400x400y 0si es igual o más pequeña que 400x400...


Suponiendo nombres de archivos sanos (sin líneas nuevas / espacios / pestañas, etc.) que podría usar identifypara imprimir nombres de imágenes precedidos por cualquiera de los dos , 1:o 0:procese la salida eliminando líneas que comienzan con 0:y eliminando el inicio 1:del resto de líneas para que solo queden los nombres de archivo. por línea, luego canalice esa lista a mogrify ... @-( se agregó la @sintaxisimagemagick v6.5.2 ):

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

De lo contrario, findpodría imprimir solo los archivos con un tamaño> 400x400 y luego canalizar el resultado a xargs+ mogrify(es menos eficiente ya que ejecuta un shell para cada archivo pero debería funcionar con todo tipo de nombres de archivo):

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'

Si eres zshusuario, mira también esta respuesta .


3

¿Qué tal si usas Identificar para encontrar el tamaño de tu imagen y decidir desde un pequeño script si quieres editarlo o no?

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

No debería ser demasiado difícil editar el formato de salida para usarlo en un script simple.


Teniendo en cuenta mis habilidades limitadas y el hecho de que los tamaños de las imágenes son tan irregulares, necesito un método más simple. Prefiero procesarlos a todos con mogrify.
Mike

0

Yo uso tal script PHP, usa 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);
?>

Escala todas las imágenes en el directorio actual más grande que 3000 en algún borde.

Ejecutar comando: php scale.phpOphp scale.php 2000


0

Aquí está mi opinión al respecto, incorporando ideas de @ArionKrause y @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

(Necesitaba esto porque mi procesador por lotes favorito Phatch no funciona con Ubuntu 16.04).


0

Mis funciones para redimensionar y optimizar

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"
}
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.