Page 1 of 1

Color flatting with ImageMagick

Posted: 2018-02-11T12:24:15-07:00
by johnwallie
Hello everyone,
I'm trying to come up with an automated way to fill in shapes with randomized colors. The goal is to take a bitmap line drawing and fill in all the white areas with color, so that I can later go in with a paint program and easily drop the appropriate colors in with the paint bucket.

Using Python and PIL I was able to easily create a script that does this (here it is if you're curious: https://pastebin.com/Cc8AcNZv ), but I'd really like to come up with one that can handle gaps in the linework. This is where it got complicated.

Using the -morphology Close function in imageMagick, I was able to address a lot of the gaps, but unfortunately it also leaves a lot of white space around my linework once the result has been colorized:
Image

After looking around more I found the Sparse-Color operator, which seems like it would be a good choice for this project, but I can't seem to figure out how best to implement it. Essentially what I want is for the edges of the "color islands" to spread out until they meet, in a voronoi-type fashion. I tried to follow the directions here but I couldn't get it to work, and as my source images are fairly large I suspect that it would probably be an inefficient way of doing this, anyway.

IM version: 6.8.9-9

Any suggestions would be appreciated. If you think I'm approaching this in the wrong way and you see a more direct way of solving the problem, that's great too! Thanks!

Re: Color flatting with ImageMagick

Posted: 2018-02-11T12:33:53-07:00
by fmw42
Please always provide your IM version and platform when asking questions, since syntax may vary. Also it would be best to provide separate files, so people who might want to help can use it without having to crop it out of your combined image.

What command did you try with sparse-color? Did you make your remaining white pixels transparent before using sparse-color?

Re: Color flatting with ImageMagick

Posted: 2018-02-11T12:46:09-07:00
by johnwallie
Sorry about that. IM version: 6.8.9-9

The entire source image can be obtained here: https://ibb.co/hpHmJ7

I did convert the white pixels to transparent before running sparse-color. (I altered my Python script to output transparency instead of white.)

Following the directions in the documentation I did the following, but as you can see, it failed to work (transcript from my terminal window):

Code: Select all

john@strangelove ~/flood-fill $ convert output.png -channel A -morphology EdgeIn Diamond edges.png
john@strangelove ~/flood-fill $ convert edges.png txt:- |\
> sed '1d; / 0) /d; s/:.* /,/;' | \
> convert edges.png -alpha off \
> -sparse-color voronoi '@-' voronoi_result.png
convert: invalid argument for option `sparse-color': Invalid number of Arguments @ error/mogrify.c/SparseColorOption/526.
It's hard for me to tell exactly what's going on there because my understanding of what the sed line is supposed to do is pretty vague.

Re: Color flatting with ImageMagick

Posted: 2018-02-11T14:23:05-07:00
by fmw42
Please provide output.png so we can test you command. I presume it is the colored image with white or transparency for the missing colors.

Re: Color flatting with ImageMagick

Posted: 2018-02-11T14:43:07-07:00
by johnwallie
You are correct. Here it is: https://i.imgur.com/rgCA59X.png

Re: Color flatting with ImageMagick

Posted: 2018-02-11T14:53:22-07:00
by snibgo
I show a few methods of Mending broken lines.

When you have fixed the breaks, you can make all the lines transparent, and use any method of Filling holes or Filling holes in priority order, then composite with the original black lines if you want.

Re: Color flatting with ImageMagick

Posted: 2018-02-11T15:56:00-07:00
by fmw42
I have cropped your color image for testing a small section.

Input:
Image

Note txt: outputs a line for each pixels of the form:

Code: Select all

32,22: (0,0,0,0)  #00000000  none
33,22: (7710,37008,65535,65535)  #1E90FFFF  DodgerBlue
So the grep finds only those lines that do not contain none (i.e. the opaque colors)

The sed finds the x,y coordinates before the colon and the color value at the end of the line and makes them into for example

Code: Select all

33,32,DodgerBlue
The following convert command after the sed makes a clone of the image, extracts the edges in the color area with transparency everywhere else. Then uses all the triplets of opaque colors with their coordinates and feeds that to sparse-color voronoi to fill in the transparent area with the closest color, so as not to add new colors.

Code: Select all

convert image_crop.png \
\( +clone -alpha extract -morphology edgein diamond:1 \) \
-alpha off -compose copy_opacity -composite \
-background black -alpha background -depth 8 txt:- |\
grep -v "none" |\
sed -n 's/^\(.*,.*\):.*[#][^ ]*  \(.*\)$/\1,\2/p' |\
convert image_crop.png \
\( +clone -alpha off -sparse-color voronoi '@-' \) \
-compose over -composite image_crop_vornoi.png
Image

Is this what you want?

Re: Color flatting with ImageMagick

Posted: 2018-02-11T18:07:47-07:00
by johnwallie
That is exactly the result I am looking for, but so far I've been unable to reproduce your procedure. I tried copy-pasting it straight into a shell script, and entering it manually, but both had the same resulting error message:

Code: Select all

john@strangelove ~/flood-fill $ convert panel_isolated_colors.png \
> \( +clone -alpha extract -morphology edgein diamond:1 \) \
> -alpha off -compose copy_opacity -composite \
> -background black -alpha background -depth 8 txt:- |\
> grep -v "none" |\
> sed -n 's/^\(.*,.*\):.*[#][^ ]*  \(.*\)$/\1,\2/p' |\
> convert panel_isolated_colors.png \
> \( +clone -alpha off -sparse-color voronoi '@-' \) \
> -compose over -composite voronoi.png
convert: invalid argument for option `sparse-color': Invalid number of Arguments @ error/mogrify.c/SparseColorOption/526.
(panel_isolated_colors.png is the same as the "output.png" I was using earlier.)

I'm not quite sure what I'm doing wrong.

Would you mind breaking down your nested command into multiple "convert" lines so that I can more easily understand what's going on? With all the cloning and piping and such I have a hard time visualizing what's actually happening here and I'd really like to understand.

Re: Color flatting with ImageMagick

Posted: 2018-02-11T19:45:31-07:00
by fmw42
Slight change below from before.

Code: Select all

Line1: read input
Line2: clone the input, extract the alpha channel and get the inner edges of it
Line3: put the result of line2 into the alpha channel of the input
Line4: put black under the alpha channel of all transparent pixels, so that its color is none (equivalent to srgb(0,0,0,0) and output as txt: to stdout
Line5: remove all lines from txt that do not include "none" for the color
Line6: reformat the remaining lines to be in the format x,y,color
Line7: start a new convert and read the original input
Line8: clone the input turn the alpha channel off and send all the x,y,color triplets to stdin and apply sparse-color voronoi
Line9: swap so as to compose the transparent original input image over the opaque voronoi filled out one

I have added +write tmpX.png to different parts so you can see what is happening. See where it stops by which tmp images are produced and which are not. Note tmp2 and tmp3 will look identical since only the color under the transparency has been changed.

I tested using IM 6.8.9.9 and it works for me. What is your platform? Do you have the unix commands grep and sed installed?

Code: Select all

convert image_crop.png \
\( +clone -alpha extract -morphology edgein diamond:1 +write tmp1.png \) \
-alpha off -compose copy_opacity -composite +write tmp2.png  \
-background black -alpha background -depth 8 +write tmp3.png  txt:- |\
grep -v "none" |\
sed -n 's/^\(.*,.*\):.*[#][^ ]*  \(.*\)$/\1,\2/p' |\
convert image_crop.png \
\( +clone -alpha off -sparse-color voronoi '@-' +write tmp4.png \) \
+swap -compose over -composite image_crop_vornoi2.png
Check your policy.xml file to see that it has not enabled prevention of @-. It should be commented out as

<!-- <policy domain="path" rights="none" pattern="@*" /> -->

My policy.xml file is at /usr/local/etc/ImageMagick-6/policy.xml. See https://www.imagemagick.org/script/resources.php

Re: Color flatting with ImageMagick

Posted: 2018-02-12T16:35:45-07:00
by johnwallie
I'm running Linux Mint 18.3. I checked my policy.xml file and found that the line was not commented out. I corrected it but I'm still getting the same error as before. For me policy.xml was located in /etc/ImageMagick-6. Is it possible that there is another config file somewhere that is overriding this one?

Here is my policy.xml if it helps any: https://pastebin.com/NwTunYZd

As an experiment I piped the output of sed into a file and got the following (excerpted):

Code: Select all

48,25,srgba(255,77,0,1)
49,25,srgba(255,77,0,1)
50,25,srgba(255,77,0,1)
51,25,srgba(255,77,0,1)
52,25,srgba(255,77,0,1)
53,25,srgba(255,77,0,1)
54,25,srgba(255,77,0,1)
55,25,srgba(255,77,0,1)
56,25,srgba(255,77,0,1)
57,25,srgba(255,77,0,1)
58,25,srgba(255,77,0,1)
59,25,srgba(255,77,0,1)
60,25,srgba(255,77,0,1)
61,25,srgba(255,77,0,1)
62,25,srgba(255,77,0,1)
etc...
Is that the formatting we want?

Edit:
Searching around it looks as if the ImageMagick build in the Ubuntu/Mint repositories does not allow '@-' even if the policy.xml allows it.

Re: Color flatting with ImageMagick

Posted: 2018-02-12T17:13:51-07:00
by fmw42
That is the correct format. Yes, your system admin may set that limitation and you may not be able to relax it. Check with your system admin.

Re: Color flatting with ImageMagick

Posted: 2018-02-12T17:19:01-07:00
by snibgo
I suggest you try a simple test case. Create a text file called v.txt, containing:

Code: Select all

0,0,red
1,1,blue
Then try the command:

Code: Select all

convert -size 2x2 xc: -sparse-color voronoi "@v.txt" txt
(I use Windows. For Unix, you need single-quotes.)
The expected output is:

Code: Select all

# ImageMagick pixel enumeration: 2,2,65535,srgb
0,0: (65535,0,0)  #FFFF00000000  red
1,0: (65535,0,0)  #FFFF00000000  red
0,1: (65535,0,0)  #FFFF00000000  red
1,1: (0,0,65535)  #00000000FFFF  blue

Re: Color flatting with ImageMagick

Posted: 2018-02-12T17:36:27-07:00
by johnwallie
Snibgo, thanks for the idea! Looks like I can do a workaround where the sed output gets sent to a text file, which is then read by convert. Not the most elegant solution but it will hold me over until I succeed in building imagemagick myself.

Thanks everyone!

Edit: I built ImageMagick from source with ./configure --enable-pipes and now it's working as expected.