Photoshop Scripting. How to put each closed path on a separate Path layer ?

Explorer ,
Dec 15, 2021 Dec 15, 2021

Copy link to clipboard

Copied

The document has one Paths layer (Work Path) which contains a series of closed paths. How to put each closed path on a separate Path layer ?P000.jpgP001.jpg

TOPICS
Actions and scripting

Views

141

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 1 Correct answer

LEGEND , Dec 15, 2021 Dec 15, 2021

I found an old thread https://community.adobe.com/t5/photoshop-ecosystem-discussions/script-convert-point-tool-to-all-anchor-points-in-a-shape/m-p/7593967   c.pfaffenbichler posted a Script the copied a Path but removed all the curve so there were  straight  lines between control points.   So I hack that script for you.  I put the curves  back in and created a  Path for each Subpath.  Its not pretty, I use a sledge hammer. Note: The selected Work Path was Preserved but its Names was Changed and

...

Likes

Translate

Translate
LEGEND ,
Dec 15, 2021 Dec 15, 2021

Copy link to clipboard

Copied

Your script would process the Path collection for the work Path and for each closed path create a new Path in the Paths Palette. They are not layers they are Paths displayed in the Path Palette. The document Layers collection is displayed in the Layers palette. 

image.png

 

This script will show you how to process a targeted path in the Path palette.

// 2015  John J. McAssey (JJMack) 
// ======================================================= */

// This script is supplied as is. It is provided as freeware. 
// The author accepts no liability for any problems arising from its use.
	
// enable double-clicking from Mac Finder or Windows Explorer
#target photoshop // this command only works in Photoshop CS2 and higher

// Save the current preferences
var startRulerUnits = app.preferences.rulerUnits;
// Set Photoshop to use pixels 
app.preferences.rulerUnits = Units.PIXELS;
var thePath = selectedPath();
if (thePath == undefined) {
	alert("No Path Selected");
	}
else {
	var myPathInfo = extractSubPathInfo(thePath);
	var message ="    Path Points\n";	
	for(var k=0;k<myPathInfo.length;k++){  
		for(var j=0;j<myPathInfo[k].entireSubPath.length;j++){ 
			message = message +  "P" + k + " " + j + " X " +  Math.round(myPathInfo[k].entireSubPath[j].anchor[0]) + "  Y " +  Math.round(myPathInfo[k].entireSubPath[j].anchor[1]) + "\n";
			}
		}
	alert(message);
	}
// Return the app preferences
app.preferences.rulerUnits = startRulerUnits;

