Remapping a picture to a set color palette.

Questions and postings pertaining to the usage of ImageMagick regardless of the interface. This includes the command-line utilities, as well as the C and C++ APIs. Usage questions are like "How do I use ImageMagick to create drop shadows?".
Post Reply
mattlasvegas
Posts: 2
Joined: 2018-10-20T23:04:17-07:00
Authentication code: 1152

Remapping a picture to a set color palette.

Post by mattlasvegas » 2018-10-20T23:34:09-07:00

So I am writing this program from a friend who does crystal/beading. The se-up is a follows.

1. These beads come in a number of different colors (each has a number and a name). I have a picture that shows each of these colors. I manually cropped a small sample of each color into a file called XXX.png where XXX is the number.
2. I then ran a script on these XXX.png files:
// reduce to a 1x1 and get the RGB values of it. (Note, here XXX is just a three digit number for the color sample file.)
convert XXX.png -resize 1x1\! -format "%[fx:int(255*r+.5)],%[fx:int(255*g+.5)],%[fx:int(255*b+.5)]" info:-
// create a color tile of size 30x15. (RR, GG, BB are the hex values extracted from the previous line's command, XXX is still the color number
convert -size 30x15 xc:#RRGGBB XXX-proof.png

After this I now have a bunch of XXX-proof.png files - these make up the colors I want to use.

3. I then make a color palette:
convert -append colors/*proof.png palette.png
can be seen here: Image

4. I now find the picture I want to work on. For example this one:
Image
which is 960x759
5. I reduce the size of that picture, again using imagemagick:
convert filename -resize 96x76! +dither -resize-filename
result:
Image
size is 96x76 here, but that is user defined.
6. I now apply the following command:
convert resize-US.jpg +dither -remap palette.png remap-resize-US.jpg
and I get:
Image

I was now expecting that ALL the pixels int he remapped and resized image would be ONE of the colors in the palette file that I gave it, but it isn't.

EVEN if I add: -color 2 to have it pick the best TWO colors only when I inspect the picture I find pixels that are a completely different color than ANY of the ones in the palette. Here is that result (convert resize-US.jpg -dither None -remap palette.png -colors 2 remap2-resize-US.jpg):
Image

Bar writing code to read a picture, compute L*a*b distances of all pixels to every color in the palette and picking the color that is the 'closest' in the CIELAB 94 norm I don't know what to do.... I do NOT cherish the idea of having to do all that nasty math myself ;-). Any help here would be greatly appreciated.

snibgo
Posts: 11932
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: Remapping a picture to a set color palette.

Post by snibgo » 2018-10-21T05:50:55-07:00

You are saving to JPG format. JPG is lossy, which means it changes the pixel colours. I suggest you use a losslesss format such as PNG.
snibgo's IM pages: im.snibgo.com

mattlasvegas
Posts: 2
Joined: 2018-10-20T23:04:17-07:00
Authentication code: 1152

Re: Remapping a picture to a set color palette.

Post by mattlasvegas » 2018-10-21T22:54:23-07:00

Yes, I think I figured it out too .... The problem is DON'T start with a jpg. I converted to a png and then used

convert in.png -resize WxH\~ +depth +dither -remap palette.png out.png

and then make sure that when creating the palette.png it is not dithered either.

snibgo
Posts: 11932
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: Remapping a picture to a set color palette.

Post by snibgo » 2018-10-22T02:39:20-07:00

The data loss (ie change to pixels) occurs when writing JPG, not reading JPG. If your source image is JPG, converting it to PNG won't get the data back.

As general rules: don't use JPG sources unless nothing better is available. Don't use JPG for any image processing. JPG is a useful format if you want to show photos on the web, but don't use it for anything else.
snibgo's IM pages: im.snibgo.com

Post Reply