﻿//#target photoshop
/**
 * Export Layer names into web optimized images
 *
 * Author: Aaron McGuire (samcreate.com)
 * Twitter: @samcreate
 *
 * Feel free to share/reuse/modify to your hearts content. Attribution would be nice but
 * is not required.
 *
 */

var wizbang = {};

wizbang.global = {
    original_doc: app.activeDocument,
    export_folder: null
};

wizbang.util = function () {

    var self = {
        rasterizeLayerStyle: function () {
            var idrasterizeLayer = stringIDToTypeID("rasterizeLayer");
            var desc5 = new ActionDescriptor();
            var idnull = charIDToTypeID("null");
            var ref4 = new ActionReference();
            var idLyr = charIDToTypeID("Lyr ");
            var idOrdn = charIDToTypeID("Ordn");
            var idTrgt = charIDToTypeID("Trgt");
            ref4.putEnumerated(idLyr, idOrdn, idTrgt);
            desc5.putReference(idnull, ref4);
            var idWhat = charIDToTypeID("What");
            var idrasterizeItem = stringIDToTypeID("rasterizeItem");
            var idlayerStyle = stringIDToTypeID("layerStyle");
            desc5.putEnumerated(idWhat, idrasterizeItem, idlayerStyle);
            executeAction(idrasterizeLayer, desc5, DialogModes.NO);
        },

        getWH: function (layer) {
            var width = (layer.bounds[2] - layer.bounds[0]);
            var height = (layer.bounds[3] - layer.bounds[1]);
            return {
                w: width,
                h: height
            };
        },

        hexToRgb: function (hex) {
            var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
            return result ? {
                r: parseInt(result[1], 16),
                g: parseInt(result[2], 16),
                b: parseInt(result[3], 16)
            } : null;
        },
        dup_doc: function (w, h, layer, retina, uopt) {
            app.activeDocument = wizbang.global.original_doc;
            wizbang.global.original_doc.activeLayer = layer;
            var activeLay = wizbang.global.original_doc.activeLayer;
            var newLayer = activeLay.duplicate();
            var scale = (retina == true ? 2 : 1);
            newLayer.name = "Wizurd Spell";
            wizbang.global.original_doc.activeLayer = newLayer;
            newLayer.translate(new UnitValue(0 - newLayer.bounds[0].as('px'), 'px'), new UnitValue(0 - newLayer.bounds[1].as('px'), 'px'));
 
            self.resizeLayerInPixels(newLayer, uopt.w, uopt.h, false);
            
            if (retina) {
                newLayer.resize(200, 200, AnchorPosition.TOPLEFT);
            }
        

            newLayer.rasterize(RasterizeType.ENTIRELAYER);
            wizbang.util.rasterizeLayerStyle();
            newLayer.copy();
            var myNewDoc = app.documents.add(w * scale, h * scale, 72, "WizurdMagik", NewDocumentMode.RGB, DocumentFill.TRANSPARENT);
            var targetLayer = myNewDoc.artLayers.add();
            myNewDoc.paste();
            targetLayer.opacity = activeLay.opacity;
            myNewDoc.trim(TrimType.TRANSPARENT);
            app.activeDocument = wizbang.global.original_doc;
            newLayer.remove();
            return myNewDoc;

        },
        trim: function (str) {
            return str.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
        },
        resizeLayerInPixels : function(Layer,Width , Height, Constrain){
   
            var startRulerUnits = preferences.rulerUnits;
            preferences.rulerUnits = Units.PIXELS;
            var LB = Layer.bounds;
            var lWidth = 100/(LB[2].value - LB[0].value);
            var lHeight =100/(LB[3].value - LB[1].value);
            var NewWidth = lWidth * Width;
            var NewHeight = lHeight * Height;
            if(Constrain) NewHeight = NewWidth;
            Layer.resize(Number(NewWidth),Number(NewHeight),AnchorPosition.MIDDLECENTER); 
            app.preferences.rulerUnits = startRulerUnits;
        }


    };

    return self;

}();

