Skip navigation
Currently Being Moderated

export multiple images with random layers

Jul 27, 2012 8:15 PM

Tags: #photoshop #save #script #export #png #layer #layers #photoshop_scripting #variations #photoship_cs5

I have this texture file that has many different variations to it. (3 different kinds of pants, different hairpieces, some optional items, etc...)

What i want to do, is export it with random layers selected. (there are also folders inside, it's fine if i have to merge the folder into a single layer, but it would be better if it could treat the folders as a layer)

There are 2 layers that must always be on,

then there are 6 other layers that can be mixed and matched completely at random.

Finally: there are 3 layers that only one of them can be active at one time (if one is active, the other 2 cannot be). Those last 3 layers I wouldn't mind if i had to go through manually and remove the combinations that couldn't work, but it would be much better to have it automatic.

Is there any way to script this so that it exports all of these textures as *filename*_*variation#*.png

 
Replies
  • Currently Being Moderated
    Jul 28, 2012 2:35 AM   in reply to Johnathan A. M.

    What i want to do, is export it with random layers selected.

    What difference will selecting a Layer make for Exporting? Did you mean »visible«?

     

    Is there any way to script this so that it exports all of these textures as *filename*_*variation#*.png

    One can Script that, but how experienced are you with JavaScript?

     

    Please post a screenshot of the Layers Panel or the file itself.

     
    |
    Mark as:
  • Currently Being Moderated
    Aug 3, 2012 8:52 AM   in reply to Johnathan A. M.

    The screenshot shows the results I get with the Script farther down below on the last file in the screenshot (each number being on a layer of its own, 1 being the lowest of them, 9 the topmost).

     

    The function needs these arguments

    • an array of layers (and arrays),

    • the minimum number of layers,

    • the maximum number of layers (of the elements in the array at position 0) and

    • a number to give the index of the layer in the array that must be shown – if no specific layer is needed insert some String.

    If the array contains an array that needs like content as the function will be tun on that.

     

    In the example the array contains layers 6, 5, 4, 3, 2 and an array with an array containing the layers 9, 8, 7 and baseLayer 0 (referring to the first of those), so if that array is used 9 will be visible.

     

    minimal and maximal only refer to the array and don’t take the contents of additional arrays into account.

     

    So you can set up the arrays according to your needs and give it a try (if you haven’t already performed the task manually).

     

    Edit: Existing files of the same resulting names will be overwritten without prompting.

    randomLayerVisibilityScr.jpg

    // 2012, use it at your own risk;
    #target photoshop
    if (app.documents.length > 0) {
    var myDocument = app.activeDocument;
    // getting the name and location;
    var docName = myDocument.name;
    var basename = docName.match(/(.*)\.[^\.]+$/)[1];
    var docPath = myDocument.path;
    // set up the arrays of layers;
    var theLayers = myDocument.layers;
    var theArray2 = [[theLayers[0], theLayers[1], theLayers[2]], 1, 3, 0];
    var theArray = [theArray2, theLayers[3], theLayers[4], theLayers[5], theLayers[6], theLayers[7]];
    // randomize and save png;
    for (var p = 1; p < 21; p++) {
              RandomShow (theArray, 1, 5, "no");
              savePNG (myDocument, docPath, basename, p)
              }
    };
    ////// randomly show layers; baselayer is the index in thearray of a layer that has to be shown //////
    function RandomShow (theArray, minimal, maximal, baseLayer) {
    var theCounter = 0;
    if (minimal > theArray.length || maximal > theArray.length) {alert ("nonsense")}
    else {
    // create array of numbers without baselayer;
              var numbersArray = new Array;
              for (var m = 0; m < theArray.length; m++) {
                        if (m != baseLayer) {
                                  numbersArray.push(m);
                                  };
                        };
    //  hide layers;
              hideLayers(theArray);
    // show the baselayer;
    if (baseLayer.constructor == Number) {
              theArray[baseLayer].visible = true;
              maximal--
              };
    // number of layers to show;
              var theNumber = minimal + Math.floor( Math.random() * (maximal - minimal + 1) );
    // shuffle the array of numbers;
              arrayShuffle(numbersArray);
    // take the first x numbers;
              for (var n = 0; n < theNumber; n++) {
                        var theObject = theArray[numbersArray[n]];
                        if (theObject.constructor != Array) {
                                  theObject.visible = true;
                                  }
                        else {
                                  RandomShow (theObject[0], theObject[1], theObject[2], theObject[3])
                                  }
                        };
              }
    };
    ////// hide the layers in an array of layers //////
    function hideLayers (anArray) {
              try {
                        for (var o = 0; o < anArray.length; o++) {
                                  if (anArray[o].constructor != Array) {anArray[o].visible = false}
                                  else {hideLayers (anArray[o])}
                                  }
                        }
              catch (e) {}
              };
    ////// shuffle the items in an array //////
    // http://www.hardcode.nl/subcategory_1/article_317-array-shuffle-function
    function arrayShuffle(theArray) {
              var len = theArray.length;
              var i = len;
              while (i--) {
                        var p = parseInt(Math.random()*len);
                        var t = theArray[i];
                        theArray[i] = theArray[p];
                        theArray[p] = t;
              }
    };
    ////// function to png //////
    function savePNG (myDocument, docPath, basename, theSuffix) {
    // weboptions;
    var webOptions = new ExportOptionsSaveForWeb();
    webOptions.format = SaveDocumentType.PNG;
    webOptions.PNG8 = false; 
    webOptions.transparency = true;
    webOptions.interlaced = 0;
    webOptions.includeProfile = false;
    webOptions.optimized = true;
    myDocument.exportDocument(new File(docPath+"/"+basename+"_"+theSuffix+".png"), ExportType.SAVEFORWEB, webOptions);
    };
    
     
    |
    Mark as:
  • Currently Being Moderated
    Aug 4, 2012 1:48 AM   in reply to Johnathan A. M.

    -the first 8 lines just make sure there is a valid document open, and if there is, find out the file path and everything

    Correct.

    But I cut corners, if I were more diligent I would also check for the existence of more than one layer and that the file has been saved at all (otherwise it has no path and an error occurs) etc.

     

    -line 14 just makes sure it outputs no more than 20 images (which i find odd. the texture files are extremely small ~6.82 kb each, so loading them won't be a problem. it would be good if it got stuck in an infinite loop)

    Feel free to change it to a higher number.

    To create 100 files change to

    for (var p = 1; p < 101; p++) {
    

     

    Why is thearray2 put in thearray, but then never used separately?

    The function RandomShow checks if the elements in the Array are Arrays themselves

    if (theObject.constructor != Array) {
    

    and just assumes it is a Layer if it is not an Array.

    But when it is an Array the function RandomShow is run with that Arrays elements as arguments.

    This is intended to enable the various rules – for example if you have two or more Layers of which only one may be visible you could put them in such an Array with minimal and maximal set to 1, which should only make one visible.

    But – and again I should have included checks for this – you should not put a Layer in more than one Array.

     

    In the example changing theArray2 to

    var theArray2 = [[theLayers[0], theLayers[1], theLayers[2]], 1, 1, "no"];
    

    would mean that 7, 8 and 9 would only be visible individually.

    But as theArray2 is itself part of theArray it may be visible or not unless it is set as the baseLayer.

    Or rather it would if I had not forget to check the baseLayer item for being an Array itself …

    So please change the affected if-clause (should be about line 34) to

    // show the baselayer;
    if (baseLayer.constructor == Number) {
              var theObject = theArray[baseLayer];
    // show baselayer if layer;
              if (theObject.constructor != Array) {
                        theObject.visible = true;
                        }
    // run function if baselayer is an array;
              else {
                        RandomShow (theObject[0], theObject[1], theObject[2], theObject[3])
                        };
              maximal--
              };
    

     

     

    -baselayer is defined (but i can't find out where to input what it is, do i put it in place of the "no" on line 15?)

    The function takes four arguments,

    • the Array

    • the minimum number of visible elements

    • the maximum number of visible elements

    • a layer that should always be visible identified by its place in the Array

    So when invoking the function RandomShow and wanting the first layer in the Array to be visible it would be:

    RandomShow (theArray, 1, 5, 0);
    

    -for the layer array do I put in the actual layer names?

    If you want to address a layer with teh name »Layer 1« by name (top level layers that is, layers in Groups are filial to the Group) you can use

    myDocument.layers.getByName("Layer 1")
    

     

    -If I currently have layers hidden, how would i tel it to not add those to be randomly shuffled and made visible (it was randomizing the texturemap and the other layer that is there for future reference into the compiled pngs)

    Whether a Layer is visible or not is irrelevant in the curren tform of the Script, the Layers are addressed in the Array.

    Introducing a check for visibility would be possible, but make the function a bit more convoluted as this would also affect the maximum number for example.

     

    I don’t think I answered all questions, but maybe you’ve made progress on your own already and you can always post again if matters are still unclear.

    Maybe the function is more complicated than it would need to be or maybe it will not be able to accomodate all your needs currently, but one could for example extend the baseLayer argument to an Array itself to have more than one element (either Layer or another Array) that will always be visible … there are still possibilities but the issue might be a bit complicated.

     
    |
    Mark as:
  • Currently Being Moderated
    Aug 5, 2012 3:10 AM   in reply to c.pfaffenbichler

    I noticed an error – I forgot to remove the baseLayer from the array, so it could account for two »visibilities« in effect reducing the number of actually shown layers/elements.

    Forget it, the line

    if (m != baseLayer) {
    

    took care of it …

     
    |
    Mark as:
  • Currently Being Moderated
    Aug 5, 2012 3:49 AM   in reply to c.pfaffenbichler

    I’ve adapted the Script somewhat …

    // 2012, use it at your own risk;
    #target photoshop
    if (app.documents.length > 0) {
    var myDocument = app.activeDocument;
    // getting the name and location;
    var docName = myDocument.name;
    var basename = docName.match(/(.*)\.[^\.]+$/)[1];
    var docPath = myDocument.path;
    // set up the arrays of layers;
    var theLayers = myDocument.layers;
    var theArray2 = [[theLayers[0], theLayers[1], theLayers[2]], 1, 1, []];
    var theArray3 = [[theLayers[3], theLayers[4], theLayers[5]], 1, 2, []];
    // randomize and save png;
    for (var p = 1; p < 21; p++) {
              RandomShow ([theLayers[6], theLayers[7], theLayers[8]], 3, 5, [theArray2, theArray3]);
              savePNG (myDocument, docPath, basename, p)
              }
    };
    ////// randomly show layers; baselayer is the index in thearray of a layer that has to be shown //////
    function RandomShow (theArray, minimal, maximal, baseLayer) {
    // baselayers;
    for (var q = 0; q < baseLayer.length; q++) {
              var theObject = baseLayer[q];
    // show baselayer if layer;
              if (theObject.constructor != Array) {
                        theObject.visible = true;
                        }
    // run function if baselayer is an array;
              else {
                        if (theObject.length != 0) {
                                  RandomShow (theObject[0], theObject[1], theObject[2], theObject[3])
                                  }
                        };
              maximal--;
              minimal--
              };
    // process the purely random layers;
    if (minimal > theArray.length || maximal > theArray.length) {alert ("nonsense")}
    else {
    // create array of numbers without baselayer;
              var numbersArray = new Array;
              for (var m = 0; m < theArray.length; m++) {
                        numbersArray.push(m);
                        };
    //  hide layers;
              hideLayers(theArray);
    // number of layers to show;
              var theNumber = minimal + Math.floor( Math.random() * (maximal - minimal + 1) );
    // shuffle the array of numbers;
              arrayShuffle(numbersArray);
    // take the first x numbers;
              for (var n = 0; n < theNumber; n++) {
                        var theObject = theArray[numbersArray[n]];
                        if (theObject.constructor != Array) {
                                  theObject.visible = true;
                                  }
                        else {
                                  RandomShow (theObject[0], theObject[1], theObject[2], theObject[3])
                                  }
                        };
              }
    };
    ////// hide the layers in an array of layers //////
    function hideLayers (anArray) {
              try {
                        for (var o = 0; o < anArray.length; o++) {
                                  if (anArray[o].constructor != Array) {anArray[o].visible = false}
                                  else {hideLayers (anArray[o])}
                                  }
                        }
              catch (e) {}
              };
    ////// shuffle the items in an array //////
    // http://www.hardcode.nl/subcategory_1/article_317-array-shuffle-function
    function arrayShuffle(theArray) {
              var len = theArray.length;
              var i = len;
              while (i--) {
                        var p = parseInt(Math.random()*len);
                        var t = theArray[i];
                        theArray[i] = theArray[p];
                        theArray[p] = t;
              }
    };
    ////// function to png //////
    function savePNG (myDocument, docPath, basename, theSuffix) {
    // weboptions;
    var webOptions = new ExportOptionsSaveForWeb();
    webOptions.format = SaveDocumentType.PNG;
    webOptions.PNG8 = false; 
    webOptions.transparency = true;
    webOptions.interlaced = 0;
    webOptions.includeProfile = false;
    webOptions.optimized = true;
    myDocument.exportDocument(new File(docPath+"/"+basename+"_"+theSuffix+".png"), ExportType.SAVEFORWEB, webOptions);
    };
    

    In this version the nine layer file gets results like these:

    randomLayerVisibilityScr2.jpg

    The lowest three layers (1, 2, 3) are random but at least one will be visible, of the middle ones (4, 5, 6) one or two can be visible, of the topmost three (7, 8, 9) only one will be shown.

     

    The baseLayer-argument needs to be an Array now which can contain layers (which is basically useless as if one wants a layer to always be visible one need not include it in the function at all) or arrays.

     
    |
    Mark as:

More Like This

  • Retrieving data ...

Bookmarked By (0)

Answers + Points = Status

  • 10 points awarded for Correct Answers
  • 5 points awarded for Helpful Answers
  • 10,000+ points
  • 1,001-10,000 points
  • 501-1,000 points
  • 5-500 points