Categories

RSS

A few people have expressed interest in how Wavatars are made. Here is the long boring explanation for those overly curious souls. Again, if you want the WordPress plugin, go for it. If you want to adapt it for non-Wordpress use, help yourself.

All of the following is done in PHP: This isn’t exacly the most complex process in the world. Pretty simple, but the results are amusing to me.

Step 1 is to generate an 80×80 blank PNG using imagecreatetruecolor (). That image is then flood filled a color of a random hue (max saturation, low lightness value) with imagefill ().

Step 2 selects a random “fade” pattern from a possible 4. This is a simple white PNG with a gradient mask that will cause the background to fade from that base color to white. This makes the icon a little more interesting, and adds some variety.

Step 3 selects a random face shape from the possible 9. It loads in the mask of the chosen face and slaps it into place. I have a black border on the mask, because that looks nice.

Step 4 selects a color for the head. Again, this is a random hue, max saturation, high lightness value. It then flood fills the image starting in the very center at 40, 40. Note that this creates an interesting limitation. The face has to be a single enclosed polygon that covers the center. This means you couldn’t make a head from two shapes which weren’t touching, and you couldn’t make a shape with a hole right in the middle

I could get around these limits by using imagefilter (IMG_FILTER_COLORIZE) instead of imagefill (), but I found that not all setups of PHP will support this, and that if it fails the wavatar will come out white. I figured portable, functional code was more important than something which would silently fail in confusing and unrecoverable ways for some users.

For each mask shape, (circle, triangle, square, etc) I have a matching “shine” filter. This is another gradient-masked PNG of pure white, which is used to make the shape look glossy. It’s totally opaque in the areas with lots of shine, low transparency accross the main surface, and fully transparent where the “shadows” should be. I made these using the “emboss” tool in Paint Shop Pro 8.

Step 5 puts this shine image into place. Note that this step is optional. (You’ll need to have the know-how to edit the source if you want to skip it, though.) If you skip it, the Wavatars will look a little more cartoony and a little less like they’re made of iPod plastic.

Step 6 selects a random set of eyebrows and slaps them on. No fancy filters or coloring this time. The brows go on before the other features so that they will appear “behind” eyeglasses.

Step 7 selects a random set of empty eyes / eyeglasses and slaps them into place.

Step 8 selects a set of pupils and adds them.

Step 9 adds the mouth.

The last step is to resample the image from the default size to the icon size the user selected (assuming they differ) and save the resulting image to disk.

That’s it. All done. You could, if you wanted, add all kinds of additional shapes to any of the categories, or replace ones you don’t like. If you change the number of available images, you’ll have to edit the source code so that the plugin knows how many images are available. Don’t worry – you can do this even if you don’t know PHP. Just look inside of wavatars.php and near the top you’ll see a few lines:

Very nice, Shamus.
As a Microsoft technologies dev, this almost makes me want to look into PHP. On-the-fly image generation can be a pain. Looks like PHP has some powerful tools for it.
So, how long do you cache these files on disk? Couldn’t you be opening yourself up to a DOS attack if you don’t manage the files properly? Just a thought.

I’m still experimenting with different things after the + to get different things.. any time I already have something to say I try something different, sooner or later I’ll hit on the ultimate wavatar (then use it forever) :D

I’m not a programmer, so many of the things I see online I take for granted (or used to until I started reading this blog!) but seeing this wavatars explanation really puts it in perspective for me. That seems like a lot of steps and so much work to get one made! Kudos to you programmers!

PHP is an awesome language, especially for beginners. It’s so easy to just borrow a little code from somewhere and manipulate it just slightly to fit your purposes.

People are usually very put off by “computer programming” because it sounds difficult, but really anybody can learn it. In my opinion, the most difficult part of PHP is the sysadmin part. Tweaking esoteric config files, folder read-write permissions…that stuff is way more complicated for your average newcomer than the actual code is.

I would have prefared this guide before I went through and recomented your code shamus, but thanks anyway.

oh, I have another error(although not a massive one), if the image has a size that’s odd then dividing it by to produces a float(to handle the decimal), this causes errors when you attempt to make your fill from the center of the image on images with odd dimentions. the obvious solution is to simply reparse these as integers:imagefill($avatar, (int)(AVATAR_SIZE / 2),(int)(AVATAR_SIZE / 2),$bg);

