Skip to main content
Participating Frequently
May 30, 2024
Question

Is it possible to automate or create a script to duplicate links and activate/deactivate Layer Comp?

  • May 30, 2024
  • 4 replies
  • 2104 views

For example, if I have 50 .psd images in my file, which I need to duplicate each one, so two links for each image.

The top image needs to have only a certain group/layer activated using the Layer Comps tool, then the second link under that needs to have everything deactivated but leaving only a layer which needs to be in multiply mode.

Basically two links, one for the model, another for the model's shadow.

What's the best approach to do that?

This topic has been closed for replies.

4 replies

ril3ydxAuthor
Participating Frequently
June 1, 2024

After tweaking, playing around, trying to get help on Chatgpt but no success, I ended up with this script:

It's doing some parts correctly:

- It duplicates the link and sets to multiply, it enters the "object layer options" and hides the folder modelo but the layer "fundo branco" that i also need to hide, it doesn't...

- in the original link i need to hide the group "fundo" but its not doing

- after it runs, it gives me this error: Error occurred: ReferenceError: Object is invalid

 

script:

 

var lnk = app.activeDocument.links.everyItem().getElements();
var fileNames = [];

// Generate a list of file names for all selected images
for (var i = 0; i < lnk.length; i++) {
if (lnk[i].parent.constructor.name == "Image") {
fileNames.push(lnk[i].name);
}
}

// Iterate through the list of file names
for (var j = 0; j < fileNames.length; j++) {
var fileName = fileNames[j];

// Find the original image by file name
for (var k = 0; k < lnk.length; k++) {
if (lnk[k].name === fileName && lnk[k].parent.constructor.name == "Image") {
var originalImage = lnk[k].parent.parent;

// Duplicate the original image
var dup = originalImage.duplicate();

// Set the top link (original image) to Multiply
originalImage.transparencySettings.blendingSettings.blendMode = BlendMode.MULTIPLY;

// Set the duplicated image to Normal
dup.transparencySettings.blendingSettings.blendMode = BlendMode.NORMAL;

try {
// Adjust visibility of layers in the original image
var graphicLayerOptionsOriginal = originalImage.images[0].graphicLayerOptions;
var modeloGroupOriginal = graphicLayerOptionsOriginal.graphicLayers.itemByName("Edicao").graphicLayers.itemByName("Modelo");
if (modeloGroupOriginal.isValid) {
modeloGroupOriginal.currentVisibility = false;
}

var fundoBrancoLayerOriginal = graphicLayerOptionsOriginal.graphicLayers.itemByName("Edicao").graphicLayers.itemByName("Fundo Branco");
if (fundoBrancoLayerOriginal.isValid) {
fundoBrancoLayerOriginal.currentVisibility = false;
}

// Deactivate visibility for "Fundo" folder in the duplicated image
var graphicLayerOptionsDup = dup.images[0].graphicLayerOptions;
var fundoFolderDup = graphicLayerOptionsDup.graphicLayers.itemByName("Fundo");
if (fundoFolderDup.isValid) {
fundoFolderDup.currentVisibility = false;
}

// Iterate through all layers in the duplicated image and deactivate their visibility
var layers = graphicLayerOptionsDup.graphicLayers.everyItem().getElements();
for (var l = 0; l < layers.length; l++) {
layers[l].currentVisibility = false;
}
} catch (error) {
alert("Error occurred: " + error);
}

break;
}
}
}

rob day
Community Expert
Community Expert
June 3, 2024

My first version did not consider groups. This loops through the groups recursively and gets a layer by name-- the 2nd parameter in the getGraphicLayer() function

 

var lnk = app.activeDocument.links.everyItem().getElements()

