Search code examples
photoshopextendscript

Making an Auto Export Script for Photoshop


I'm trying to write a script for Photoshop that reads a specified text file for the layers that it needs to make visable and the filename to which it will be exported as. Then it untoggles everything and moves onto the next entry. So far I have -

// Create Trim function
function trim(str) {
    return str.replace(/^\s+|\s+$/g, '');
}

// Turn on all groups in document
var doc = app.activeDocument;
var allGroups = doc.layerSets;
for (var i = 0; i < allGroups.length; i++) {
    allGroups[i].visible = true;
}   



// Open the input file and read each line
var inputFile = File.openDialog("Select input file");
inputFile.open("r");
var inputLines = inputFile.read().split("\n");
inputFile.close();

// Loop through each line in the input file
for (var k = 0; k < inputLines.length; k++) {
  var inputLine = trim(inputLines[k]);

  // Split the line into layer names and filename
  var inputs = inputLine.split("|");
  var layerNames = inputs[0].split(",");
  var filename = inputs[1];

  // Loop through all layers in the document
  for (var i = 0; i < app.activeDocument.layers.length; i++)
  {
    var layer = app.activeDocument.layers[i];

    var idx = get_index(layerNames, layer.name);

    // Toggle visibility for layers with matching names
    // if (namesArray.indexOf(layer.name) >= 0) 
    if (idx >= 0) 
    {
      layer.visible = !layer.visible;
    }
    
    function get_index(arr, str)
    {
      for (var i = 0; i < arr.length; i++)
      {
        if (arr[i] == str) return i;
      }
    }       
  }
         
  // Export the PNG file
  var pngFile = new File("filepath" + "/" + filename + ".png");
  var opts = new ExportOptionsSaveForWeb()
  opts.format = SaveDocumentType.PNG;
  opts.PNG8 = false;
  opts.colorProfileName = "ICC Profile Name";
  opts.quality = 100;
  app.activeDocument.exportDocument(pngFile, ExportType.SAVEFORWEB, opts);

    
  // Untoggle all layers and groups
  for (var i = app.activeDocument.layers.length - 1; i >= 0; i--) {
    var layer = app.activeDocument.layers[i];

    // If the layer is a group, loop through its layers
    if (layer.typename == "LayerSet") {
      for (var j = layer.layers.length - 1; j >= 0; j--) {
        var subLayer = layer.layers[j];

        // Turn off visibility for each layer inside the group
        subLayer.visible = false;
      }
    }

    // Turn off visibility for the layer itself
    layer.visible = false;
  }
}

However, when I run the script it ends up exporting blank pngs. I was wondering how do I go about fixing this script and also changing the export options to better match those in Photoshop's "Export As" menu as opposed to the "Save for Web" one.


Solution

  • I just tried to rewrite the script. Now it hides and unhides layers with recursive functions. I hope it will fix the 'blank pngs':

    var inputFile = File.openDialog("Select input file");
    inputFile.open("r");
    var inputLines = inputFile.read().split("\n");
    inputFile.close();
    
    var filepath = inputFile.parent;
    
    var opts     = new ExportOptionsSaveForWeb();
    opts.format  = SaveDocumentType.PNG;
    opts.PNG8    = false;
    opts.quality = 100;
    opts.colorProfileName = "ICC Profile Name";
    
    for (var k = 0; k < inputLines.length; k++) {
        var inputLine  = inputLines[k].replace(/^\s+|\s+$/g, "");
        var inputs     = inputLine.split("|");
        var layerNames = inputs[0].split(",");
        var filename   = inputs[1];
    
        hide_all_layers();
        for (var i=0; i<layerNames.length; i++) unhide_layer(layerNames[i]);
    
        var pngFile = new File(filepath + "/" + filename + ".png");
        app.activeDocument.exportDocument(pngFile, ExportType.SAVEFORWEB, opts);
    }
    
    
    // ------------------------------------------------------------------
    
    function hide_all_layers(item) {
        if (!item) var item = app.activeDocument;
        var layers = item.layers;
        for (var i=0; i<layers.length; i++) {
            var layer = layers[i];
            layer.visible = false;
            if (layer.typename == "LayerSet") hide_all_layers(layer);
        }
    }
    
    function unhide_layer(name, item) {
        if (!item) var item = app.activeDocument;
        var layers = item.layers;
        for (var i=0; i<layers.length; i++) {
            var layer = layers[i];
            if (layer.name == name) layer.visible = true;
            if (layer.typename == "LayerSet") {
                layer.visible = true;
                unhide_layer(name, layer);
            }
        }
    }
    

    As for 'changing the export options to better match those in Photoshop's "Export As" menu' I'm not sure what exactly you do mean. Do you need some additional export options?


    Update

    Rather for educational purpose, here is the less verbose and a little bit more efficient variant of the script:

    var inputFile = File.openDialog('Select input file');
    inputFile.open('r');
    var inputLines = inputFile.read().split('\n');
    inputFile.close();
    
    var filepath = inputFile.parent;
    
    var opts     = new ExportOptionsSaveForWeb();
    opts.format  = SaveDocumentType.PNG;
    opts.PNG8    = false;
    opts.quality = 100;
    opts.colorProfileName = 'ICC Profile Name';
    
    var layers = save_visibility();
    
    while (inputLines.length) {
        var inputs     = inputLines.pop().replace(/^\s+|\s+$/g, '').split('|');
        var filename   = inputs.pop();
        var layerNames = inputs.pop().split(',');
    
        hide_all_layers();
        while (layerNames.length) show_layer(layerNames.pop());
    
        var pngFile = new File(filepath + '/' + filename + '.png');
        app.activeDocument.exportDocument(pngFile, ExportType.SAVEFORWEB, opts);
    }
    
    restore_visibility(layers);
    
    // ------------------------------------------------------------------
    
    function hide_all_layers(item) {
        if (!item) var item = app.activeDocument;
        for (var i=0; i<item.layers.length; i++) {
            item.layers[i].visible = false;
            try { hide_all_layers(item.layers[i]) } catch(e) {}
        }
    }
    
    function show_layer(name, item) {
        if (!item) var item = app.activeDocument;
        try { item.visible = true } catch(e) {}
        try { item.layers.getByName(name).visible = true } catch(e) {}
        for (var i=0; i<item.layerSets.length; i++)
            show_layer(name, item.layerSets[i]);
    }
    
    function save_visibility(item, arr) {
        if (!item) var item = app.activeDocument;
        if (!arr) var arr = [];
        for (var i=0; i<item.layers.length; i++) {
            arr.push([item.layers[i], item.layers[i].visible]);
            try { save_visibility(item.layers[i], arr) } catch(e) {}
        }
        return arr;
    }
    
    function restore_visibility(arr) {
        for (var i=0; i<arr.length; i++) arr[i][0].visible = arr[i][1];
    }
    

    It does exactly the same, plus it keeps the original visibility all of the layers.