Skip to main content
martinj65399781
Known Participant
March 27, 2021
Answered

In Javascript , how to crop the canvas from layer mask bounds ?

  • March 27, 2021
  • 2 replies
  • 1735 views
Hello, despite all my researches i am struggling on this, i need to export multiple crops of an image, determined by the layers in the group "Gp CADRAGE".

 

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

This topic has been closed for replies.
Correct answer Stephen Marsh

 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 );
}

 

 

2 replies

Stephen Marsh
Community Expert
Stephen MarshCommunity ExpertCorrect answer
Community Expert
March 27, 2021

 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 );
}

 

 

martinj65399781
Known Participant
March 28, 2021

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]
            }

    }

 

c.pfaffenbichler
Community Expert
Community Expert
March 27, 2021
// =======================================================
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 )
martinj65399781
Known Participant
March 28, 2021

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 😉

Stephen Marsh
Community Expert
Community Expert
March 28, 2021

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.