var obj, dup, sh, glc;
for (var i = 0; i < lnk.length; i++){
    if (lnk[i].parent.constructor.name == "Image") {
        obj = lnk[i].parent.parent
        dup = obj.duplicate().images[0];
        glc = dup.graphicLayerOptions.graphicLayers;

        getGraphicLayer(glc, "Modelo").currentVisibility = true;
        getGraphicLayer(glc, "Sombra").currentVisibility = false;
        
        obj.transparencySettings.blendingSettings.blendMode = BlendMode.MULTIPLY
    } 
};   

/**
* Recursively get an image’s graphic layer by name 
* @ param the root graphic layer group 
* @ param the name of the graphic layer to get 
* @ return the graphiclayer 
*/
function getGraphicLayer(gl, n) {
    for (var i = 0; i < gl.length; i++){
        if (gl[i].name == n) {
            return gl[i]
        } else if (gl[i].hasOwnProperty("graphicLayers") && gl[i].graphicLayers.length) {
            var r = getGraphicLayer(gl[i].graphicLayers, n)
            if(r) return r
        } 
    };  
}
rob day
Community Expert
Community Expert
June 3, 2024

Also, another way to do this would be with a function that returns all of the graphic layers as an array, which might be useful with deeply nested groups where the layers might have the same names. Here I have a single image direct selected, and the alert lists all of its graphic layers:

 

var gl = app.activeDocument.selection[0].graphicLayerOptions.graphicLayers;
var ga = getAllGraphicLayers(gl);
var s ="Image Graphic Layers \r"
for (var i = 0; i < ga.length; i++){
    s+= ga[i].name + "\r"
};   

alert(s)


/**
* Gets all of an image’s graphic layers as an array
* @ param the root graphic layer group 
* @ return an array of graphic layers 
*/
function getAllGraphicLayers(gl) {
    var gla = []
    for (var i = 0; i < gl.length; i++){
        if (gl[i].graphicLayers.length == 0) {
            gla.push(gl[i])
        } else if (gl[i].hasOwnProperty("graphicLayers")) {
            gla.push(gl[i])
            gla = gla.concat(getAllGraphicLayers(gl[i].graphicLayers));
        } 
    }; 
    if(gla.length){
        return gla
    }  
}

 

 

 

 

Participant
May 31, 2024

I had the same problem with shadows that you have that was resolved by using paths instead of layer comps.

I have a script that searches all images in a doc containing two layers with fixed names. When such an image is found it :

- duplicates the image,

- applies the 'packshot' path to the foremost image

- applies the 'full image' path with multiply mode to the bottom one

- groups the two images together to move them more easily when needed.

Maybe this could be adapted to your use of Layer Comps (but I never used those so not sure of how to address them).

ril3ydxAuthor
Participating Frequently
May 31, 2024

Thanks, but in my case I have the model hair and "delicated" stuff like that, it's a bit impossible to make that work with a path, so a mask is the way to go...

Community Expert
May 31, 2024

Are all the images on a layer by themselves?

Only asking cos how to target just those images with layer comps - are they a different file format to all the other files in the document, like PSD for layer comps and TIF for evertyhing else?

 

Just thinking how would the script target.

 

Robert at ID-Tasker
Legend
May 31, 2024
quote

Are all the images on a layer by themselves?

Only asking cos how to target just those images with layer comps - are they a different file format to all the other files in the document, like PSD for layer comps and TIF for evertyhing else?

 

Just thinking how would the script target.


By @Eugene Tyson

 

Targeting isn't a problem - Image, PDF and INDD have extra property:

https://www.indesignjs.de/extendscriptAPI/indesign-latest/#GraphicLayerOption.html

 

Then you can get names of the layers and process only links with those layers. 

 

 

 

Robert at ID-Tasker
Legend
May 30, 2024

What's so special with the shadow in your file that you can't generate shadow in InDesign?

 

If names of the layers are constant - then it would be fairly easy.

 

ril3ydxAuthor
Participating Frequently
May 30, 2024

It's a "real" shadow from the image, not generated

Robert at ID-Tasker
Legend
May 30, 2024

What with the names of the layers?