使用ImageMagick调整索引PNG图像大小并保留色彩映射

4

我正在使用自定义批处理脚本来制作文件夹中所有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

但它不起作用。

编辑:

这是更新后的代码,但它仍然不能按照预期工作(请参见附加的图像-左侧是原始大小,右侧是调整大小后的图像):

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

这里输入图像描述

原始图片: 原始图片

缩放版本: 缩放图片


1
问题是您希望保留特定的、精确的调色板吗?还是您希望确保调整大小后的图像小且索引到某个调色板,但您并不介意这个调色板中包含什么?答案将是不同的。 - Mark Setchell
我不介意颜色映射。我想确保调整大小后的图像很小。这是用于Web上的Retina图像。第一个(原始图像)是用于具有3dpi屏幕的屏幕等等。 - Juraj.Lorinc
请问您能够单独提供原始图像吗?而不是将其与输出图像合并在一起。 - Mark Setchell
使用 convert image.png -format "%[type]" info: | grep -i Palette 检测调色板图像,如果是调色板图像,则使用 -colors 250 来获得最佳的调色板输出图像结果。 - Mark Setchell
我在当前版本的ImageMagick(6.9.3-7)中没有观察到这个问题。你的脚本运行良好,可以生成干净的-2x和-3x图像。你使用的是哪个版本?(使用“convert | head -2”命令查找)。 - Glenn Randers-Pehrson
我正在使用6.8.9-9版本。我尝试过升级,但没有成功。我按照这些说明进行操作:http://askubuntu.com/questions/267746/how-can-i-install-the-latest-upstream-version-of-imagemagick-without-compiling - Juraj.Lorinc
2个回答

5
请使用"-sample"而不是"-resize"来保留颜色集。这会通过最近邻颜色选择而不是任何插值方式进行调整大小。
否则,颜色映射将超过256种颜色,png编码器无法保留它,因为PNG PLTE块的大小限制为256种颜色。虽然我不能保证您会喜欢结果的外观。
另外,请确保您正在使用最新版本的ImageMagick。我在当前版本(6.9.3-7)中没有观察到这个问题。您的脚本可以正常工作并生成清晰的2x和3x图像。

OPеҸҜд»ҘдҪҝз”Ё-resizeжқҘиҺ·еҫ—д»Өдәәж»Ўж„Ҹзҡ„жҸ’еҖјпјҢ然еҗҺдҪҝз”Ё-colors 250жҲ–-colors 60жқҘе…Ғи®ёжӮЁзҡ„еә“дҪҝз”Ёи°ғиүІжқҝйўңиүІжҳ е°„еҗ—пјҹ - Mark Setchell

0

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

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 

调色板

看起来你实际上只想输出带有"任意"颜色映射而不是"特定"颜色映射的调色板图像。如果你想保留特定的颜色映射,Glenn的回答是完美的。然而,如果任何颜色映射都可以,你可以使用-colors将结果图像中的颜色减少到一个PNG库可以决定创建调色板图像的级别。关于这个问题,Glenn比我知道得多,因为他写了这个功能!然而,我认为如果你将颜色减少到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

你可以尝试使用其他颜色数量进行实验,看看它对文件大小的影响 - 你需要的数量将取决于你的图像。


性能不是大问题(我处理的是数十张图片而不是数千张),但微调一下还是很好的。我想要处理目录和子目录中的所有图像,所以对我来说查找很有用。你的解决方案中的问题是,我在文件夹(和子文件夹)中有几种不同类型的PNG(8位、24位、索引、非索引...),因此我需要为不同的图像使用不同的参数。请参见我的帖子编辑,了解到目前为止我的代码并没有按预期工作。有大面积(正方形)的不同颜色。 - Juraj.Lorinc

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接