Verwenden Sie mogrify, um die Größe großer Dateien zu ändern, während Sie kleine ignorieren

10

Ich führe den folgenden Befehl aus:

mogrify -resize '400x400>' *.png

Beachten Sie das ">". Angeblich werden kleinere Dateien ignoriert, aber obwohl die Größe nicht geändert wird, werden sie bearbeitet (Änderungsdatum und Dateigröße werden geändert).

Gibt es eine Möglichkeit, die kleineren Dateien in Ruhe zu lassen? Ich möchte mehrere tausend unnötige Schreibvorgänge vermeiden.

Mike
quelle

Antworten:

15

Ich denke, mogrifydie Datei wird systematisch neu geschrieben, daher besteht Ihre einzige Hoffnung darin, zuerst die Liste zu filtern, wie von jippie vorgeschlagen . So können Sie es machen (ungetestet): Drucken Sie eine Liste von Bilddateien mit einer Größenangabe aus, behalten Sie nur die Namen bei, deren zugehörige Größe innerhalb des Bereichs liegt, und verarbeiten Sie diese Liste.

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

Skripterklärung:

  • Drucken Sie für jede Datei eine Zeile mit der Breite, einem Leerzeichen, der Höhe, einem Leerzeichen und dem Dateinamen. Abhängig von Ihrer Version von identifykann das \nHinzufügen einer endgültigen neuen Zeile entweder erforderlich (ImageMagick 6.6.0) oder überflüssig, aber harmlos (GraphicsMagick 1.1.11) sein.
  • ( awk) Wenn in jeder Zeile die Breite ( $1) und Höhe ( $2) den erforderlichen Bedingungen entsprechen, gilt Folgendes:
    • Entfernen Sie den gesamten Text bis zum zweiten Leerzeichen. Dadurch werden Breite und Höhe entfernt.
    • Drucken Sie, was von der Zeile übrig bleibt, nämlich den Dateinamen.
  • Ersetzen Sie Zeilenumbrüche durch Nullzeichen.
  • Rufen Sie xargs -0auf, um den mogrifyBefehl für die Dateinamen auszuführen . (Wir können plain nicht verwenden, xargsda es keine Eingaben mit Leerzeichen oder verarbeiten kann \'".)

Die Dateinamen können beliebige Zeichen außer Zeilenumbrüchen enthalten.

Gilles 'SO - hör auf böse zu sein'
quelle
Kannst du das Skript erklären? Speziell der "Sub" -Teil. Es werden die Dateinamen ohne Leerzeichen gedruckt oder eine neue Zeile eingefügt. mogrify: Datei `22 553.png308 400 0134 2.png '@ error / png.c / ReadPNGImage / 2951 kann nicht geöffnet werden. Ich habe keine Ahnung, woher diese "308 400" kommt. Ich sollte erwähnen, dass die Dateien Leerzeichen in ihren Namen haben. Danke.
Mike
Ich erhalte mogrify: Datei `340 271 22 553.png308 400 0134 2.png '@ error / png.c / ReadPNGImage / 2951 kann nicht geöffnet werden. Ich habe den Befehl mit 200x200 für zwei Beispieldateien ausgeführt. Ich sehe, dass 308x400 die Größe einer der Dateien ist
Mike
2
@ Mike Ah, verstanden. Einige Versionen von identifysetzen nach jedem Datensatz automatisch eine neue Zeile, andere müssen explizit eine haben. Fügen Sie \nam Ende des Arguments hinzu -format(siehe meine Bearbeitung).
Gilles 'SO - hör auf böse zu sein'
8

Ich hatte das gleiche Problem, das Sie beschrieben haben. Hier ist meine Lösung:

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

Ich habe es auf mehreren JPEG-Bildern auf einem virtualisierten CentOS 6.5-Computer getestet. Das Skript hat nur die Größe der Bilder geändert und komprimiert, deren Breite oder Höhe größer als 640 Pixel war. Dadurch funktionierte es für Bilder mit Abmessungen wie 800 x 600 (Querformat, Größenänderung auf 640 x 480) und Abmessungen wie 600 x 800 (Hochformat, Größenänderung auf 480 x 640).

PS: Ein Hinweis zum 400x400Parameter: mogrifyverarbeitet die Datei auch dann, wenn ihre Abmessungen gleich oder kleiner als 400 x 400 sind, ändert jedoch nur die Größe , wenn ihre Abmessungen größer als 400 x 400 sind. Aus diesem Grund werden die Änderungszeit und -größe der Dateien geändert (in meinem Fall wurden mogrifydiese Dateien noch größer als sie waren).

Arion Krause
quelle
5

Sie können den fxOperator auch verwenden , um Bilder basierend auf Höhe / Breite zu filtern, z

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

wird ausgegeben, 1wenn das Bild größer als 400x400und 0wenn es gleich oder kleiner als 400x400...


Unter der Annahme vernünftiger Dateinamen (keine Zeilenumbrüche / Leerzeichen / Tabulatoren usw.) können Sie Bildnamen identifydrucken, denen entweder vorangestellt ist, 1:oder 0:die Ausgabe verarbeiten, 0:indem Sie Zeilen löschen, die mit den Zeilen beginnen und die führenden 1:Zeilen entfernen , sodass nur die Dateinamen übrig bleiben pro Zeile, dann leiten Sie diese Liste an mogrify ... @-(die @Syntax wurde hinzugefügt in imagemagick v6.5.2):

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

Andernfalls findkönnten Sie mit nur die Dateien mit einer Größe> 400x400 drucken und dann das Ergebnis an xargs+ weiterleiten mogrify(es ist weniger effizient, da für jede Datei eine Shell ausgeführt wird, aber es sollte mit allen Arten von Dateinamen funktionieren):

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'

Wenn Sie ein zshBenutzer sind, sehen Sie auch diese Antwort .

don_crissti
quelle
3

Wie wäre es mit Identifizieren, um die Größe Ihres Bildes zu ermitteln und anhand eines kleinen Skripts zu entscheiden, ob Sie es bearbeiten möchten oder nicht:

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

Es sollte nicht zu schwierig sein, das Ausgabeformat für die Verwendung in einem einfachen Skript zu bearbeiten.

Jippie
quelle
Angesichts meiner begrenzten Fähigkeiten und der Tatsache, dass die Bildgrößen so unregelmäßig sind, brauche ich eine einfachere Methode. Ich würde sie lieber alle mit mogrify verarbeiten.
Mike
0

Ich benutze ein solches PHP-Skript, es benutzt 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);
?>

Es skaliert alle Bilder im aktuellen Verzeichnis, die an einer Kante größer als 3000 sind.

Befehl php scale.phpausführen : ODERphp scale.php 2000

Andrew Barhatov
quelle
0

Hier ist meine Sichtweise, die Ideen von @ArionKrause und @don_crissti enthält:

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

(Ich brauchte das, weil mein Lieblings-Batch-Prozessor Phatch mit Ubuntu 16.04 nicht funktioniert.)

Bovender
quelle
0

Meine Funktionen zu ändern und zu optimieren

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"
}
Srghma
quelle