twemoji-color-font icon indicating copy to clipboard operation
twemoji-color-font copied to clipboard

Better Fallback

Open adyeths opened this issue 5 years ago • 16 comments

I was thinking that the automatically generated black and white fallback should be better than it currently is, so I started playing around with trying to come up with a better way to automatically create them. I think I can have come up with something that works.

Here are examples of the commands that I came up with while experimenting:

rsvg-convert -a -b white -w 1000 -h 1000 -o generated.png input.svg
convert generated.png -scale 1000x1000 -gravity center -extent 102.4% +antialias -colorspace Gray -blur 5 -canny 0x0+99%+1% -morphology Dilate Diamond:3 -negate generated.pgm
potrace --backend svg --flat -o new.svg generated.pgm

The convert command does all the magic. I'm sure it could be tweaked to produce even better results, but this produces quite nice results.

adyeths avatar Nov 18 '19 02:11 adyeths

Interesting! Thanks for working on this idea. I've always wondered if/when someone would figure a way to make these better. I'll try this out. We need some comparisons posted to this issue.

13rac1 avatar Nov 18 '19 17:11 13rac1

Here are links three examples that I generated using my method...

example 1

example 2

example 3

adyeths avatar Nov 18 '19 19:11 adyeths

Wow, this looks awesome. I was about to create a similar (but inferior) issue before I found this...

ahyangyi avatar Jan 01 '20 15:01 ahyangyi

My suggestion: do not set the background to pure white. Set it to something rarely used. I personally use #ff00ff which is the classical "impossible" color.

One of the emojis affected by different background colors is 1f1e7-1f1fe, the Belarusian flag.

trace with white background: before-2

trace with magenta background: after

I added -background "#FF00FF" to the convert command line, and I did not set a background color to the inkscape command.

ahyangyi avatar Jan 01 '20 16:01 ahyangyi

I guess I am probably boar'd today! I made another attempt.

I personally prefer the monochrome font to use thicker lines and fill in all “dark” regions of the emoji, since that blends better with the typical sans-serif system UI fonts.

build/svg-bw/%.svg: build/staging/%.svg | build/svg-bw
    inkscape -w 1000 -h 1000 -z --export-file=$(TMP)/$(*F).png $<
    convert $(TMP)/$(*F).png -level 0%,115% -background "#FFFFFF" -gravity center -extent 1050x1050 +antialias -colorspace Gray -blur 3 $(TMP)/$(*F)_gray.png
    convert $(TMP)/$(*F)_gray.png -threshold 10% -morphology EdgeIn:12 Disk $(TMP)/$(*F)_threshold_1.pgm
    convert $(TMP)/$(*F)_gray.png -threshold 20% -morphology EdgeIn:12 Disk $(TMP)/$(*F)_threshold_2.pgm
    convert $(TMP)/$(*F)_gray.png -threshold 30% $(TMP)/$(*F)_threshold_3.pgm
    convert $(TMP)/$(*F)_gray.png -threshold 40% -morphology EdgeOut:12 Disk -negate $(TMP)/$(*F)_threshold_4.pgm
    convert $(TMP)/$(*F)_gray.png -threshold 51% -morphology EdgeOut:12 Disk -negate $(TMP)/$(*F)_threshold_5.pgm
    convert $(TMP)/$(*F)_gray.png -threshold 60% -morphology EdgeOut:12 Disk -negate $(TMP)/$(*F)_threshold_6.pgm
    convert $(TMP)/$(*F)_gray.png -threshold 70% -morphology EdgeOut:12 Disk -negate $(TMP)/$(*F)_threshold_7.pgm
    convert $(TMP)/$(*F)_gray.png -threshold 80% -morphology EdgeOut:12 Disk -negate $(TMP)/$(*F)_threshold_8.pgm
    convert $(TMP)/$(*F)_gray.png -threshold 90% -morphology EdgeOut:12 Disk -negate $(TMP)/$(*F)_threshold_9.pgm
    convert $(TMP)/$(*F)_threshold_3.pgm \
        $(TMP)/$(*F)_threshold_1.pgm -compose Screen -composite \
        $(TMP)/$(*F)_threshold_2.pgm -compose Screen -composite \
        $(TMP)/$(*F)_threshold_4.pgm -compose Multiply -composite \
        $(TMP)/$(*F)_threshold_5.pgm -compose Multiply -composite \
        $(TMP)/$(*F)_threshold_6.pgm -compose Multiply -composite \
        $(TMP)/$(*F)_threshold_7.pgm -compose Multiply -composite \
        $(TMP)/$(*F)_threshold_8.pgm -compose Multiply -composite \
        $(TMP)/$(*F)_threshold_9.pgm -compose Multiply -composite \
        $(TMP)/$(*F).pgm
    rm $(TMP)/$(*F).png $(TMP)/$(*F)_gray.png
    potrace --flat -s --height 2048pt --width 2048pt -o $@ $(TMP)/$(*F).pgm
    rm $(TMP)/$(*F).pgm \
        $(TMP)/$(*F)_threshold_1.pgm \
        $(TMP)/$(*F)_threshold_2.pgm \
        $(TMP)/$(*F)_threshold_3.pgm \
        $(TMP)/$(*F)_threshold_4.pgm \
        $(TMP)/$(*F)_threshold_5.pgm \
        $(TMP)/$(*F)_threshold_6.pgm \
        $(TMP)/$(*F)_threshold_7.pgm \
        $(TMP)/$(*F)_threshold_8.pgm \
        $(TMP)/$(*F)_threshold_9.pgm

