【问题标题】:Resize indexed PNG image with ImageMagick while preserving color map使用 ImageMagick 调整索引 PNG 图像的大小,同时保留颜色映射
【发布时间】:2016-06-22 21:45:01
【问题描述】:

我正在使用自定义批处理脚本来制作文件夹中所有 PNG 图像的大小调整副本(33% 和 66%)。这是我的代码:

for f in $(find /myFolder -name '*.png'); 
do
sudo cp -a $f "${f/%.png/-3x.png}"; 
sudo convert $f -resize 66.67% "${f/%.png/-2x.png}"; 
sudo convert $f -resize 33.33% $f; 
done

它工作正常,除非原始图像被索引。在这种情况下,图像的较小版本是 RGB(因此文件大小比原始图像更大)。

我尝试了几个版本,但都没有成功。我想应该解决这个问题的一个是休闲:

for f in $(find /myFolder -name '*.png'); 
do
sudo cp -a $f "${f/%.png/-3x.png}"; 
sudo convert $f -define png:preserve-colormap -resize 66.67% "${f/%.png/-2x.png}"; 
sudo convert $f -define png:preserve-colormap -resize 33.33% $f; 
done

但它不起作用。

编辑:

这是更新的co,但它仍然无法正常工作(见附图——左为原图,右为调整大小):

for f in $(find /myFolder -name '*.png');
do
  sudo cp -a $f "${f/%.png/-3x.png}";
  numberOfColors=`identify -format "%k" $f`

  convert "$f"                                                        \
    \( +clone -resize 66.67% -colors $numberOfColors -write "${f/%.png/-2x.png}" +delete \)  \
    -resize 33.33% -colors $numberOfColors "$f"
done

原图:

缩放版本:

【问题讨论】:

  • 您想保留一个特定的、准确的颜色图吗?或者您想确保调整大小的图像很小并且索引到 a 颜色图,但您并不真正介意该颜色图中的内容?答案会有所不同。
  • 我不介意彩色地图。我想确保调整大小的图像很小。这适用于网络上的视网膜图像。第一个(原始图像)用于具有 3dpi 屏幕的屏幕等等。
  • 您能否单独提供原始图像 - 而不是加入输出图像。
  • 如何使用convert image.png -format "%[type]" info: | grep -i Palette 检测托盘化图像,如果托盘化,使用-colors 250 以获得最佳结果,您可以使用托盘化输出图像。
  • 我没有发现当前版本的 ImageMagick (6.9.3-7) 存在这个问题。您的脚本工作正常并生成干净的 -2x 和 -3x 图像。你用的是什么版本? (使用“convert | head -2”来找出)。

标签: imagemagick png imagemagick-convert indexed-image


【解决方案1】:

使用“-sample”而不是“-resize”来保留颜色集。这会导致通过最近邻颜色选择而不是任何类型的插值来调整大小。

否则,由于 PNG PLTE 块大小的 256 色限制,颜色图最终会包含超过 256 种颜色,并且 png 编码器无法保留它。不过,我不能保证你会喜欢结果的外观。

另外,请确保您使用的是最新版本的 ImageMagick。 我没有观察到当前版本(6.9.3-7)的这个问题。您的脚本工作正常并生成干净的 -2x 和 -3x 图像。

【讨论】:

  • OP 是否可以使用 -resize 获得令人愉悦的插值,然后使用 -colors 250-colors 60 以允许您的库使用调色板颜色图?
【解决方案2】:

这里有几件事要解决...

find vs glob

你说你想处理一个文件夹中的所有文件,然后你使用find,它也会搜索到子目录。如果你只想处理当前目录中的文件,你可以让bash 直接为你做 globbing。所以,而不是

for f in $(find . -name "*.png"); do

你可以这样做:

shopt -s nullglob
for f in *.png; do

性能

您运行两次convert 并加载两次原始图像,这不是很有效。您可以运行单个进程来加载单个图像并将大小调整为两种不同的大小并将两者都写入磁盘。所以,而不是

for ...; do
   convert ...
   convert ...
done

您可以编写以下内容来启动一个convert,读取图像一次,将其克隆到内存中并写出,删除内存中的备用副本,然后调整原始图像的大小并重新保存。

for ...; do
   convert "$f"                                                        \
      \( +clone -resize 66.67% -write "${f/%.png/-2x.png}" +delete \)  \
      -resize 33.33% "$f"
done 

调色板

看来您实际上只想输出带有 "any" 颜色图而不是 "specific" 颜色图的调色(索引)图像。如果您想保留特定的颜色图,格伦的回答是完美的。但是,如果任何颜色图都可以,您可以使用-colors 将结果图像中的颜色减少到PNG 库可以决定创建调色图像的级别。格伦在写这篇文章时比我知道更多!但是,我认为如果您将颜色减少到 250(或更多),您可能会得到 256 项颜色图,如果您将颜色减少到 60 左右,您将获得 64 项颜色图。所以,你会这样做:

shopt -s nullglob
for f in *.png; do
   sudo cp ... ...
   convert "$f"                                                        \
      \( +clone -resize 66.67% -colors 250 -write "${f/%.png/-2x.png}" +delete \)  \
      -resize 33.33% -colors 250 "$f"
done

您可以尝试使用其他颜色数量,看看它如何影响文件大小 - 您需要的颜色数量取决于您的图像。

【讨论】:

  • 性能不是我的大问题(我正在处理数十张而不是数千张图像),但这是一个很好的调整。我想处理目录和子目录中的所有图像,所以 find 对我有用。您的解决方案中的问题是,我在文件夹(和子文件夹)中有几种不同类型的 PNG(8 位、24 位、索引、未索引......)所以我需要不同的参数来处理不同的图像。到目前为止,请参阅我的帖子编辑以了解我的代码。它没有按预期工作。有不同颜色的大(正方形)区域。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-20
相关资源
最近更新 更多