使用脚本自动选择 JPEG 和 PNG

Glu*_*ate 5 png unix jpeg imagemagick conversion

选择正确的格式来保存图像对于保持图像质量和减少伪影至关重要。不同的格式遵循不同的压缩方法,并具有各自的优点和缺点。

例如,JPG 适用于色彩渐变丰富的现实生活照片。另一方面,无损 PNG 在原理图方面要优越得多:

在此处输入图片说明

在处理大量文件时,选择正确的格式可能是一件苦差事。这就是为什么我很想找到一种方法来自动化它。


关于我的特定用例的一些背景知识:

我正在为我大学的一系列讲座制作一些讲义。讲义中有丰富的图表,我必须从 PDF 格式的幻灯片中提取。提取这些图像给了我无损的 PNG,有时会不必要地大。

将这些特定文件转换为 JPEG 可以将它们的大小减少到原始文件大小的 20% 以下,同时保持相同的质量。这很重要,因为在文字处理器中处理数百张大图像非常容易崩溃。

将所有提取的 PNG 批量转换为 JPEG不是我愿意遵循的选项,因为大多数图像更适合格式化为 PNG。转换这些将导致大小不显着的减少,有时甚至会增加文件大小 - 至少我的测试运行显示了这一点。


我们可以从中得出的是,压缩后的文件大小可以作为指示哪种格式最适合特定图像的指标。它不是一个特别准确的预测器,但效果很好。那么为什么不以脚本的形式使用它:

在此处输入图片说明

我包含inotifywait是因为我希望在将提取的图像拖到文件夹中时自动执行脚本。

这是我过去几周一直在使用的脚本的更简单版本:

#!/bin/bash
inotifywait -m --format "%w%f" --exclude '.jpg' -r -e create -e moved_to --fromfile '/home/MHC/.scripts/Workflow/Conversion/include_inotifywait' | while read file; do mogrify -format jpg -quality 92 "$file"
done
Run Code Online (Sandbox Code Playgroud)

脚本的高级版本必须

  • 能够处理文件名和目录名中的空格
  • 保留原始文件名
  • 如果设置了 alpha 值,则展平 PNG 图像
  • 比较临时转换后的图像与其原始图像之间的文件大小
  • 确定差异是否大于给定的百分比
  • 按指示行动

实际转换可以使用 imagemagick 工具完成:

convert -quality 92 -flatten -background white file.png file.jpg
Run Code Online (Sandbox Code Playgroud)

不幸的是,我的 bash 技能甚至还不够先进,无法将上述方案转换为实际脚本,但我相信你们中的许多人都可以。

我在这里的声誉点很低,但我很乐意用我可以设置的最高赏金奖励最有帮助的答案。

参考资料:http : //www.formortals.com/introducing-cnb-imageguide/,http : //www.turnkeylinux.org/blog/png-vs-jpg

编辑:另请参阅下面我的评论,了解有关为什么我认为此脚本将是我所面临问题的最佳解决方案的更多信息。

Glu*_*ate 2

编辑:修复了原始脚本的一些问题。根据马克斯·托马斯的提议添加了另一种选择。

编辑 2:根据多次测试运行更新截止值。我仍然不确定如何估计灰度图像的文件大小。如果您正在处理 RGB 配色方案之外的大量图像,您可能希望将第一个脚本实现为第二个脚本的后备模式。

编辑 3:添加optipng集成。这可以优化 PNG 文件大小,而不会造成任何质量损失。浏览此处获取更多信息。一些较小的改进。


版本0.1

重要提示该脚本已被弃用。新版本的效率要高得多。

好吧,我的问题可能有点过于本地化,所以我花了一些时间并自己编译了脚本:

#!/bin/bash

# AUTHOR:   (c) MHC (http://askubuntu.com/users/81372/mhc)
# NAME:     Intelliconvert 0.1
# DESCRIPTION:  A script to automate and optimize the choice between different image formats.
# LICENSE:  GNU GPL v3 (http://www.gnu.org/licenses/gpl.html)
# REQUIREMENTS:  Imagemagick

ORIGINAL="$1"

###Filetype check###

MIME=$(file -ib "$ORIGINAL")

if [ "$MIME" = "image/png; charset=binary" ]
  then
    echo "PNG Mode"

###Variables###

      ##Original Image##
    FILENAME=$(basename "$ORIGINAL")
    PARENTDIR=$(dirname "$ORIGINAL")
        SUBFOLDER=$(echo "$PARENTDIR" | cut -d"/" -f10-)
    ORIGARCHIVE="~/ORIG"

      ##Converted Image##
    TEMPDIR="/tmp/imgcomp"
    CONVERTED="$TEMPDIR/$FILENAME.jpg"

      ##Image comparison##
    DIFFLO="50"
    DIFFHI="75"
    CUTOFF="1000000"

      ##DEBUG
    echo "#### SETTINGS ####"
    echo "Filepath to original = $ORIGINAL"
    echo "Filename= $FILENAME"
    echo "Parent directory = $PARENTDIR"
    echo "Archive directory = $ORIGARCHIVE"
    echo "Temporary directory = $TEMPDIR"
    echo "Filepath to converted image = $CONVERTED"
    echo "Low cut-off = $DIFFLO"
    echo "High cut-off = $DIFFHI"

###Conversion###

    convert -quality 92 -flatten -background white "$ORIGINAL" "$CONVERTED"

