使用mogrify调整大文件的大小,而忽略小文件


10

我正在运行以下命令:

mogrify -resize '400x400>' *.png

请注意“>”。据说它将忽略较小的文件,但是尽管它不会调整它们的大小,但是会编辑它们(修改日期和文件大小已更改)。

有没有办法让它实际上只留下较小的文件?我想避免数千次不必要的写操作。

Answers:


15

我认为mogrify系统地重写了文件,所以您唯一的希望是按照jippie的建议首先过滤列表。这是您的操作方法(未试用):打印出带有大小指示的图像文件列表,仅保留相关大小在范围内的名称,然后处理该列表。

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

脚本说明:

  • 对于每个文件,请打印一条带有宽度,空格,高度,空格和文件名的行。根据您的的版本identify\n添加最终换行符可能是必要的(ImageMagick 6.6.0),也可以是多余但无害的(GraphicsMagick 1.1.11)。
  • awk)在每一行上,如果宽度($1)和高度($2)符合要求的条件,则:
    • 删除所有文本,直到第二个空格字符。这样会去除宽度和高度。
    • 打印该行的其余部分,即文件名。
  • 用空字符替换换行符。
  • 调用xargs -0mogrify对文件名执行命令。(我们不能使用Plain,xargs因为它不能处理包含空格或的输入\'"。)

文件名可以包含除换行符以外的任何字符。


你能解释一下那个剧本吗?特别是“子”部分。它在打印文件名时不带空格或插入新行。mogrify:无法打开文件`22 553.png308 400 0134 2.png'@ error / png.c / ReadPNGImage / 2951。我不知道“ 308 400”来自何处。我应该提到文件名称中有空格谢谢。
迈克

我正在抱怨:无法打开文件'340 271 22 553.png308 400 0134 2.png'@ error / png.c / ReadPNGImage / 2951。我在两个示例文件上使用200x200运行了该命令。我看到308x400是其中一个文件的大小
Mike

2
@Mike Ah,明白了。某些版本的identify自动在每条记录后添加换行符,其他版本则需要明确地使用换行符。\n在参数末尾添加到-format(请参阅我的编辑)。
吉尔(Gilles)'所以

8

我遇到了您描述的相同问题。这是我的解决方案:

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

我在虚拟化的CentOS 6.5机器上的几张JPEG图像上对其进行了测试。该脚本仅调整宽度和高度大于640像素的图像的大小并对其进行压缩。这使其适用于尺寸为800 x 600(横向,将其调整为640 x 480)和尺寸为600 x 800(纵向,将其调整为480 x 640)的图像。

PS:关于400x400参数的注释:mogrify即使文件大小等于或小于400x400,也将对其进行处理,但是仅当文件大小大于400x400 时才对其进行调整。这就是更改文件的修改时间和大小的原因(在我的情况下,mogrify使这些文件比以前更大)。


5

您还可以使用fx运算符根据高度/宽度过滤图像,例如

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

1如果图像大于400x4000等于或小于400x400...,将输出


假设文件名合理(没有换行符,空格/制表符等),则可以identify用来打印以1:或开头的图像名称0:,处理输出删除以开头的行,0:并删除1:其余行的开头,因此仅保留文件名,一个每行,然后将该列表传递到mogrify ... @-(在中添加了@语法imagemagick v6.5.2):

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

否则,find您只能打印大小> 400x400的文件,然后将结果通过管道传递给xargs+ mogrify(效率较低,因为它会为每个文件运行一个shell,但它应该适用于所有类型的文件名):

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'

如果您是zsh用户,请参见此答案


3

如何使用identify查找图像的大小并通过一个小的脚本来决定是否要编辑它:

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

编辑用于简单脚本的输出格式应该不太难。


考虑到我有限的技能以及图像尺寸如此不规则的事实,我需要一种更简单的方法。我宁愿处理所有这些。
迈克

0

我使用这样的PHP脚本,它使用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);
?>

它会将当前目录中的所有图像缩放到大于3000的某个边缘。

运行命令:php scale.phpphp scale.php 2000


0

这是我的观点,结合了@ArionKrause和@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

(我需要这样做是因为我最喜欢的批处理处理器Phatch无法在Ubuntu 16.04上使用。)


0

我要调整大小和优化的功能

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"
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.