Copy link to clipboard
Copied
I need to either :
- get the layermask active, invert it, and then crop to bounds of the mask
- or get a selection of the layer mask of active layer, invert it, and then crop to doc.selection.bounds
I tried to get a selection from the layer mask and then invert it, but i cannot select the layer mask propertly.
I tried to invert the alpha channel but i cannot get the alpha channel of the layer mask active.
I suppose that we can do it with actiondescriotor and actionreference etc, but don't understand how it works yet. So didn't get the code i found on the net to work 🙂
Thanks a lot if you can help me !
Martin
Here is how I would do it:
// Replace the layerName variable with the required layer name, i.e. "vertical"
selectLayer("horizontal", false);
// Load selected layer mask channel as selection
setSelectionToMask();
// Invert selection
app.activeDocument.selection.invert();
// Crop to selection
var idCrop = charIDToTypeID( "Crop" );
executeAction( idCrop, undefined, DialogModes.NO );
// Deselect
app.activeDocument.selection.deselect();
// Functions
function selectLayer(layerName, makeVisible
...
Copy link to clipboard
Copied
// =======================================================
var idset = stringIDToTypeID( "set" );
var desc3 = new ActionDescriptor();
var idnull = stringIDToTypeID( "null" );
var ref1 = new ActionReference();
var idchannel = stringIDToTypeID( "channel" );
var idselection = stringIDToTypeID( "selection" );
ref1.putProperty( idchannel, idselection );
desc3.putReference( idnull, ref1 );
var idto = stringIDToTypeID( "to" );
var ref2 = new ActionReference();
var idchannel = stringIDToTypeID( "channel" );
var idordinal = stringIDToTypeID( "ordinal" );
var idtargetEnum = stringIDToTypeID( "targetEnum" );
ref2.putEnumerated( idchannel, idordinal, idtargetEnum );
desc3.putReference( idto, ref2 );
executeAction( idset, desc3, DialogModes.NO );
// =======================================================
var idinverse = stringIDToTypeID( "inverse" );
executeAction( idinverse, undefined, DialogModes.NO )
Copy link to clipboard
Copied
thank you for your answer, but i need to make a crop out of the selection, so making a selection from the rgb channels will often make a selection of the whole canvas 😉
Copy link to clipboard
Copied
The ScriptListener code that I posted was just a quick way to select a named target layer inside a layer set and to then load the mask channel as a selection in order to crop. There were a whole lot of assumptions that had to be made. Without having sample files and knowing how consistent multiple files are, one can only do so much. The code worked as intended when I made a simple test file based off your screenshot where the layer mask content was not full canvas.
Copy link to clipboard
Copied
Here is how I would do it:
// Replace the layerName variable with the required layer name, i.e. "vertical"
selectLayer("horizontal", false);
// Load selected layer mask channel as selection
setSelectionToMask();
// Invert selection
app.activeDocument.selection.invert();
// Crop to selection
var idCrop = charIDToTypeID( "Crop" );
executeAction( idCrop, undefined, DialogModes.NO );
// Deselect
app.activeDocument.selection.deselect();
// Functions
function selectLayer(layerName, makeVisible) {
var c2t = function (s) {
return app.charIDToTypeID(s);
};
var s2t = function (s) {
return app.stringIDToTypeID(s);
};
var descriptor = new ActionDescriptor();
var reference = new ActionReference();
reference.putName( s2t( "layer" ), layerName );
descriptor.putReference( c2t( "null" ), reference );
descriptor.putBoolean( s2t( "makeVisible" ), makeVisible );
executeAction( s2t( "select" ), descriptor, DialogModes.NO );
}
function setSelectionToMask() {
var c2t = function (s) {
return app.charIDToTypeID(s);
};
var s2t = function (s) {
return app.stringIDToTypeID(s);
};
var descriptor = new ActionDescriptor();
var reference = new ActionReference();
var reference2 = new ActionReference();
reference.putProperty( s2t( "channel" ), s2t( "selection" ));
descriptor.putReference( c2t( "null" ), reference );
reference2.putEnumerated( s2t( "channel" ), s2t( "channel" ), s2t( "mask" ));
descriptor.putReference( s2t( "to" ), reference2 );
executeAction( s2t("set"), descriptor, DialogModes.NO );
}
Copy link to clipboard
Copied
Thanks you ! i took only the part i needed, just to make a selection of the layer mask, it seems to work perfectly !
So here is the part of code where i use your code 🙂
doc.suspendHistory("Exporter en jpeg web en local", "exporterDifferentsCadrage()")
function exporterDifferentsCadrage() {
// Load selected layer mask channel as selection
setSelectionToMask();
// Invert selection
app.activeDocument.selection.invert();
// Crop to selection
var idCrop = charIDToTypeID( "Crop" );
executeAction( idCrop, undefined, DialogModes.NO );
// Deselect
app.activeDocument.selection.deselect();
// Functions
function setSelectionToMask() {
var c2t = function (s) {
return app.charIDToTypeID(s);
};
var s2t = function (s) {
return app.stringIDToTypeID(s);
};
var descriptor = new ActionDescriptor();
var reference = new ActionReference();
var reference2 = new ActionReference();
reference.putProperty( s2t( "channel" ), s2t( "selection" ));
descriptor.putReference( c2t( "null" ), reference );
reference2.putEnumerated( s2t( "channel" ), s2t( "channel" ), s2t( "mask" ));
descriptor.putReference( s2t( "to" ), reference2 );
executeAction( s2t("set"), descriptor, DialogModes.NO );
}
if (checkJpegHD.value == true){
// récupère le nom d'utilisateur de l'ordinateur
// retourne une (String) du nom de l'utilisateur
function getUserName() {
return (isMacOS()) ? $.getenv("USER") : $.getenv("USERNAME");
}
var userName = getUserName();
if (isMacOS() == true) {
// vérifie si le dossier de destination existe et la créer au besoin
var nouveaudossier = new Folder("/Users/"+ userName +"/Desktop/Photoshop output/06_jpeg HD/");
if ( ! nouveaudossier.exists ) {
nouveaudossier.create()
}
//enregistre en local sur OSX
var jpegSaveOptionsHD = new JPEGSaveOptions()
jpegSaveOptionsHD.embedColorProfile = true
jpegSaveOptionsHD.quality = 12
doc.saveAs(new File("/Users/"+ userName+"/Desktop/Photoshop output/06_jpeg HD/" + docname + '_HD_' + doc.activeLayer.name + '.jpg'), jpegSaveOptionsHD, true, Extension.LOWERCASE)
}
else {
// vérifie si le dossier de destination existe et la créer au besoin
var nouveaudossier = new Folder("C:/Users/" + userName + "/Desktop/Photoshop output/06_jpeg HD/");
if ( ! nouveaudossier.exists ) {
nouveaudossier.create()
}
//enregistre en local sur Windows
var jpegSaveOptionsHD = new JPEGSaveOptions()
jpegSaveOptionsHD.embedColorProfile = true
jpegSaveOptionsHD.quality = 12
doc.saveAs(new File("C:/Users/" + userName + "/Desktop/Photoshop output/06_jpeg HD/" + docname + '_HD_' + doc.activeLayer.name + '.jpg'), jpegSaveOptionsHD, true, Extension.LOWERCASE)
}
}
if (checkTiff.value == true){
// récupère le nom d'utilisateur de l'ordinateur
// retourne une (String) du nom de l'utilisateur
function getUserName() {
return (isMacOS()) ? $.getenv("USER") : $.getenv("USERNAME");
}
var userName = getUserName();
if (isMacOS() == true) {
// vérifie si le dossier de destination existe et la créer au besoin
var nouveaudossier = new Folder("/Users/"+ userName+"/Desktop/Photoshop output/05_tiff HD/");
if ( ! nouveaudossier.exists ) {
nouveaudossier.create()
}
//enregistre en local sur OSX
var tiffHDSaveOptions = new TiffSaveOptions()
tiffHDSaveOptions.embedColorProfile = true
tiffHDSaveOptions.layers = false
tiffHDSaveOptions.alphachannels = false
tiffHDSaveOptions.transparency = false
doc.saveAs(new File("/Users/"+ userName+"/Desktop/Photoshop output/05_tiff HD/" + docname + '_HD_' + doc.activeLayer.name + '.tif'), tiffHDSaveOptions, true, Extension.LOWERCASE)
}
else {
// vérifie si le dossier de destination existe et la créer au besoin
var nouveaudossier = new Folder("C:/Users/" + userName + "/Desktop/Photoshop output/05_tiff HD/");
if ( ! nouveaudossier.exists ) {
nouveaudossier.create()
}
//enregistre en local sur Windows
var tiffHDSaveOptions = new TiffSaveOptions()
tiffHDSaveOptions.embedColorProfile = true
tiffHDSaveOptions.layers = false
tiffHDSaveOptions.alphachannels = false
tiffHDSaveOptions.transparency = false
doc.saveAs(new File("C:/Users/" + userName + "/Desktop/Photoshop output/05_tiff HD/" + docname + '_HD_'+ doc.activeLayer.name +'.tif'), tiffHDSaveOptions, true, Extension.LOWERCASE)
}
}
if (checkJpegWeb.value ==true){
cadrageLayerName = doc.activeLayer.name
function isMacOS() {
return ($.os.toLowerCase().indexOf('mac') >= 0);
}
// récupère le nom d'utilisateur de l'ordinateur
// retourne une (String) du nom de l'utilisateur
function getUserName() {
return (isMacOS()) ? $.getenv("USER") : $.getenv("USERNAME");
}
var userName = getUserName();
doc.suspendHistory("Exporter en jpeg web en local", "exporterJpegWeb()")
function exporterJpegWeb(){
doc.flatten()
if (orientation == "portrait"){
doc.resizeImage(null,UnitValue(coteLongJpegWebInput.text + "px"),null,null);
}
else{
doc.resizeImage(UnitValue(coteLongJpegWebInput.text + "px"),null,null,null);
}
if (isMacOS() == true) {
// vérifie si le dossier de destination existe et la créer au besoin
var nouveaudossier = new Folder("/Users/"+ userName+"/Desktop/Photoshop output/07_jpeg web/");
if ( ! nouveaudossier.exists ) {
nouveaudossier.create()
}
//enregistre en local sur OSX
var exportweboptions = new ExportOptionsSaveForWeb();
exportweboptions.quality = 70;
exportweboptions.format = SaveDocumentType.JPEG;
exportweboptions.optimized = true;
exportweboptions.includeProfile = true
doc.exportDocument(new File("/Users/"+ userName+"/Desktop/Photoshop output/07_jpeg web/" + docname + '_web_'+ cadrageLayerName +'.jpg'),ExportType.SAVEFORWEB,exportweboptions)
}
else {
// vérifie si le dossier de destination existe et la créer au besoin
var nouveaudossier = new Folder("C:/Users/" + userName + "/Desktop/Photoshop output/07_jpeg web/");
if ( ! nouveaudossier.exists ) {
nouveaudossier.create()
}
//enregistre en local sur Windows
var exportweboptions = new ExportOptionsSaveForWeb();
exportweboptions.quality = 70;
exportweboptions.format = SaveDocumentType.JPEG;
exportweboptions.optimized = true;
exportweboptions.includeProfile = true
doc.exportDocument(new File("C:/Users/" + userName + "/Desktop/Photoshop output/07_jpeg web/" + docname + '_web_' + cadrageLayerName + '.jpg'),ExportType.SAVEFORWEB,exportweboptions)
}
}
doc.activeHistoryState = app.activeDocument.historyStates[doc.historyStates.length-2]
}
}
Copy link to clipboard
Copied
Hi, I was able to get this to work on a document I have open, per below following script/1
However, trying to get this to work in the context of another below script/2 that loops thru 3 different masking layers, but in this context getting this following error >>
"Error 8800: General Photoshop error occurred. This functionality may not be available in this version of Photoshop. - The command “Select” is not currently available. Line: 40 -> executeAction( s2t( "select" ), descriptor, DialogModes.NO );"
Since the selectLayer function was working fine on my system in the context of script/1, I'm guessing the glitch has something to do with not correctly pointing to the dupDoc, or somehow not making it activeDocument properly. thanks in advance for any insights
script/1
// adapted from @Stephen_A_Marsh https://community.adobe.com/t5/photoshop-ecosystem-discussions/in-javascript-how-to-crop-the-canvas-from-layer-mask-bounds/m-p/11931296#M525799
function selectLayer(layerName, makeVisible) {
var c2t = function (s) {
return app.charIDToTypeID(s);
};
var s2t = function (s) {
return app.stringIDToTypeID(s);
};
var descriptor = new ActionDescriptor();
var reference = new ActionReference();
reference.putName( s2t( "layer" ), layerName );
descriptor.putReference( c2t( "null" ), reference );
descriptor.putBoolean( s2t( "makeVisible" ), makeVisible );
executeAction( s2t( "select" ), descriptor, DialogModes.NO );
}
function setSelectionToMask() {
var c2t = function (s) {
return app.charIDToTypeID(s);
};
var s2t = function (s) {
return app.stringIDToTypeID(s);
};
var descriptor = new ActionDescriptor();
var reference = new ActionReference();
var reference2 = new ActionReference();
reference.putProperty( s2t( "channel" ), s2t( "selection" ));
descriptor.putReference( c2t( "null" ), reference );
reference2.putEnumerated( s2t( "channel" ), s2t( "channel" ), s2t( "mask" ));
descriptor.putReference( s2t( "to" ), reference2 );
executeAction( s2t("set"), descriptor, DialogModes.NO );
}
// Select layer mask to crop
selectLayer("1x1", false);
// Load selected layer mask channel as selection
setSelectionToMask();
// Invert selection
// app.activeDocument.selection.invert();
// Crop to selection
var idCrop = charIDToTypeID( "Crop" );
executeAction( idCrop, undefined, DialogModes.NO );
// Deselect
// app.activeDocument.selection.deselect();
script/2
// Set path for the folder containing PSD input files
var inputFolderPath = "/Users/ask/Desktop/Ready For Cropping";
// Set paths for the output folders containing exported crops
var exportFolderPaths = [
"/Users/ask/Desktop/Crops 1x1",
"/Users/ask/Desktop/Crops 3x4",
"/Users/ask/Desktop/Crops 16x9"
];
// Function to create output folders if they do not exist
function createOutputFolders() {
for (var i = 0; i < exportFolderPaths.length; i++) {
var outputFolder = new Folder(exportFolderPaths[i]);
if (!outputFolder.exists) {
outputFolder.create();
}
}
}
// Function to select a specific layer
// adapted from @Stephen_A_Marsh https://community.adobe.com/t5/photoshop-ecosystem-discussions/in-javascript-how-to-crop-the-canvas-from-layer-mask-bounds/m-p/11931296#M525799
function selectLayer(layerName, makeVisible) {
var c2t = function (s) {
return app.charIDToTypeID(s);
};
var s2t = function (s) {
return app.stringIDToTypeID(s);
};
var descriptor = new ActionDescriptor();
var reference = new ActionReference();
reference.putName( s2t( "layer" ), layerName );
descriptor.putReference( c2t( "null" ), reference );
descriptor.putBoolean( s2t( "makeVisible" ), makeVisible );
executeAction( s2t( "select" ), descriptor, DialogModes.NO );
}
// Function to set selection to the specified masking layer
// adapted from @Stephen_A_Marsh https://community.adobe.com/t5/photoshop-ecosystem-discussions/in-javascript-how-to-crop-the-canvas-from-layer-mask-bounds/m-p/11931296#M525799
function setSelectionToMask() {
var c2t = function (s) {
return app.charIDToTypeID(s);
};
var s2t = function (s) {
return app.stringIDToTypeID(s);
};
var descriptor = new ActionDescriptor();
var reference = new ActionReference();
var reference2 = new ActionReference();
reference.putProperty( s2t( "channel" ), s2t( "selection" ));
descriptor.putReference( c2t( "null" ), reference );
reference2.putEnumerated( s2t( "channel" ), s2t( "channel" ), s2t( "mask" ));
descriptor.putReference( s2t( "to" ), reference2 );
executeAction( s2t("set"), descriptor, DialogModes.NO );
}
// Function to process each PSD input file in the folder
function processFiles(folder) {
var files = folder.getFiles();
for (var i = 0; i < files.length; i++) {
var file = files[i];
// Check if it's a PSD file
if (file instanceof File && file.name.match(/\.(psd)$/i)) {
// Open the PSD file
var doc = app.open(file);
// Perform actions on "Crops" layer folder
var cropsFolder = doc.layerSets.getByName("Crops");
// Loop through masking layers
var maskingLayerNames = ["1x1", "3x4", "16x9"];
for (var j = 0; j < maskingLayerNames.length; j++) {
// Get the name of masking layer
var maskingLayer = cropsFolder.artLayers.getByName(maskingLayerNames[j]);
// Duplicate the document
var dupDoc = doc.duplicate();
app.activeDocument = dupDoc;
// Select layer mask to crop
selectLayer(maskingLayer, false);
// Load selected layer mask channel as selection
setSelectionToMask();
// Invert selection
// app.activeDocument.selection.invert();
// Crop to selection
var idCrop = charIDToTypeID( "Crop" );
executeAction( idCrop, undefined, DialogModes.NO );
// Deselect
// app.activeDocument.selection.deselect();
// Save as JPG without prompting
var outputFileName = file.name.replace(/\.[^.]+$/, "") + "_" + maskingLayerNames[j] + ".jpg";
var outputFile = new File(exportFolderPaths[j] + "/" + outputFileName);
var options = new JPEGSaveOptions();
options.quality = 12; // Highest quality
doc.saveAs(outputFile, options, true);
// Close the duplicate document without saving changes
dupDoc.close(SaveOptions.DONOTSAVECHANGES);
}
// Close the file without saving changes
doc.close(SaveOptions.DONOTSAVECHANGES);
}
// If it's a folder, recursively process its contents
if (file instanceof Folder) {
processFiles(file);
}
}
}
// Call the function to create output folders if they do not exist
createOutputFolders();
// Call the function to process the PSD input files
var folder = new Folder(inputFolderPath);
processFiles(folder);
Copy link to clipboard
Copied
hi @Stephen_A_Marsh sorry I can't figure out how to edit my previous reply, I have further adjusted script/2 but still throwing same error "The command “Select” is not currently available. Line: 40 -> executeAction( s2t( "select" ), descriptor, DialogModes.NO )" which doesn't make sense as it works fine in the context of script/1. thanks in advance
// Set path for the folder containing PSD input files
var inputFolderPath = "/Users/ask/Desktop/Ready For Cropping";
// Set paths for the output folders containing exported crops
var exportFolderPaths = [
"/Users/ask/Desktop/Crops 1x1",
"/Users/ask/Desktop/Crops 3x4",
"/Users/ask/Desktop/Crops 16x9"
];
// Function to create output folders if they do not exist
function createOutputFolders() {
for (var i = 0; i < exportFolderPaths.length; i++) {
var outputFolder = new Folder(exportFolderPaths[i]);
if (!outputFolder.exists) {
outputFolder.create();
}
}
}
// Function to select a specific layer
// adapted from @Stephen_A_Marsh https://community.adobe.com/t5/photoshop-ecosystem-discussions/in-javascript-how-to-crop-the-canvas-from-layer-mask-bounds/m-p/11931296#M525799
function selectLayer(layerName, makeVisible) {
var c2t = function (s) {
return app.charIDToTypeID(s);
};
var s2t = function (s) {
return app.stringIDToTypeID(s);
};
var descriptor = new ActionDescriptor();
var reference = new ActionReference();
reference.putName( s2t( "layer" ), layerName );
descriptor.putReference( c2t( "null" ), reference );
descriptor.putBoolean( s2t( "makeVisible" ), makeVisible );
executeAction( s2t( "select" ), descriptor, DialogModes.NO );
}
// Function to set selection to the specified masking layer
// adapted from @Stephen_A_Marsh https://community.adobe.com/t5/photoshop-ecosystem-discussions/in-javascript-how-to-crop-the-canvas-from-layer-mask-bounds/m-p/11931296#M525799
function setSelectionToMask() {
var c2t = function (s) {
return app.charIDToTypeID(s);
};
var s2t = function (s) {
return app.stringIDToTypeID(s);
};
var descriptor = new ActionDescriptor();
var reference = new ActionReference();
var reference2 = new ActionReference();
reference.putProperty( s2t( "channel" ), s2t( "selection" ));
descriptor.putReference( c2t( "null" ), reference );
reference2.putEnumerated( s2t( "channel" ), s2t( "channel" ), s2t( "mask" ));
descriptor.putReference( s2t( "to" ), reference2 );
executeAction( s2t("set"), descriptor, DialogModes.NO );
}
// Function to process each PSD input file in the folder
function processFiles(folder) {
var files = folder.getFiles();
for (var i = 0; i < files.length; i++) {
var file = files[i];
// Check if it's a PSD file
if (file instanceof File && file.name.match(/\.(psd)$/i)) {
// Open the PSD input file
var doc = app.open(file);
// Loop through masking layers
var maskingLayerNames = ["1x1", "3x4", "16x9"];
for (var j = 0; j < maskingLayerNames.length; j++) {
// Duplicate the PSD input file
var dupDoc = doc.duplicate(file.name.replace(/\.[^.]+$/, "") + "_" + maskingLayerNames[j]);
// Perform actions on "Crops" layer folder
var cropsFolder = dupDoc.layerSets.getByName("Crops");
// Get the name of masking layer
var maskingLayer = cropsFolder.artLayers.getByName(maskingLayerNames[j]);
// Select layer mask to crop
selectLayer(maskingLayer, false);
// Load selected layer mask channel as selection
setSelectionToMask();
// Invert selection
// app.activeDocument.selection.invert();
// Crop to selection
var idCrop = charIDToTypeID( "Crop" );
executeAction( idCrop, undefined, DialogModes.NO );
// Deselect
// app.activeDocument.selection.deselect();
// Save as JPG without prompting
var outputFileName = file.name.replace(/\.[^.]+$/, "") + "_" + maskingLayerNames[j] + ".jpg";
var outputFile = new File(exportFolderPaths[j] + "/" + outputFileName);
var options = new JPEGSaveOptions();
options.quality = 12; // Highest quality
dupDoc.saveAs(outputFile, options, true);
// Close the duplicate document without saving changes
dupDoc.close(SaveOptions.DONOTSAVECHANGES);
}
// Close the input PSD file without saving changes
doc.close(SaveOptions.DONOTSAVECHANGES);
}
// If it's a folder, recursively process its contents
if (file instanceof Folder) {
processFiles(file);
}
}
}
// Call the function to create output folders if they do not exist
createOutputFolders();
// Call the function to process the PSD input files
var folder = new Folder(inputFolderPath);
processFiles(folder);
Copy link to clipboard
Copied
@ASKproduKtion – Please post the sample file.
Copy link to clipboard
Copied
Please disregard, in the end I was able to solve this and make it work using paths instead of layer masks
Copy link to clipboard
Copied
https://github.com/ASKproduKtion/exportCrops