(I apologise in advance for the question if it’s stupid, but sadly I’m not particularly well-versed in server-side languages like PHP)

Following on from Cadamar’s question above, how are you managing to store these images? Are you storing them on your server? If so, surely that has the potential to run to quite impressive sizes, especially when you include the fact that you also need to store references for which email address the wavatar corresponds to.

@Phlux: I disagree. I actually find PHP to be painful to use after using just about anything else. It just reeks of poor planning to me, especially with the sheer number of ways to break code simply by changing the configuration file. Let’s not even talk about the extreme pain I went through thanks to PHP’s safe_mode feature on my last web host. That broke 95% of the PHP applications I used in some way.

I probably wouldn’t be so bitter about it if your average PHP user didn’t act like a zealot. Not saying that you or anyone here does that, but take a look at any blog criticizing any part of PHP and you’ll see what I mean. ;)

Assuming every page on your blog has been viewed since installing wavatars, there will be one icon file for each unique person in the comments.

On a busy site like mine, this does indeed add up to a lot of files. I currently have ~5,200 in the cache. At 4k each, that comes out to ~20MB. That is indeed a lot, but keep in mind that’s for a three-year old site with massive comment threads. You can dump the cache as often as you like, but keep in mind the icons would be re-created as soon as they were needed again.

No other info is needed to match the email to the icon, as that is done on the fly.

So, what, does this generate an avatar the first time we post and then tie it to our email? Or does it hash the email address and generate an avatar based on this code? When I read “portability” I assumed it would be “based” on the email like this rather than just generated at random and linked.

When you enter your email, it does an md5 hash on it. In simple terms: readable text goes in, gibberish comes out. However, it’s deterministic gibberish.

You enter your email: someguy@someplace.com
And it churns out a huge string of characters: “0a8b4eeab8249b2038e34f27d67c” and so on. I take this value and chop it off at 17 characters, since that’s all I need.

That email will ALWAYS produce the same gibberish. When it encounters a post, it gets the hash and looks to see if “0a8b4eeab8249b20.png” exists. If not, it creates it. Each pair of digits defines one of the steps above. Perhaps the “0a” will lead to a blue background while a “3b” would give you yellow. Whatever.

Damn you Shamus. Now I just have to post to find out what I look like. :D
Very cool stuff though. Looks very neat too.
I know that hattrick.org used some similar tactic on their player-images when I was playing that. But they actually layered a bunch of HTML divs and images on top of each other to create the face in the browser instead of storing the final image on the server…

Oh thank you very much. You’ve now gone and forced (yes, showing me something cute like this counts as forcing, I have a very low Will save) me to add “Port Wavatars to Perl” to my exceptionally long TODO list!

One suggestion I would make is to use the MD5SUM as input data instead of random numbers. That way, if two sites implemented Wavatars, and used the same set of shapes on the backend, then anyone commenting on both sites would get the same Wavatar on each.

Since my first (real) experience programming was C-style, I find programming languages like PERL, PHP, LISP, BASIC, etc. to be especially jarring if I haven’t used them in a while. The weird thing is that even though I can immediately read the code and understand what it is doing, I get these amazing headaches if I have to transition from Java/C to PHP or back. It’s a little like trying to go back and forth between reading English and Latin. I have this strange physical reaction for a day or two then it goes away while I’m constantly exposed. If I go a week or two without exposure, bang, instant headache when I try to flip back around.

OK, in order to make this not “just anoher test”, I’ll actually write something:

Shamus, I like the new layout even if you use boxes… I have so far only looked at the “black text on white background”. I’m also glad that the dice no longer break the comments (they used to start when the dice ended). Now, I’d probably better get back to working…

Shamus, I was wondering what you used to map from email address to input for the selection algorithm. I was half suspecting an MD5 hash of the email, used as a seed for a PRNG, but I must say that simply chopping enough bits out and use that (with, I suspect, using modulus to bring it into raneg for each choice) is more elegant, in its own twisted way.

I see that the CAPTCHA has been redesigned, the new style is more… printed than the previous rather flowing one.