ImageMagick / ImageMagick

🧙‍♂️ ImageMagick 7
https://imagemagick.org
Other
11.63k stars 1.31k forks source link

-remap reorders the palette unpredictably #6916

Open php4fan opened 7 months ago

php4fan commented 7 months ago

ImageMagick version

7.1.1-21

Operating system

Linux

Operating system, version and so on

Debian 12

Description

(I'm actually not sure what the OS version is, as I'm using a docker image)

When you use -remap to replace the colors in an image with the palette from another given image, the order of the colors in the palette is not preserved. Not only that, it's not reordered in a consistent, predictable manner, that is, if you remap several images with the same palette image as parameter to -remap, you get different resulting palettes (same colors but potentially in different orders), I guess depending on the input image.

I'm not sure if there's a criterion to the ordering, maybe from the least used to most used color or viceversa (it's certainly not just a function of the colors, otherwise it would at least be consistent, it's at least also a function of the input image, unless it's just totally utterly random). But either way, since you're being explicitly asked to use a given palette, I don't see a reason for not taking the palette as is including the order.

Steps to Reproduce

  1. run the following commands:
    convert input1.png -dither FloydSteinberg -colorspace CMYK -remap palette.png output1.png
    convert input2.png -dither FloydSteinberg -colorspace CMYK -remap palette.png output2.png

Expected behavior: the two output images should have the same palette with colors in the same order, and that should be the same as the palette in palette.png

Observed behavior: the two output images have palettes with the same colors but in different order.

Images

images.zip

snibgo commented 7 months ago

I suggest using magick instead of convert.

After running your commands above, you can do this:

magick palette.png output1.png -scale "%[fx:v.w]x%[fx:v.h]^!" -compose Copy -composite -type palette -define png:preserve-colormap=true output1.png

magick palette.png output2.png -scale "%[fx:v.w]x%[fx:v.h]^!" -compose Copy -composite -type palette -define png:preserve-colormap=true output2.png

The files palette.png, output1.png and outpu2.png will then have the same colours in their palettes, in the same order.

You can, of course, combine the commands.

CHiPs44 commented 5 months ago

Hello,

I'm trying to make the very same sort of batch processing for 70 128x128 icons, so I tried this command on one of them, and with my 13 colors palette image, output is only 4 colors:

$ magick -version
Version: ImageMagick 7.1.1-27 Q16-HDRI x86_64 9c64c662f:20240120 https://imagemagick.org
[...]
$ magick palette.png input.png -scale "%[fx:v.w]x%[fx:v.h]^!" -compose Copy -composite -type palette -define png:preserve-colormap=true output.png
$ magick identify *.png
input.png PNG 128x128 128x128+0+0 8-bit sRGB 4159B 0.000u 0:00.001
output.png PNG 128x128 128x2+0+0 8-bit sRGB 4c 786B 0.000u 0:00.000
palette.png PNG 128x9216 128x128+0+0 8-bit sRGB 13c 55194B 0.000u 0:00.000

Do you have any idea why this is the case?

fmw42 commented 5 months ago

-scale averages blocks of pixels. If the output size is much smaller than the input size, you may indeed get fewer (averaged) colors.