////// determine selected path //////
function selectedPath () {
	try {
		var ref = new ActionReference(); 
		ref.putEnumerated( charIDToTypeID("Path"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") ); 
		var desc = executeActionGet(ref);
		var theName = desc.getString(charIDToTypeID("PthN"));
		return app.activeDocument.pathItems.getByName(theName)
	}
	catch (e) {
		return undefined
	}
};
////// michael l hale’s code //////
function extractSubPathInfo(pathObj){  
    var pathArray = new Array();// each element can be used as the second arugment in pathItems.add ie doc.pathItems.add("myPath1", [pathArray[0]]);  
    var pl = pathObj.subPathItems.length;  
    for(var s=0;s<pl;s++){  
        var pArray = new Array();  
          for(var i=0;i<pathObj.subPathItems[s].pathPoints.length;i++){  
             pArray[i] = new PathPointInfo;  
             pArray[i].kind = pathObj.subPathItems[s].pathPoints[i].kind;  
             pArray[i].anchor = pathObj.subPathItems[s].pathPoints[i].anchor;  
			 //alert("Anchor " + pathObj.subPathItems[s].pathPoints[i].anchor );
             pArray[i].leftDirection = pathObj.subPathItems[s].pathPoints[i].leftDirection;  
             pArray[i].rightDirection = pathObj.subPathItems[s].pathPoints[i].rightDirection;  
          };  
        pathArray[pathArray.length] = new Array();  
        pathArray[pathArray.length - 1] = new SubPathInfo();  
        pathArray[pathArray.length - 1].operation = pathObj.subPathItems[s].operation;  
        pathArray[pathArray.length - 1].closed = pathObj.subPathItems[s].closed;  
        pathArray[pathArray.length - 1].entireSubPath = pArray;  
    };  
    return pathArray;  
};  

 

JJMack

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Dec 15, 2021 Dec 15, 2021

Copy link to clipboard

Copied

I found an old thread https://community.adobe.com/t5/photoshop-ecosystem-discussions/script-convert-point-tool-to-all-anch...   c.pfaffenbichler posted a Script the copied a Path but removed all the curve so there were  straight  lines between control points.   So I hack that script for you.  I put the curves  back in and created a  Path for each Subpath.  Its not pretty, I use a sledge hammer. Note: The selected Work Path was Preserved but its Names was Changed and the SubPath Paths were created.

Capture.jpg

CopyClosePaths.jsx

 

// Copy Close Paths  hack of c.pfaffenbichler script
// 2015, use it at your own risk;   
#target photoshop   
try {
	if (app.documents.length > 0) {   
		var myDocument = app.activeDocument;  
		if (myDocument.pathItems.length > 0) {  
			if (!selectedPath()) alert("No Path");
			var thePath = selectedPath();  
			if (thePath != undefined) {  
				var thePathKind = thePath.kind;  
				// check if selected path is vector mask;  
				if (thePathKind == PathKind.VECTORMASK && thePath == myDocument.pathItems[myDocument.pathItems.length - 1]) {var replace = true}
				else {var replace = false};  
				var theArray = collectPathInfoFromDesc2012 (myDocument, selectedPath ());  
				//logInfo(theArray);
				var theNewArray = new Array;  
				// creae new array;  
				for (var m = 0; m < theArray.length; m++) {  
					var thisSub = theArray[m];  
					theNewArray.push(new Array);  
						for (var n = 0; n < thisSub.length - 2; n++) {  
							var thisPoint = thisSub[n];  
							//alert( thisPoint[0] + ", " + thisPoint[1] + ", " + thisPoint[2] + ", " + false );
							theNewArray[0].push([thisPoint[0], thisPoint[1], thisPoint[2], false]);  
						};  
					theNewArray[0].push(thisSub[thisSub.length-2]);  
					theNewArray[0].push(thisSub[thisSub.length-1]); 
					var theNewPath = createPath2015(theNewArray, thePath.name+"p" + m) ; 
					theNewArray = [];          				
				};  
				// create copy path;  
				//logInfo(theNewArray);
				//var theNewPath = createPath2015(theNewArray, thePath.name+"x")  
			};
		}			
	};  
}
catch(e) { alert(e + ': on line ' + e.line, 'Photoshop Error', true); }  
// from »Flatten All Masks.jsx« by jeffrey tranberry;  
///////////////////////////////////////////////////////////////////////////////  
// Function: hasVectorMask  
// Usage: see if there is a vector layer mask  
// Input: <none> Must have an open document  
// Return: true if there is a vector mask  
///////////////////////////////////////////////////////////////////////////////  
function hasVectorMask() {  
	var hasVectorMask = false;  
	try {  
		var ref = new ActionReference();  
		var keyVectorMaskEnabled = app.stringIDToTypeID( 'vectorMask' );  
		var keyKind = app.charIDToTypeID( 'Knd ' );  
		ref.putEnumerated( app.charIDToTypeID( 'Path' ), app.charIDToTypeID( 'Ordn' ), keyVectorMaskEnabled );  
		var desc = executeActionGet( ref );  
		if ( desc.hasKey( keyKind ) ) {  
			var kindValue = desc.getEnumerationValue( keyKind );  
			if (kindValue == keyVectorMaskEnabled) {  
				hasVectorMask = true;  
			}  
		}  
	}
	catch(e) {  
		hasVectorMask = false;  
	}  
	return hasVectorMask;  
};  
////// collect path info from actiondescriptor, smooth added //////  
function collectPathInfoFromDesc2012 (myDocument, thePath) {  
	var originalRulerUnits = app.preferences.rulerUnits;  
	app.preferences.rulerUnits = Units.POINTS;  
	// based of functions from xbytor’s stdlib;  
	var ref = new ActionReference();  
	for (var l = 0; l < myDocument.pathItems.length; l++) {  
		var thisPath = myDocument.pathItems[l];  
		if (thisPath == thePath && thisPath.kind == PathKind.WORKPATH) {  
			ref.putProperty(cTID("Path"), cTID("WrPt"));  
		};  
		if (thisPath == thePath && thisPath.kind != PathKind.WORKPATH && thisPath.kind != PathKind.VECTORMASK) {  
			ref.putIndex(cTID("Path"), l + 1);  
		};  
		if (thisPath == thePath && thisPath.kind == PathKind.VECTORMASK) {  
			var idPath = charIDToTypeID( "Path" );  
			var idPath = charIDToTypeID( "Path" );  
			var idvectorMask = stringIDToTypeID( "vectorMask" );  
			ref.putEnumerated( idPath, idPath, idvectorMask );  
		};  
	};  
	var desc = app.executeActionGet(ref);  
	var pname = desc.getString(cTID('PthN'));  
	// create new array;  
	var theArray = new Array;  
	var pathComponents = desc.getObjectValue(cTID("PthC")).getList(sTID('pathComponents'));  
	// for subpathitems;  
	for (var m = 0; m < pathComponents.count; m++) {  
		var listKey = pathComponents.getObjectValue(m).getList(sTID("subpathListKey"));  
		var operation1 = pathComponents.getObjectValue(m).getEnumerationValue(sTID("shapeOperation"));  
		switch (operation1) {  
			case 1097098272:  
			var operation = 1097098272 //cTID('Add ');  
			break;  
			case 1398961266:  
			var operation = 1398961266 //cTID('Sbtr');  
			break;  
			case 1231975538:  
			var operation = 1231975538 //cTID('Intr');  
			break;  
			default:  
			// case 1102:  
			var operation = sTID('xor') //ShapeOperation.SHAPEXOR;  
			break;  
		};  
		// for subpathitem’s count;  
		for (var n = 0; n < listKey.count; n++) {  
			theArray.push(new Array);  
			var points = listKey.getObjectValue(n).getList(sTID('points'));  
			try {var closed = listKey.getObjectValue(n).getBoolean(sTID("closedSubpath"))}  
			catch (e) {var closed = false};  
			// for subpathitem’s segment’s number of points;  
			for (var o = 0; o < points.count; o++) {  
				var anchorObj = points.getObjectValue(o).getObjectValue(sTID("anchor"));  
				var anchor = [anchorObj.getUnitDoubleValue(sTID('horizontal')), anchorObj.getUnitDoubleValue(sTID('vertical'))];  
				var thisPoint = [anchor];  
				try {  
					var left = points.getObjectValue(o).getObjectValue(cTID("Fwd "));  
					var leftDirection = [left.getUnitDoubleValue(sTID('horizontal')), left.getUnitDoubleValue(sTID('vertical'))];  
					thisPoint.push(leftDirection)  
				}  
				catch (e) {  
					thisPoint.push(anchor)  
				};  
				try {  
					var right = points.getObjectValue(o).getObjectValue(cTID("Bwd "));  
					var rightDirection = [right.getUnitDoubleValue(sTID('horizontal')), right.getUnitDoubleValue(sTID('vertical'))];  
					thisPoint.push(rightDirection)  
				}  
				catch (e) {  
					thisPoint.push(anchor)  
				};  
				try {  
					var smoothOr = points.getObjectValue(o).getBoolean(cTID("Smoo"));  
					thisPoint.push(smoothOr)  
				}  
				catch (e) {thisPoint.push(false)};  
				theArray[theArray.length - 1].push(thisPoint);  
			};  
			theArray[theArray.length - 1].push(closed);  
			theArray[theArray.length - 1].push(operation);  
		};  
	};  
	// by xbytor, thanks to him;  
	function cTID (s) { return cTID[s] || cTID[s] = app.charIDToTypeID(s); };  
	function sTID (s) { return sTID[s] || sTID[s] = app.stringIDToTypeID(s); };  
	// reset;  
	app.preferences.rulerUnits = originalRulerUnits;  
	return theArray;  
};  
////// create a path from collectPathInfoFromDesc2012-array //////  
function createPath2015(theArray, thePathsName) {  
	var originalRulerUnits = app.preferences.rulerUnits;  
	app.preferences.rulerUnits = Units.POINTS;  
	// thanks to xbytor;  
	cTID = function(s) { return app.charIDToTypeID(s); };  
	sTID = function(s) { return app.stringIDToTypeID(s); };  
  
  
	var desc1 = new ActionDescriptor();  
    var ref1 = new ActionReference();  
    ref1.putProperty(cTID('Path'), cTID('WrPt'));  
    desc1.putReference(sTID('null'), ref1);  
    var list1 = new ActionList();  
  
	for (var m = 0; m < theArray.length; m++) {  
		var thisSubPath = theArray[m];  
  
		var desc2 = new ActionDescriptor();  
		desc2.putEnumerated(sTID('shapeOperation'), sTID('shapeOperation'), thisSubPath[thisSubPath.length - 1]);  
		var list2 = new ActionList();  
		var desc3 = new ActionDescriptor();  
		desc3.putBoolean(cTID('Clsp'), thisSubPath[thisSubPath.length - 2]);  
		var list3 = new ActionList();  
  
		for (var n = 0; n < thisSubPath.length - 2; n++) {  
			var thisPoint = thisSubPath[n];  
  
			var desc4 = new ActionDescriptor();  
			var desc5 = new ActionDescriptor();  
			desc5.putUnitDouble(cTID('Hrzn'), cTID('#Rlt'), thisPoint[0][0]);  
			desc5.putUnitDouble(cTID('Vrtc'), cTID('#Rlt'), thisPoint[0][1]);  
			desc4.putObject(cTID('Anch'), cTID('Pnt '), desc5);  
			var desc6 = new ActionDescriptor();  
			desc6.putUnitDouble(cTID('Hrzn'), cTID('#Rlt'), thisPoint[1][0]);  
			desc6.putUnitDouble(cTID('Vrtc'), cTID('#Rlt'), thisPoint[1][1]);  
			desc4.putObject(cTID('Fwd '), cTID('Pnt '), desc6);  
			var desc7 = new ActionDescriptor();  
			desc7.putUnitDouble(cTID('Hrzn'), cTID('#Rlt'), thisPoint[2][0]);  
			desc7.putUnitDouble(cTID('Vrtc'), cTID('#Rlt'), thisPoint[2][1]);  
			desc4.putObject(cTID('Bwd '), cTID('Pnt '), desc7);  
			desc4.putBoolean(cTID('Smoo'), thisPoint[3]);  
			list3.putObject(cTID('Pthp'), desc4);  
  
		};  
  
		desc3.putList(cTID('Pts '), list3);  
		list2.putObject(cTID('Sbpl'), desc3);  
		desc2.putList(cTID('SbpL'), list2);  
		list1.putObject(cTID('PaCm'), desc2);  
	};  
  
    desc1.putList(cTID('T   '), list1);  
    executeAction(cTID('setd'), desc1, DialogModes.NO);  

	for (var x = 0; x < activeDocument.pathItems.length; x++) {  
		if (activeDocument.pathItems[x].kind == PathKind.WORKPATH) {  
			app.activeDocument.pathItems[x].name = thePathsName;  
			var myPathItem = app.activeDocument.pathItems[x]  
		}  
	};  
	app.preferences.rulerUnits = originalRulerUnits;  
	return myPathItem  
}; 
	
////// determine selected path, updated 08.2011 //////  
function selectedPath () {  
	try {  
		var ref = new ActionReference();   
		ref.putEnumerated( charIDToTypeID("Path"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );   
		var desc = executeActionGet(ref);  
		var theName = desc.getString(charIDToTypeID("PthN"));  
		// save work path;  
		if (app.activeDocument.pathItems[app.activeDocument.pathItems.length - 1].kind == PathKind.WORKPATH) { 
			// =======================================================  
			var idslct = charIDToTypeID( "slct" );  
				var desc3 = new ActionDescriptor();  
				var idnull = charIDToTypeID( "null" );  
					var ref2 = new ActionReference();  
					var idPath = charIDToTypeID( "Path" );  
					var idWrPt = charIDToTypeID( "WrPt" );  
					ref2.putProperty( idPath, idWrPt );  
				desc3.putReference( idnull, ref2 );  
			executeAction( idslct, desc3, DialogModes.NO );  
			// =======================================================  
			var idMk = charIDToTypeID( "Mk  " );  
				var desc4 = new ActionDescriptor();  
				var idnull = charIDToTypeID( "null" );  
					var ref3 = new ActionReference();  
					var idPath = charIDToTypeID( "Path" );  
					ref3.putClass( idPath );  
				desc4.putReference( idnull, ref3 );  
				var idFrom = charIDToTypeID( "From" );  
					var ref4 = new ActionReference();  
					var idPath = charIDToTypeID( "Path" );  
					var idWrPt = charIDToTypeID( "WrPt" );  
					ref4.putProperty( idPath, idWrPt );  
				desc4.putReference( idFrom, ref4 );  
				var idNm = charIDToTypeID( "Nm  " );  
				desc4.putString( idNm, dateString() );  
			executeAction( idMk, desc4, DialogModes.NO );  
		};  
		//  
		if (theName == "Work Path") { 
			return app.activeDocument.pathItems[app.activeDocument.pathItems.length - 1]  
		}  
		else {  
			return app.activeDocument.pathItems.getByName(theName)  
		}  
	}  
	catch (e) {  
		return undefined  
	}  
};  
	
////// function to get the date //////
function dateString () {
	var now = new Date();
	var day = now.getDate();
	var month = now.getMonth();
	month++;
	var year = now.getFullYear();
	var hour = now.getHours();
	var minutes = now.getMinutes();
	var seconds = now.getSeconds();
	var myDateText = day+"-"+month+"-"+year+"_"+hour+"-"+minutes+"-"+seconds;
	return myDateText
};
function logInfo(Txt){ // Create write and open log file
    try {	
       var file = new File(Folder.desktop + "/copypath].txt"); 
       file.open("w", "TEXT", "????"); 
       file.encoding = "UTF8";
       file.seek(0,2);   
       $.os.search(/windows/i)  != -1 ? file.lineFeed = 'windows'  : file.lineFeed = 'macintosh';
       file.writeln(Txt); 
       if (file.error) alert(file.error);
       file.close();
       file.execute(); 
    }
    catch(e) { alert(e + ': on line ' + e.line, 'Script Error', true); }
};   	

 

 

JJMack

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Apr 04, 2022 Apr 04, 2022

Copy link to clipboard

Copied

JJMack Thank you!

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Apr 04, 2022 Apr 04, 2022

Copy link to clipboard

Copied

Don't thank, just mark as correct answer 🙂 / actually BrettN marked it but later it vanished:(

 

You're 3 months too late. If you answered in December he would see it, but now: Feb 04, 2022

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Apr 04, 2022 Apr 04, 2022

Copy link to clipboard

Copied

LATEST

Yes, mark which answer(s) work for you. JJ has passed away.

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines