Source: apc-static/task/worker/generate_theme_favicon_files.js

/**
 * Generate theme favicon files.
 * @function task.worker.generateThemeFaviconFiles
 * @param {object} config - Task configuration
 * @param {string} config.destDir - Destination directory.
 * @param {string} config.letter - A letter to print on favicon.
 * @param {number} [config.size=256] - favicon size.
 * @param {number} [config.count=12] - Number of favicons to generate.
 * @param {number[]} [config.rounds=[0,40,80]] - Corner radius patterns.
 * @param {number[]} [config.borders=[0,10,20]] - Border width patterns.
 * @param {function} callback - Callback when done.
 * @author Taka Okunishi
 */
var path = require('path'),
    util = require('util'),
    format = util.format,
    lib = require('../../lib'),
    image = lib.image,
    array = lib.array,
    file = lib.file,
    mkdirP = file.mkdirP,
    debug = require('./_debug'),
    shuffled = array.shuffled,
    _themeNameForIndex = require('./_theme_name_for_index'),
    text2image = image.text2image,
    apeman = require('apeman'),
    _randomColor = require('./_random_color'),
    _randomFont = require('./_random_font');

exports = module.exports = function (config, callback) {
    var destDir = path.resolve(config.destDir),
        size = config.size || 256,
        appName = apeman.current.meta().name,
        count = config.count || 12,
        rounds = config.rounds || [0, 40, 80],
        borders = config.borders || [0, 10, 20];

    var favLetter = config.letter = (function (appName) {
        var names = appName.split('-');
        names.shift(); //Ignore prefix
        var name = names.shift();
        return name && name[0];
    })(appName);
    mkdirP(destDir, function (err) {
        if (err) {
            callback(err);
            return;
        }
        require('async').series(
            exports._faviconData(size, rounds, borders, count).map(function (data, i) {
                return function (callback) {
                    var dest = path.resolve(destDir, exports._nameFaviconFile(i));
                    text2image(
                        favLetter,
                        dest,
                        data,
                        function (err) {
                            if (!err) {
                                debug.didCreateFile(dest);
                            }
                            setTimeout(function () {
                                callback(err);
                            }, 10);
                        }
                    )
                }
            }),
            function (err) {
                callback(err);
            }
        );
    });
};

exports._nameFaviconFile = function (i) {
    var themeName = _themeNameForIndex(i);
    return format('favicon-theme-%s.png', themeName);
};

exports._faviconData = function (size, rounds, borders, count) {
    var data = [];
    for (var i = 0; i < count; i++) {
        var fontFile = _randomFont().filename,
            themeColor = _randomColor(),
            borderWidth = shuffled(borders).shift(),
            round = shuffled(rounds).shift();

        var colors = [ themeColor, '#FFF'];
        colors = colors.sort(function (a, b) {
            return Math.random() - Math.random();
        });

        data.push({
            backgroundColor: colors[0],
            width: size,
            height: size,
            fontSize: size,
            color: colors[1],
            fontFile: fontFile,
            borderWidth: borderWidth,
            borderColor: themeColor,
            cornerRadius: round
        });
    }
    return data;
};