So here are my experiment results.

Benchmark: 1f417, the boar boar

Old script boar

@adyeths's script boar

My new script boar

For the Belarus flag, my new script is not perfect but the result is recognizable: boar

However, my script is agonizingly slow, so maybe some optimization needs to be done...

EDIT, ouch, it seems the current list of thresholds is not enough...

ahyangyi avatar Jan 01 '20 19:01 ahyangyi

I had experimented with trying to preserve some of the fill characteristics but I was never quite happy with the results. It's not bad but I believe it could be improved. Here is the convert command that I used for this in case you want to experiment with it.

convert input.png \
        -gravity center \
        -background \#ff00ff \
        -extent 102.4% \
        -flatten \
        -scale 1536x1536 \
        \( +clone \
           -canny 0x1+.01%+1% \
           -morphology Dilate:10 Diamond \
           -negate \
        \) \
        -fill white \
        +fuzz \
        -opaque '#FF00FF' \
        -opaque '#A0041E' \
        -opaque '#BE1931' \
        -opaque '#EB2027' \
        -opaque '#FF000E' \
        -opaque '#FF5000' \
        -opaque '#DD2E44' \
        -opaque '#5C913B' \
        -opaque '#138F3E' \
        -opaque '#226798' \
        -opaque '#226699' \
        -opaque '#3558A0' \
        -opaque '#004A77' \
        -opaque '#744EAA' \
        -opaque '#880082' \
        -opaque '#66757F' \
        -opaque '#7C533E' \
        -opaque '#7C543E' \
        -opaque '#DA2F47' \
        -colorspace Gray \
        -threshold 45% \
        -compose Darken \
        -composite \
        output.pgm

adyeths avatar Jan 02 '20 03:01 adyeths

Sorry to bump this, but could a branch or fork be made with the dark fill emoji and the output font? I'm entirely unable to read the current B&W emoji because of the tiny details & small stroke.

Compare: New - & old - .

ghost avatar May 25 '20 04:05 ghost

@nedevel I'm building this right now with @ahyangyi script. It is so slow :turtle: Interested to see what happens though :man_shrugging:

13rac1 avatar Sep 12 '20 23:09 13rac1

@ahyangyi Wow. It is so so so slow. 20mins for the regular build vs hours and hours. I'm timing this. It wouldn't be bad if the files were generated then committed.

13rac1 avatar Sep 13 '20 23:09 13rac1

:laughing: This is quite a bit longer than the regular build:

real	637m51.631s
user	2319m55.108s
sys	17m29.041s

20mins vs 10.5hrs

13rac1 avatar Sep 14 '20 05:09 13rac1

Added to the current release. I don't intend to make this the default though, because of the 10.5hr build. Try it out. If someone can determine an even better process which doesn't take as long I'll be happy to implement it.

13rac1 avatar Sep 15 '20 02:09 13rac1

Rebased for 13.1.0 on https://github.com/eosrei/twemoji-color-font/tree/thickfallback I don't to build this myself due to the 10+ hr build time.

13rac1 avatar Jun 22 '21 05:06 13rac1

I have been messing around a little and got these results:

1f1f9-1f1eb

1f0cf

1f387

1f9d1-200d-1f692

The contour lines are still very thin but if I add more thickness to them, images like the flags get very bad.

Humming-Owl avatar Apr 22 '22 21:04 Humming-Owl

I improved a little bit more how to process the SVG images and ended with this script (Bash).

You need the Image Magick binary from the main page in the same location as the script for it to work. Also a folder called "input" with the SVG images.

https://github.com/Humming-Owl/scripts/blob/main/svgtobw.sh

It will create a "final" folder with the resulting images.

Humming-Owl avatar Apr 28 '22 02:04 Humming-Owl

It occurred to me that rasterizing, converting to black and white, and then tracing the images was completely unnecessary. So here's a significantly faster way to make black and white fallback svg's using only sed.

# from inside directory containing svg... will place black and white svg's in output directory...
for i in *.svg ; do 
    sed -r -e 's/ fill="(#[A-Z0-9]{3,6}|[a-z]+)"/ fill="white" stroke="black" stroke-width=".5" /gi;' < $i > output/$i
done

1f0cf 1f3a2 1f5fb

adyeths avatar Jun 20 '22 19:06 adyeths

One more update from me... I made a simple python script to convert the svg's to black and white, with an attempt at adding fills where they seemed appropriate. source is here -> https://gist.github.com/adyeths/ec20a69e35f2817110aeb13df7ed8b43

1f0cf 1f1f5-1f1f2 1f3c1 1f417

adyeths avatar Jun 25 '22 19:06 adyeths