Gunakan mogrify untuk mengubah ukuran file besar sambil mengabaikan yang kecil


10

Saya menjalankan perintah berikut:

mogrify -resize '400x400>' *.png

Perhatikan ">". Seharusnya itu akan mengabaikan file yang lebih kecil, tetapi meskipun tidak mengubah ukurannya, itu mengeditnya (tanggal modifikasi dan ukuran file berubah).

Apakah ada cara untuk membuatnya hanya meninggalkan file yang lebih kecil saja? Saya ingin menghindari beberapa ribu operasi penulisan yang tidak perlu.

Jawaban:


15

Saya pikir mogrifysecara sistematis menulis ulang file, jadi satu-satunya harapan Anda adalah menyaring daftar terlebih dahulu, seperti yang disarankan oleh jippie . Inilah cara Anda dapat melakukannya (belum diuji): mencetak daftar file gambar dengan indikasi ukuran, hanya menyimpan nama-nama yang ukurannya terkait dalam jangkauan, dan memproses daftar itu.

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

Penjelasan skrip:

  • Untuk setiap file, cetak garis dengan lebar, spasi, tinggi, spasi, dan nama file. Tergantung pada versi Anda identify, \nuntuk menambahkan baris baru akhir mungkin diperlukan (ImageMagick 6.6.0) atau berlebihan tetapi tidak berbahaya (GraphicsMagick 1.1.11).
  • ( awk) Pada setiap baris, jika lebar ( $1) dan tinggi ( $2) sesuai dengan persyaratan yang disyaratkan, maka:
    • Hapus semua teks hingga karakter spasi kedua. Ini mengupas lebar dan tinggi.
    • Cetak sisa baris, yang merupakan nama file.
  • Ganti baris baru dengan karakter nol.
  • Panggilan xargs -0untuk mengeksekusi mogrifyperintah pada nama file. (Kami tidak dapat menggunakan polos xargskarena tidak dapat menangani input yang mengandung spasi atau \'".)

Nama file dapat berisi karakter apa pun kecuali baris baru.


dapatkah kamu menjelaskan skrip itu? Khususnya bagian "sub". Mencetak nama file tanpa spasi atau menyisipkan baris baru. mogrify: tidak dapat membuka file `22 553.png308 400 0134 2.png '@ error / png.c / ReadPNGImage / 2951. Saya tidak tahu dari mana "308 400" itu berasal. Saya harus menyebutkan file memiliki spasi dalam nama mereka. Terima kasih.
Mike

Saya mendapatkan mogrify: tidak dapat membuka file `340 271 22 553.png308 400 0134 2.png '@ error / png.c / ReadPNGImage / 2951. Saya menjalankan perintah menggunakan 200x200 pada dua file sampel. Saya melihat bahwa 308x400 adalah ukuran salah satu file
Mike

2
@ Mike Ah, mengerti. Beberapa versi identifysecara otomatis menempatkan baris baru setelah setiap catatan, yang lain harus memiliki satu secara eksplisit. Tambahkan \ndi akhir argumen ke -format(lihat edit saya).
Gilles 'SANGAT berhenti menjadi jahat'

8

Saya menghadapi masalah yang sama seperti yang Anda gambarkan. Inilah solusi saya:

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

Saya mengujinya pada beberapa gambar JPEG pada mesin CentOS 6.5 yang tervirtualisasi. Script hanya mengubah ukuran dan mengompresi gambar yang lebar atau tingginya lebih besar dari 640 piksel. Ini membuatnya berfungsi untuk gambar dengan dimensi seperti 800 x 600 (lanskap, mengubah ukurannya menjadi 640 x 480) dan dimensi seperti 600 x 800 (potret, mengubah ukurannya menjadi 480 x 640).

PS: Catatan pada 400x400parameter: mogrifyakan memproses file walaupun dimensinya sama atau lebih kecil dari 400x400, tetapi akan mengubah ukuran hanya jika dimensinya lebih besar dari 400x400. Itu sebabnya waktu dan ukuran modifikasi file berubah (dalam kasus saya, mogrifymenjadikan file ini lebih besar dari sebelumnya).


5

Anda juga dapat menggunakan fxoperator untuk memfilter gambar berdasarkan tinggi / lebar mis

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

akan menampilkan 1jika gambar lebih besar dari 400x400dan 0jika sama atau lebih kecil dari 400x400...


Mengasumsikan nama file waras (tidak ada baris baru / spasi / tab dll) yang dapat Anda gunakan identifyuntuk mencetak nama gambar yang didahului oleh salah satu 1:atau 0:, memproses output menghapus garis yang dimulai dengan 0:dan menghapus baris 1:di sisa baris sehingga hanya nama file yang tersisa, satu per baris, lalu pipa daftar itu ke mogrify ... @-( @sintaks ditambahkan imagemagick v6.5.2):

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

Jika tidak, findAnda hanya dapat mencetak file dengan ukuran> 400x400 dan kemudian mengirimkan hasilnya ke xargs+ mogrify(itu kurang efisien karena menjalankan shell untuk setiap file tetapi harus bekerja dengan semua jenis nama 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'

Jika Anda seorang zshpengguna, lihat juga jawaban ini .


3

Bagaimana kalau menggunakan identifikasi untuk menemukan ukuran gambar Anda dan memutuskan dari skrip kecil apakah Anda ingin mengeditnya atau tidak:

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

Seharusnya tidak terlalu sulit untuk mengedit format output untuk digunakan dalam skrip sederhana.


Mempertimbangkan kemampuan saya yang terbatas dan fakta bahwa ukuran gambar sangat tidak teratur, saya memerlukan metode yang lebih sederhana. Saya lebih suka memproses semuanya dengan mogrif.
Mike

0

Saya menggunakan skrip PHP seperti itu, ia menggunakan 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);
?>

Ini skala semua gambar dalam direktori saat ini lebih besar dari 3000 di beberapa sisi.

Jalankan perintah: php scale.phpATAUphp scale.php 2000


0

Inilah pendapat saya, memasukkan ide-ide dari @ArionKrause dan @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

(Saya membutuhkan ini karena prosesor batch favorit saya Phatch tidak berfungsi dengan Ubuntu 16.04.)


0

Fungsi saya untuk mengubah ukuran dan mengoptimalkan

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"
}
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.