Sử dụng mogrify để thay đổi kích thước các tệp lớn trong khi bỏ qua các tệp nhỏ


10

Tôi đang chạy lệnh sau:

mogrify -resize '400x400>' *.png

Lưu ý ">". Giả sử nó sẽ bỏ qua các tệp nhỏ hơn, nhưng mặc dù nó không thay đổi kích thước chúng, nó sẽ chỉnh sửa chúng (ngày sửa đổi và kích thước tệp được thay đổi).

Có cách nào để làm cho nó thực sự chỉ để các tập tin nhỏ hơn một mình? Tôi muốn tránh hàng ngàn thao tác ghi không cần thiết.

Câu trả lời:


15

Tôi nghĩ rằng mogrifyviết lại tập tin một cách có hệ thống, vì vậy hy vọng duy nhất của bạn là lọc danh sách trước, như được đề xuất bởi jippie . Đây là cách bạn có thể làm điều đó (chưa được kiểm tra): in ra danh sách các tệp hình ảnh có chỉ thị kích thước, chỉ giữ lại các tên có kích thước được liên kết trong phạm vi và xử lý danh sách đó.

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

Kịch bản giải thích:

  • Đối với mỗi tệp, in một dòng có chiều rộng, khoảng trắng, chiều cao, khoảng trắng và tên tệp. Tùy thuộc vào phiên bản của bạn identify, việc \nthêm một dòng mới cuối cùng có thể là cần thiết (ImageMagick 6.6.0) hoặc không cần thiết nhưng vô hại (GraphicsMagick 1.1.11).
  • ( awk) Trên mỗi dòng, nếu chiều rộng ( $1) và chiều cao ( $2) khớp với các điều kiện bắt buộc, thì:
    • Xóa tất cả văn bản lên đến ký tự khoảng trắng thứ hai. Điều này dải chiều rộng và chiều cao.
    • In những gì còn lại của dòng, đó là tên tệp.
  • Thay thế dòng mới bằng ký tự null.
  • Gọi xargs -0để thực hiện mogrifylệnh trên tên tệp. (Chúng tôi không thể sử dụng đơn giản xargsvì nó không thể xử lý đầu vào có chứa khoảng trắng hoặc \'".)

Tên tệp có thể chứa bất kỳ ký tự nào ngoại trừ dòng mới.


bạn có thể giải thích kịch bản đó? Cụ thể là phần "phụ". Đó là in tên tệp mà không có dấu cách hoặc chèn một dòng mới. mogrify: không thể mở tệp `22 553.png308 400 0134 2.png '@ error / png.c / ReadPNGImage / 2951. Tôi không biết "308 400" đó đến từ đâu. Tôi nên đề cập đến các tập tin có không gian trong tên của họ Cảm ơn bạn.
Mike

Tôi đang nhận được sự nhầm lẫn: không thể mở tệp `340 271 22 553.png308 400 0134 2.png '@ error / png.c / ReadPNGImage / 2951. Tôi đã chạy lệnh bằng 200x200 trên hai tệp mẫu. Tôi thấy 308x400 là kích thước của một trong các tệp
Mike

2
@Mike Ah, hiểu rồi. Một số phiên bản identifytự động đặt một dòng mới sau mỗi bản ghi, những phiên bản khác cần phải có một bản rõ ràng. Thêm \nvào cuối đối số để -format(xem chỉnh sửa của tôi).
Gilles 'SO- ngừng trở nên xấu xa'

8

Tôi đã đối mặt với cùng một vấn đề bạn mô tả. Đây là giải pháp của tôi:

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

Tôi đã thử nghiệm nó trên một số hình ảnh JPEG trên máy CentOS 6.5 ảo hóa. Tập lệnh chỉ thay đổi kích thước và nén hình ảnh có chiều rộng hoặc chiều cao lớn hơn 640 pixel. Điều này làm cho nó hoạt động đối với các hình ảnh có kích thước như 800 x 600 (phong cảnh, thay đổi kích thước thành 640 x 480) và kích thước như 600 x 800 (dọc, thay đổi kích thước thành 480 x 640).

PS: Một lưu ý về 400x400tham số: mogrifysẽ xử lý tệp ngay cả khi kích thước của nó bằng hoặc nhỏ hơn 400x400, nhưng sẽ chỉ thay đổi kích thước nếu kích thước của nó lớn hơn 400x400. Đó là lý do tại sao thời gian sửa đổi và kích thước của các tệp bị thay đổi (trong trường hợp của tôi, mogrifylàm cho các tệp này thậm chí còn lớn hơn so với trước đây).


5

Bạn cũng có thể sử dụng fxtoán tử để lọc hình ảnh dựa trên chiều cao / chiều rộng, vd

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

sẽ xuất ra 1nếu hình ảnh lớn hơn 400x4000nếu nó bằng hoặc nhỏ hơn 400x400...


Giả sử tên tệp sane (không có dòng mới / dấu cách / tab, v.v.) bạn có thể sử dụng identifyđể in tên hình ảnh đi trước 1:hoặc 0:, xử lý các dòng xóa đầu ra bắt đầu 0:và xóa đầu dòng 1:trên phần còn lại của dòng để chỉ còn lại tên tệp, một trên mỗi dòng, sau đó đặt danh sách đó vào mogrify ... @-( @cú pháp đã được thêm vào imagemagick v6.5.2):

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

Mặt khác, với findbạn chỉ có thể in các tệp có kích thước> 400x400 và sau đó chuyển kết quả thành xargs+ mogrify(nó kém hiệu quả hơn vì nó chạy vỏ cho mỗi tệp nhưng nó sẽ hoạt động với tất cả các loại tên tệp):

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'

Nếu bạn là zshngười dùng cũng thấy câu trả lời này .


3

Còn về cách sử dụng nhận dạng để tìm kích thước hình ảnh của bạn và quyết định từ một tập lệnh nhỏ nếu bạn muốn chỉnh sửa nó hay không:

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

Không nên quá khó để chỉnh sửa định dạng đầu ra để sử dụng trong một tập lệnh đơn giản.


Xem xét các kỹ năng hạn chế của tôi và thực tế kích thước của hình ảnh rất bất thường, tôi cần một phương pháp đơn giản hơn. Tôi muốn xử lý tất cả chúng với mogrify.
Mike

0

Tôi sử dụng tập lệnh PHP như vậy, nó sử dụng 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);
?>

Nó chia tỷ lệ tất cả các hình ảnh trong thư mục hiện tại lớn hơn 3000 trên một số cạnh.

Chạy lệnh: php scale.phpHOẶCphp scale.php 2000


0

Đây là ý kiến ​​của tôi, kết hợp các ý tưởng từ @ArionKrause và @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

(Tôi cần điều này vì bộ xử lý hàng loạt yêu thích của tôi Phatch không hoạt động với Ubuntu 16.04.)


0

Chức năng của tôi để thay đổi kích thước và tối ưu hóa

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"
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.