wizbang.imageTypes = function () {

    var self = {
        export_png: function (layer, imageName, uopt) {
            var size = wizbang.util.getWH(layer);
            

            //setup for user specified options
            uopt.png8 = uopt.png8 || false;
            uopt.matte = uopt.matte || false;
            uopt.retina = uopt.retina || false;
            uopt.w = uopt.w || size.w;
            uopt.h = uopt.h || size.h;
            
            var doc = wizbang.util.dup_doc(size.w, size.h, layer, false, uopt);


            //Options to export to PNG files
            var options = new ExportOptionsSaveForWeb();
            options.format = SaveDocumentType.PNG;
            options.PNG8 = uopt.png8;

            if (uopt.matte) {
                var colors = wizbang.util.hexToRgb(uopt.matte);
                var matteColor = new RGBColor();
                matteColor.red = colors.r;
                matteColor.green = colors.g;
                matteColor.blue = colors.b;
                options.matteColor = matteColor;
            }

            options.transparency = uopt.transparency || true;

            finish(doc, imageName, options, uopt, size, layer);

            $.writeln("export_png called! name: " + imageName);
        },
        export_jpg: function (layer, imageName, uopt) {
           
            var size = wizbang.util.getWH(layer);
            

            //setup for user specified options
            uopt.retina = uopt.retina || false;
            uopt.quality = uopt.quality || 80;
            uopt.w = uopt.w || size.w;
            uopt.h = uopt.h || size.h;
            

            var doc = wizbang.util.dup_doc(size.w, size.h, layer, false, uopt);
            
           

            var options = new ExportOptionsSaveForWeb();
            options.format = SaveDocumentType.JPEG;
            options.quality = uopt.quality;

            finish(doc, imageName, options, uopt, size, layer);

            $.writeln("export_jpg called! name: " + imageName);
        },
        export_gif: function (layer, imageName, uopt) {
            var size = wizbang.util.getWH(layer);
            
            var options = new ExportOptionsSaveForWeb();

            //setup for user specified options
            uopt.retina = uopt.retina || false;
            uopt.matte = uopt.matte || false;
            uopt.w = uopt.w || size.w; 
            uopt.h = uopt.h || size.h;
            
            
            var doc = wizbang.util.dup_doc(size.w, size.h, layer,false, uopt);

            options.ditherAmount = 0;
            options.dither = Dither.NOISE;
            options.palette = Palette.LOCALADAPTIVE;
            options.format = SaveDocumentType.COMPUSERVEGIF;

            if (uopt.matte) {
                var colors = wizbang.util.hexToRgb(uopt.matte);
                var matteColor = new RGBColor();
                matteColor.red = colors.r;
                matteColor.green = colors.g;
                matteColor.blue = colors.b;
                options.matteColor = matteColor;
            }

            finish(doc, imageName, options, uopt, size, layer);

            $.writeln("export_gif called! name: " + imageName);
        }
    };

    return self;

    function finish(doc, imageName, options, uopt, size, layer) {
        wizbang.app.final_save_step(doc, imageName, options);
        if (uopt.retina) {
            var retina_doc = wizbang.util.dup_doc(size.w, size.h, layer, true, uopt);
            wizbang.app.final_save_step(retina_doc, imageName, options, true);
        }
    }


}();


wizbang.app = function () {
    var flag = 0;
    var self = {
        run: function () {
            
            wizbang.global.export_folder = Folder.selectDialog("Select a folder to export images");
            
            if(wizbang.global.export_folder != null){
                findImageLayers(activeDocument);
                $.sleep(2000);
                alert('Wizbang: Finished Export!');
            }else{
                alert('Wizbang: Export Canceled!');
            }
            
        },
        final_save_step: function (doc, imageName, options, retina) {
            app.activeDocument = doc;

            if (retina) {
                var first = imageName.substring(0, imageName.length - 4);
                var last = imageName.substring(imageName.length - 4, imageName.length);
                imageName = first + '@2x' + last;
            }
            imageName = wizbang.util.trim(imageName);
            doc.exportDocument(File(wizbang.global.export_folder + '/' + imageName), ExportType.SAVEFORWEB, options);
            doc.close(SaveOptions.DONOTSAVECHANGES);
            app.activeDocument = wizbang.global.original_doc;
        }
    };

    return self;

    function findImageLayers(ref) {
        // declare local variables      
        var layers = ref.layers;
        var len = layers.length;
        for (var i = 0; i < len; i++) {
            var layer = layers[i];
            // if layer is a "group" let's loop through it's contents
            if (layer.typename == 'LayerSet') {
                findImageLayers(layer);
            } else {
                //check if layer name is an image, if so continue
                var isImage = new RegExp(/\.(gif|jpg|jpeg|tiff|png)$/i);

                if (isImage.test(layer.name) && layer.visible) {
                    
                    //let's extract the image name the extendsion off the name and use
                    //use it to concatinate a function name e.g. export_png
                    var name_parts = layer.name.split('.');
                    var type = name_parts[(name_parts.length - 1)];
                    var export_function = "export_" + type.toLowerCase();
                    
                    //let's extract the options the layer name (if any)
                    var options = layer.name.match(/\{(.*?)\}/);
                    var imageName = layer.name.split('}')[1] || layer.name;
                    
                    //let's try to turn the the 'options' string into a real javascript object, else
                    //just make a blank object
                    try {
                        var options = eval("(" + options[0] + ")");
                    } catch (e) {
                        var options = {};
                    }
                    
                    //let's try and call our concatinated function name and throw it the layer, and name for processing.
                    try {
                        if (flag == 0) {
                            //flag = 1;
                            wizbang.imageTypes[export_function](layer, imageName, options);

                        }
                    } catch (e) {
                        $.writeln(e);
                    }

                } //eof else


            } // eof loop
        }
    }



}();

//this disables all of our programmed actions from being recorded in photoshop history, as well as init's the app
app.activeDocument.suspendHistory('Wizbang Export', 'wizbang.app.run()');