###Comparison###

    F1=$(stat -c%s "$ORIGINAL" )
    F2=$(stat -c%s "$CONVERTED" )
    FQ=$(echo "($F2*100/$F1)" | bc)

      #Depending on filesize we use a different Cut-off#
    if [ "$F1" -ge "$CUTOFF" ]
      then
        DIFF="$DIFFHI"
      else  
        DIFF="$DIFFLO"
    fi

      ##DEBUG
    echo "### COMPARISON ###"
    echo "Filesize original = $F1 Bytes"
    echo "Filesize converted = $F2 Bytes"
    echo "Chosen cut-off = $DIFF %"
    echo "Actual Ratio = $FQ %"


    if [ "$FQ" -le "$DIFF" ]
      then
           echo "JPEG is more efficient, converting..."
           mv -v "$CONVERTED" "$PARENTDIR"
               mkdir -p "$ORIGARCHIVE/$SUBFOLDER"
           mv -v "$ORIGINAL" "$ORIGARCHIVE/$SUBFOLDER"
      else
           echo "PNG is fine, exiting."
           rm -v "$CONVERTED"
    fi


  else
    echo "File does not exist or unknown MIME type, exiting."

fi
Run Code Online (Sandbox Code Playgroud)

该脚本与Watcher结合使用效果很好。

这是我的第一个正确的脚本,因此可能存在一些未解决的错误和我没有看到的问题。请随意为自己使用它并改进它。如果您这样做,如果您能在这里发表评论,我将不胜感激,以便我可以从中学习。


版本0.2.1

通过将原始文件大小与未压缩图像的估计大小进行比较,可以更有效地找到正确的格式:

#!/bin/bash

# AUTHOR:   (c) MHC (http://askubuntu.com/users/81372/mhc)
# NAME:     Intelliconvert 0.2.1
# DESCRIPTION:  A script to automate and optimize the choice between different image formats.
# LICENSE:  GNU GPL v3 (http://www.gnu.org/licenses/gpl.html)
# REQUIREMENTS:  Imagemagick, Optipng

################ Filetype Check#################

MIME=$(file -ib "$1")

if [ "$MIME" = "image/png; charset=binary" ]
  then
    echo "###PNG Mode###"

####################Settings####################

##Folders##
ORIGARCHIVE="~/ORIG"

##Comparison##
DIFFLO="25"
DIFFHI="20"
CUTOFF="1000000"

################################################

###Variables###

ORIGINAL="$1"
FILENAME=$(basename "$ORIGINAL")
PARENTDIR=$(dirname "$ORIGINAL")
SUBFOLDER=$(echo "$PARENTDIR" | cut -d"/" -f10-)
CONVERTED="$PARENTDIR/$FILENAME.jpg"

#DEBUG#
    echo "###SETTINGS###"
    echo "Filepath to original = $ORIGINAL"
    echo "Filename= $FILENAME"
    echo "Parent directory = $PARENTDIR"
    echo "Archive directory = $ORIGARCHIVE"
    echo "Filepath to converted image = $CONVERTED"
    echo "Low cut-off = $DIFFLO"
    echo "High cut-off = $DIFFHI"


###Image data###

        WIDTH=$(identify -format "%w" "$ORIGINAL")
        HEIGHT=$(identify -format "%h" "$ORIGINAL")
        ZBIT=$(identify -format "%z" "$ORIGINAL")
        COL=$(identify -format "%[colorspace]" "$ORIGINAL")
        F1=$(stat -c%s "$ORIGINAL")

        if [ "$COL" = "RGB" ]
          then
              CHANN="3"
          else
              CHANN="1"
        fi


###Cutoff setting###

    if [ "$F1" -ge "$CUTOFF" ]
      then
        DIFF="$DIFFHI"
      else  
        DIFF="$DIFFLO"
    fi


###Calculations on uncompressed image###

        BMPSIZE=$(echo "($WIDTH*$HEIGHT*$ZBIT*$CHANN/8)" | bc)
        FR=$(echo "($F1*100/$BMPSIZE)" | bc)

#DEBUG#

        echo "###IMAGE DATA###"
        echo "Image Dimensions = $WIDTH x $HEIGHT"
        echo "Colour Depth = $ZBIT"
        echo "Colour Profile = $COL"
        echo "Channels = $CHANN"
        echo "Estimated uncompressed size = $BMPSIZE"
        echo "Actual file size = $F1"
        echo "Estimated size ratio = $FR %"
        echo "Cutoff at $DIFF %"

###Backup###

        echo "###BACKUP###"
        mkdir -p "$ORIGARCHIVE/$SUBFOLDER"  #keep the original folder structure
        cp -v "$ORIGINAL" "$ORIGARCHIVE/$SUBFOLDER"
        echo ""

###Comparison###

    if [ "$FR" -ge "$DIFF" ]
      then
          echo "JPEG is more efficient, converting..."
          convert -quality 92 -flatten -background white "$ORIGINAL" "$CONVERTED"
              echo "Done."
          echo "Cleaning up..."
          rm -v "$ORIGINAL"
      else
          echo "PNG is fine, passing over to optipng."
              echo "Optimizing..."
              optipng "$ORIGINAL"
              echo "Done."
    fi

################ Filetype Check#################

  else
    echo "File does not exist or unknown MIME type, exiting."

fi
Run Code Online (Sandbox Code Playgroud)

感谢 @Marcks Thomas 的好主意。