konstantinbueschel
7/27/2013 - 6:33 PM

Automatically generate non-retina and Android images for Alloy projects

Automatically generate non-retina and Android images for Alloy projects

function downsize(event, logger) {
    var wrench = require("wrench"),
        path = require("path"),
        fs = require("fs"),
        imagemagick = require("imagemagick"),
        U = require('../../utils');

    // Generator

    function generator(source, target, percentage) {

        // File (or 9-patch version) doesn't exist or (non 9-patch) file is older
        if (!fs.existsSync(target.replace(/(\.png)$/, '.9$1')) && (!fs.existsSync(target) || (fs.statSync(source).mtime > fs.statSync(target).mtime))) {

            if (percentage === '100%') {
                logger.info('Copying: ' + target);
                U.copyFileSync(source, target);

            } else {
                logger.info('Downsizing ' + percentage + ': ' + target);

                var target_dir = path.dirname(target);

                if (!path.existsSync(target_dir)) {
                    wrench.mkdirSyncRecursive(target_dir, 0777);
                }

                imagemagick.convert([source, '-resize', percentage, target], function(error, m) {
                    error && logger.error('Failed generating "' + target + '" because of: ' + error.message);
                });
            }
        }
    }

    // Walker

    function walk(dir) {
        wrench.readdirSyncRecursive(dir).forEach(function(file) {

            // Catch retina files, except for iPhone 5 (retina only) ones
            if (file.indexOf('@2x') > 0 && file.indexOf('-568h@2x') < 0) {
                var source = path.join(dir, file);
                var target = path.join(dir, file.replace('@2x', ''));

                // iOS
                if (event.alloyConfig.platform === 'ios') {

                    // Non-retina
                    generator(source, target, '50%');

                    // Android
                } else if (event.alloyConfig.platform === 'android') {
                    target = target.replace(/(\/iphone)?(\/images)(\/.+\/)?(.+)$/, '/android$2/_DENSITY_$3$4');

                    // xhdpi
                    generator(source, target.replace('_DENSITY_', 'res-xhdpi'), '100%');

                    // hdpi
                    generator(source, target.replace('_DENSITY_', 'res-hdpi'), '75%');

                    // mdpi
                    generator(source, target.replace('_DENSITY_', 'res-mdpi'), '50%');
                }
            }
        });
    }

    // Un-retina /app to find main assets as well as in themes and widgets
    walk(event.dir.home);
}

task("pre:load", function(event, logger) {
    downsize(event, logger);
});

UPDATE: With the assets command of the TiCons CLI / Module this can be done even simpeler by calling $ ticons assets or an alloy.ymk using:

task("pre:load", function(event, logger) {
    require('ticons').assets();
});

Automatically generate non-retina and Android images for Alloy projects

This [Alloy Build Configuration File](http://docs.appcelerator.com/titanium/3.0/#!/guide/Build_Configuration_File_(alloy.jmk) automatically generates non-retina and Android XHDPI, HDPI and MDPI images for all new and changed retina (@2x) images before each compile.

Read more about it at: http://fokkezb.nl/2013/07/29/generate-non-retina-images/