Usa mogrify per ridimensionare i file di grandi dimensioni ignorando quelli piccoli


10

Sto eseguendo il seguente comando:

mogrify -resize '400x400>' *.png

Notare il ">". Presumibilmente ignorerà i file più piccoli, ma sebbene non li ridimensioni, li modifica (la data di modifica e la dimensione del file vengono cambiate).

C'è un modo per renderlo in realtà solo lasciare i file più piccoli da solo? Vorrei evitare diverse migliaia di operazioni di scrittura non necessarie.

Risposte:


15

Penso che mogrifyriscriva sistematicamente il file, quindi la tua unica speranza è di filtrare prima l'elenco, come suggerito da jippie . Ecco come potresti farlo (non testato): stampare un elenco di file di immagine con un'indicazione delle dimensioni, mantenere solo i nomi le cui dimensioni associate sono all'interno dell'intervallo ed elaborare tale elenco.

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

Spiegazione dello script:

  • Per ogni file, stampare una linea con la larghezza, uno spazio, l'altezza, uno spazio e il nome del file. A seconda della versione di identify, \naggiungere una nuova riga finale potrebbe essere necessario (ImageMagick 6.6.0) o superfluo ma innocuo (GraphicsMagick 1.1.11).
  • ( awk) Su ciascuna riga, se larghezza ( $1) e altezza ( $2) corrispondono alle condizioni richieste, quindi:
    • Rimuovi tutto il testo fino al secondo carattere spazio. Questo spoglia la larghezza e l'altezza.
    • Stampa ciò che resta della linea, che è il nome del file.
  • Sostituisci newline con caratteri null.
  • Chiama xargs -0per eseguire il mogrifycomando sui nomi dei file. (Non possiamo usare plain xargsperché non può gestire input contenenti spazi bianchi o \'".)

I nomi dei file possono contenere qualsiasi carattere tranne le nuove righe.


puoi spiegare quella sceneggiatura? In particolare la parte "sub". Sta stampando i nomi dei file senza uno spazio o inserendo una nuova riga. mogrify: impossibile aprire il file `22 553.png308 400 0134 2.png '@ error / png.c / ReadPNGImage / 2951. Non ho idea da dove provenga quel "308 400". Dovrei menzionare che i file hanno spazi nei loro nomi Grazie.
Mike,

Sto diventando mogrify: impossibile aprire il file `340 271 22 553.png308 400 0134 2.png '@ error / png.c / ReadPNGImage / 2951. Ho eseguito il comando utilizzando 200x200 su due file di esempio. Vedo che 308x400 ha le dimensioni di uno dei file
Mike,

2
@ Mike Ah, capito. Alcune versioni di identifyinseriscono automaticamente una nuova riga dopo ogni record, altre ne devono avere esplicitamente una. Aggiungi \nalla fine dell'argomento a -format(vedi la mia modifica).
Gilles 'SO- smetti di essere malvagio'

8

Ho affrontato lo stesso problema che hai descritto. Ecco la mia soluzione:

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

L'ho provato su diverse immagini JPEG su una macchina virtualizzata CentOS 6.5. Lo script ha solo ridimensionato e compresso le immagini la cui larghezza o altezza era maggiore di 640 pixel. Questo lo ha fatto funzionare per immagini con dimensioni come 800 x 600 (orizzontale, ridimensionandolo a 640 x 480) e dimensioni come 600 x 800 (verticale, ridimensionandolo a 480 x 640).

PS: una nota sul 400x400parametro: mogrifyelaborerà il file anche se le sue dimensioni sono uguali o inferiori a 400x400, ma ridimensionerà solo se le sue dimensioni sono maggiori di 400x400. Ecco perché i tempi e le dimensioni di modifica dei file sono cambiati (nel mio caso, ho mogrifyreso questi file ancora più grandi di quanto non fossero).


5

È inoltre possibile utilizzare l' fxoperatore per filtrare le immagini in base all'altezza / larghezza, ad es

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

verrà emesso 1se l'immagine è più grande di 400x400e 0se è uguale o più piccola di 400x400...


Supponendo che i nomi dei file sani (nessuna nuova riga / spazio / scheda ecc.) Si possano usare identifyper stampare i nomi delle immagini preceduti da uno dei due , 1:oppure 0:elaborare l'output eliminando le righe che iniziano con 0:e rimuovendo il comando 1:sul resto delle righe in modo che rimangano solo i nomi dei file, uno per riga, quindi reindirizzare l'elenco a mogrify ... @-(è stata aggiunta la @sintassiimagemagick v6.5.2 ):

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

Altrimenti, con findte puoi stampare solo i file con dimensioni> 400x400 e quindi reindirizzare il risultato a xargs+ mogrify(è meno efficiente in quanto esegue una shell per ogni file ma dovrebbe funzionare con tutti i tipi di nomi di file):

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 sei un zshutente vedi anche questa risposta .


3

Che ne dici di usare identifica per trovare la dimensione della tua immagine e decidere da un piccolo script se vuoi modificarla o meno:

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

Non dovrebbe essere troppo difficile modificare il formato di output per l'uso in un semplice script.


Considerando le mie capacità limitate e il fatto che le dimensioni delle immagini siano così irregolari, ho bisogno di un metodo più semplice. Preferirei elaborarli tutti con mogrify.
Mike,

0

Uso tale 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);
?>

Ridimensiona tutte le immagini nella directory corrente più grande di 3000 su un bordo.

Esegui comando: php scale.phpORphp scale.php 2000


0

Ecco la mia opinione su di esso, incorporando idee da @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

(Ne avevo bisogno perché il mio processore batch preferito Phatch non funziona con Ubuntu 16.04.)


0

Le mie funzioni per ridimensionare e ottimizzare

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"
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.