# Random Faces

The face generator is a web application that generates faces by
combinging various elements such as eyes, nose, mouth and hair into a
single picture.

## How to Contribute

The first thing I had to do was learning to draw faces. Check out
[How to Draw a Face](http://www.wikihow.com/Draw-a-Face) or a similar
resource.

The main difficulty when it comes to contributing is that you need to
provide the face elements – hair, eyes, nose, mouth – so that the
software can layer them over one another. Thus, they need to be in
more or less the same fixed positions.

Do you work with pen and paper, or do you work electronically?

I work with **pen and paper**. That's why I print out the [empty
PDF](https://campaignwiki.org/contrib/empty.pdf) and start drawing my
face elements using a blue fountain pen. The empty.pdf file has basic
face shapes that help me draw the eyes always in the right spot, the
mouth always in the right spot, the beard always in the right spot,
and so on. See this
[example of a face on the template](https://campaignwiki.org/contrib/example.png).

If this work for you, print a bunch of empty.pdf sheets and start
drawing a row of noses, a row of mouths, a row of hair (or bald
heads), a row of ears, a row of chins (maybe with beard), and so on.
Scan what you draw and send me a mail (to
[Alex Schroeder](mailto:alex@alexschroeder.ch)) as soon as possible.
I'll set up a test account and we'll see how it goes, refining the
process as we go. See this
[example of the manual process](https://campaignwiki.org/contrib/manual-process.png).

If you're like me, you'll agree that elves should have thinner faces
and dwarves should have rounder faces. That's what the
[elf PDF](https://campaignwiki.org/contrib/elf.pdf) and the
[dwarf PDF](https://campaignwiki.org/contrib/dwarf.pdf) are for.

If you work **electronically** using a tablet or so, I would suggest
something else. Here's how I worked using my iPad and Procreate: I
created a new image by importing the
[empty PNG](https://campaignwiki.org/contrib/empty.png) and adding
a new layer for all the different elements: eyes, mouth, chin, ears,
nose, extra, and hair. I exported the whole image in PSD format,
keeping all the layers intact. If you got this far,
just [send it](mailto:alex@alexschroeder.ch) to me.
See this
[example of the electronic process](https://campaignwiki.org/contrib/electronic-process.png).

If you also prefer to work with the PSD format:
[download PSD file](https://campaignwiki.org/contrib/electronic-process.psd).

To get started, send me at bunch of noses, mouths, hair, ears, and
chins. The minimum is one each, but more is better, of course. 😄
Again, I'll set up a test account and we'll see how it goes. I think
getting feedback about the process is important. This will take a few
attempts, I think.

Later, we can use some other method to exchange files.

## File Names

It's important to get the file names right.

This application goes through the files in the `elements` folder for a
given artist and picks out one of each for every *element* of a face.
These are the elements considered, in order:

* face
* eyes
* brows
* mouth
* chin
* ears
* nose
* extra (only 10% of all faces)
* horns
* bangs
* hair
* hat (only 10% of all faces)

The application also allows filtering by *type*.

* woman
* man
* elf
* dwarf
* and whatever single word you can come up with...

The file format for all the images is very simple:
`element_type_stuff.png`, e.g. `ears_elf_2.png`. Each of these files
is a *component* of a particular face.

There is a special type called "all". It is used when no file matching
the requested type is found.

Assume we want to support men, women and elves. The ears of men and
women are always the same. A typical filename for human ears might be
`ears_all_1.png`. When generating a face for a man and looking at
ears, no file matching `ears_man_*` is found and so a file matching
`ears_all_*` is taken (namely the file `ears_all_1.png` we just
mentioned). When generating a face for an elf, however, a file
matching `ears_elf_*` is found (namely the file `ears_elf_2.png` we
mentioned above) and thus the ears matching `ears_all_*` are never
considered for elves.

This results in a problem when adding a type when there was none
before. At first, we just had `hair_all_*.png`. Then we decided that
here was a hairdo for a woman and created `hair_woman_3.png`. From now
on, the "all" type will no longer be used when generating a face for a
woman. One solution is to rename `hair_all_1.png` to
`hair_man_woman_1.png`. Now it will be used for both men and women but
not for dwarves or elves.

## Nickname, Name, License

All the files for each artist go into a directory with a short
nickname, e.g. "alex". The artist's name and the link to their
homepage is extracted from the `README.md` file in their directory.

Currently, the code assumes that all artists have dedicated their
files to the
[public domain](https://creativecommons.org/publicdomain/zero/1.0/).

## Processing

If you're running your own copy of the face generator, here's the post
processing you need to do with scanned images:

1. Scan the image and crop it using [The Gimp](http://www.gimp.org/)
   or whatever else you feel comfortable with. Cropping is important.
   The result must be an image 2250 pixels wide and 3000 pixels high.
   Rescale the image if necessary.

2. Clean up the image using [ImageMagick](http://www.imagemagick.org/)
   and the following command line: `convert -blur 0x1 +dither -remap
   blau.png scan1.jpg source1.png` – this forces the image to use the
   [blue](https://campaignwiki.org/contrib/blau.png) Palette (and
   loses the grid). We're also moving from JPG (which is what your
   scanner probably produced) to PNG. As for transparency: If your PNG
   files use "indexed mode" or a *palette* then it will work if you
   have a transparent color. If you don't (because you're converting a
   JPG to a PNG as you did just now) then *white* is considered to be
   *transparent* when merging the various elements. If your PNG files
   use "RGB mode" or *true color*, then it will also work if you use
   an alpha channel. Unfortunately, this means that it will *not* work
   if you use RGB mode and no alpha channel—such elements will cover
   all previous elements.

3. Cut the image into elements using `cutter.pl`.
   It cuts the scan into 5 × 5 images of 450 × 600 pixels each and
   labels them by row. You'd invoke it as follows: `perl
   helpers/cutter.pl source1.png alex eyes_all nose_all mouth_all
   hair_all chin_all` or `perl helpers/cutter.pl source2.png alex
   eyes_all nose_all mouth_all hair_all ears_all`. In other words:
   First is the source image, then the artist name, and then you
   provide the element for every row. If the remaining rows are all
   the same element, you don't need to repeat it. Thus, if you've
   drawn a sheet full of eyes, just use `perl helpers/cutter.pl
   source4.png alex eyes_all` and you're good. Make sure you use
   `_all` in the filename. That's how the system knows the face
   element can be used for all types of faces.

4. If you think that some of your samples are specific to a particular
   phenotype, add the type to the filename. If you have a beard, for
   example, rename it from `chin_all_1.png` to `chin_man_1.png` or if
   you have ears that are fit for elves only, rename it from
   `ears_all_2.png` to `ears_elf_2.png`.

## PSD to Elements

Up above I said I started with a layer per element. Extract all the
layers to separate files:

```sh
convert Faces.psd Faces.png
```

This generates a PNG fileper layer. Faces-0.png is the visible layer,
Faces-1.png is the white background, Faces-2.png is the empty PNG I
used as a background, the rest are the useful layers. Each one
consists of 5×5 tiles.

I extract the elements from the various layers as follows:

```sh
convert Faces-[34].png -crop "5x5@" +repage eyes_all_%d.png
convert Faces-5.png -crop "5x5@" +repage face_all_%d.png
convert Faces-6.png -crop "5x5@" +repage nose_all_%d.png
convert Faces-7.png -crop "5x5@" +repage mouth_all_%d.png
convert Faces-[89].png -crop "5x5@" +repage ears_all_%d.png
convert Faces-1[01].png -crop "5x5@" +repage chin_all_%d.png
convert Faces-12.png -crop "5x5@" +repage hair_all_%d.png
convert Faces-13.png -crop "5x5@" +repage extra_all_%d.png
```

## Dependencies

The web application depends on [Mojolicious](http://mojolicio.us/)
(`sudo apt-get install libmojolicious-perl`) and
[GD](https://metacpan.org/pod/GD) (`sudo apt-get install libgd-dev`).

The clean up instructions depend on
[ImageMagick](http://www.imagemagick.org/) (`sudo apt-get install
imagemagick`).

## Installation

If you want to edit images using the script ("Face Debugging"), you'll
need to add accounts to the config file. You'll have to create this
file. The file must be called `face-generator.conf` and it must reside
in the current working directory where you run `face-generator`. It
must providing **usernames** and **passwords**. Every artist can have
an account.

Session information is stored in an encrypted cookie. The encryption
for the cookie also depends on a secret, so you should also provide a
**secret** with which the cookie will be encrypted.

Here's an example for the config file, `face.conf`:

```perl
{
  secret => '*a random string*',
  users => {
    'alex' => '*secret*',
    'berta' => '*secret*',
  },
}
```

As the web application is built using
[Mojolicious](http://mojolicio.us/), there are many other ways to
deploy it. There is a
[Cookbook](http://mojolicio.us/perldoc/Mojolicious/Guides/Cookbook#DEPLOYMENT)
with a section on deployment. The following is a quick summary.

This runs the script as a server on `localhost:3000`:

```sh
face-generator daemon
```

This runs the script as a server on `localhost:3000` and reloads it
every time you change one of the files:

```sh
morbo script/face-generator
```

This runs the script as a server on port 8080, writing a pid file:

```sh
hypnotoad script/face-generator
```

Whenever you repeat this `hypnotoad` command, the server will be
restarted. There's no need to kill it.

You can configure `hypnotoad` to listen on a different port by adding
an additional item to the config file:

```perl
{
  hypnotoad => {listen => ['http://*:8082'],},
  secret => '*a random string*',
  users => {
    'alex' => '*secret*',
    'berta' => '*secret*',
  },
}
```

## Prevent horizontal flipping

Sometimes you'll have non-symmetrical faces, like profiles of dragons.
In this case, you should note the type in the config file.

```perl
{
  no_flip => { alex => ['dragon', 'demon'] },
}
```

## Appropriate background image when editing images

When using the `/debug` URLs to edit images, you might not always want
to use the default background image,
[empty.png](https://campaignwiki.org/contrib/empty.png).

You can specify the background image to use via the URL parameter
`empty`. It must name an image in the `share` directory. Example:

* https://campaignwiki.org/face/debug/alex/eyes_dragon?empty=dragon.png

There's a also a way to specify the background image via the config
file. There, a given type is assigned a background image:

```perl
{
  empty => {
    tuiren => {
      gnome => 'dwarf.png' },
    alex => {
      dragon => 'dragon.png',
      elf => 'elf.png',
      dwarf => 'dwarf.png',
      gnome => 'dwarf.png',
      demon => 'demon.png', }},
  no_flip => { alex => ['dragon', 'demon'] },
}
```

Sadly, this only works if the URL matches exactly. This works:

* https://campaignwiki.org/face/debug/alex/dragon

This doesn't work:

* https://campaignwiki.org/face/debug/alex/eyes_dragon

In the second case you need to specify the image to use via the
`empty` parameter as shown above.

## Finding and fixing misaligned elements: the easy way

If you're an artist and you're logged in, the main menu will have a
new item: **Face Debugging**. Follow the link, pick an element type,
view the gallery, pick an element that is misaligned and klick it.
You're now on the Element Edit page. Click on the upper half of the
image to move the element up by ten pixels, click on the lower half of
the image to move the element down by ten pixels.

*Watch out*: This currently breaks if you're not using the standard
450×600 dimensions (e.g. the dragons use 600×450 instead).

## Finding and fixing elements: the hard way

I start the script using morbo and visit the gallery URLs with the
debug parameter set to 1:

```text
http://localhost:3000/gallery/man?debug=1
```

Then I just reload until I find a face where things are misaligned. I
right-click and pick "Show Graphic". This leads me to a link like the
following:

```text
http://localhost:3000/face/alex/empty_all.png,eyes_all_72.png,mouth_all_49.png,chin_man_30.png,ears_all_5.png,nose_all_20.png,hair_man_21.png
```

This shows me which elements were used to create the face I'm looking
at.

If you've found just a single misaligned element, you can change it in
place by providing the same file name twice to
[ImageMagick](http://www.imagemagick.org/):

```sh
convert -page +0+10 -background white -flatten share/alex/chin_man_30.png share/alex/chin_man_30.png
```

If it turns out that you scanned a bunch of elements and they're all
shifted by some amount, you can use the shell to make your life
easier. Here is what I used to shift some old eye elements down by 35
pixels:

```sh
for n in `seq 34`; do
  convert -page +0+35 -background white -flatten share/alex/eyes_all_$n.png eyes_all_$n.png
done
```

This will create copies in your current directory. If you're happy,
move them back into the elements folder.

If you need help figuring out by how much you might want to shift
images, you can use `top.pl` and `bottom.pl`. They cound how many
white lines there are at the top and at the bottom, respectively.

Example usage:

```sh
perl helpers/top.pl share/alex/eyes_all_*
```

## Alternative look

For [my images](https://campaignwiki.org/face/view/alex/random) I
enforced a blue color map because I was doing my drawings using a blue
fountain pen. This is the command line I used in my example above:
`convert -blur 0x1 +dither -remap blau.png scan1.jpg source1.png`

If you do your drawings using a pencil, you might want to keep the
pencil look. I'll suggest the following command line: `convert -blur
0x1 +dither -level 30%,80% scan1.jpg source1.png`. Like in the
previous example, I used a 1px blur and then I adjusted levels:
anything below 30% is black and anything above 80% is white. It looks
OK. No trace of the helping lines left and it keeps the pencil gray.

If you do your drawings using a pencil but you'd like to give it an
inked look, you migh want to increase the percentage for the black
level. I'll suggest the following comand line: `convert -blur 0x1
+dither -level 50%,80% -grayscale rec709luma scan1.jpg source1.png`.
Now anything below 50% is black. I also converted it to grayscale at
the end because the very light pixles seemed to have random colors.

## Transparency and Opacity

Sometimes you want white to be opaque. You would like to have hair
that covers a face, or a hat that covers the face. One solution is to
use *nearly white*. It's hard to work with, however. When you open the
element in Gimp, you can't tell which sectinos are white and which
ones are nearly white. In this case, use transparency. In Gimp:

1. Layer → Transparency → Add Alpha Channel
2. Choose the magic wand using `u`
3. Set the tool options to *no* antialiasing and use a threshold of 0.0
4. Select the white background with a click and cut it away (Edit → Cut)
5. Any remaining white will remain opaque, which is probably OK

Now you're ready to change some light colors to white, if you want to.

There's a little helper script to identify transparent images, if you
need it.

Example usage:

```sh
helpers/transparent.pl share/rorschachhamster/*.png
```

## Darkness

At one point I wanted to darken all the earlier elements I had drawn
to make them more similar to the newer images I had drawn.

```sh
for f in $(ls *woman* *man* *all* *squid* *orc* *elf* *dwarf*|sort|uniq); do
  convert -level 0,100%,0.6 -blur 0x1 +dither -remap ../../blau.png $f x.png && mv x.png $f
done
```
