Skip to main content
Known Participant
February 26, 2024
Answered

How do I seperate subjects into different seperate files automatically?

  • February 26, 2024
  • 3 replies
  • 2127 views

I have 2000 scans of coins with a black background, but I like to seperate them from the background into seperate images, but I do I automatize this in photoshop? Hereby images from the original to what I want. Please if someone can help me, perhaps actions in batch? 

Correct answer Stephen Marsh

The following script will save each coin to JPEG in the same folder as the original with the scanned black background in an approximately "square-ish" crop.

 

This isn't the most elegant or cleanest code, but it should get the job done. Tested on an Intel Mac with Ps2021 and Ps2024.

This script is only intended for the current active document, one open document at a time. If it works for you, it could be recorded into an action for use with the File > Automate > Batch command.

 

/*
Isolate Multi Coin Scan Sheet to Individual Coins.jsx
v1.0 - 29th February 2024, Stephen Marsh
https://community.adobe.com/t5/photoshop-ecosystem-discussions/how-do-i-seperate-subjects-into-different-seperate-files-automatically/td-p/14449644
*/

#target photoshop

// Select > Select Subject
var idautoCutout = stringIDToTypeID( "autoCutout" );
    var desc547 = new ActionDescriptor();
    var idsampleAllLayers = stringIDToTypeID( "sampleAllLayers" );
    desc547.putBoolean( idsampleAllLayers, false );
executeAction( idautoCutout, desc547, DialogModes.NO );

// Contract selection to remove minor imperfections
var idcontract = stringIDToTypeID( "contract" );
    var desc549 = new ActionDescriptor();
    var idby = stringIDToTypeID( "by" );
    var idpixelsUnit = stringIDToTypeID( "pixelsUnit" );
    desc549.putUnitDouble( idby, idpixelsUnit, 50 );
    var idselectionModifyEffectAtCanvasBounds = stringIDToTypeID( "selectionModifyEffectAtCanvasBounds" );
    desc549.putBoolean( idselectionModifyEffectAtCanvasBounds, false );
executeAction( idcontract, desc549, DialogModes.NO );

// Smooth the selection to further reduce minor imperfections
var idsmoothness = stringIDToTypeID( "smoothness" );
    var desc554 = new ActionDescriptor();
    var idradius = stringIDToTypeID( "radius" );
    var idpixelsUnit = stringIDToTypeID( "pixelsUnit" );
    desc554.putUnitDouble( idradius, idpixelsUnit, 25 );
    var idselectionModifyEffectAtCanvasBounds = stringIDToTypeID( "selectionModifyEffectAtCanvasBounds" );
    desc554.putBoolean( idselectionModifyEffectAtCanvasBounds, false );
executeAction( idsmoothness, desc554, DialogModes.NO );

// Expand the selection for the crop area
var idexpand = stringIDToTypeID( "expand" );
    var desc556 = new ActionDescriptor();
    var idby = stringIDToTypeID( "by" );
    var idpixelsUnit = stringIDToTypeID( "pixelsUnit" );
    desc556.putUnitDouble( idby, idpixelsUnit, 100 );
    var idselectionModifyEffectAtCanvasBounds = stringIDToTypeID( "selectionModifyEffectAtCanvasBounds" );
    desc556.putBoolean( idselectionModifyEffectAtCanvasBounds, false );
executeAction( idexpand, desc556, DialogModes.NO );

// Create a temporary work path from the selection
var idmake = stringIDToTypeID( "make" );
    var desc574 = new ActionDescriptor();
    var idnull = stringIDToTypeID( "null" );
        var ref189 = new ActionReference();
        var idpath = stringIDToTypeID( "path" );
        ref189.putClass( idpath );
    desc574.putReference( idnull, ref189 );
    var idfrom = stringIDToTypeID( "from" );
        var ref190 = new ActionReference();
        var idselectionClass = stringIDToTypeID( "selectionClass" );
        var idselection = stringIDToTypeID( "selection" );
        ref190.putProperty( idselectionClass, idselection );
    desc574.putReference( idfrom, ref190 );
    var idtolerance = stringIDToTypeID( "tolerance" );
    var idpixelsUnit = stringIDToTypeID( "pixelsUnit" );
    desc574.putUnitDouble( idtolerance, idpixelsUnit, 1 );
executeAction(idmake, desc574, DialogModes.NO);

// Create separate paths
workpathToSeparatePaths()

// Remove the top/first working path
app.activeDocument.pathItems[0].remove();

// Create rectangular selection channels
pathsToRectangularSelectionToAlpha();

// Create layers from the alphas
alphasToLayers();

// Delete the Background layer
app.activeDocument.backgroundLayer.remove();

// Rename the layers
var docName = app.activeDocument.name.replace(/\.[^\.]+$/, '');
var zeroPadLength = 3;
var startNumber = 1;
for (var i = 0; i < activeDocument.layers.length; i++) {
		activeDocument.layers[i].name = docName + "_" + zeroPad(startNumber, zeroPadLength);
		startNumber++
	}
function zeroPad(num, digit) {
	var tmp = num.toString();
	while (tmp.length < digit) {
		tmp = "0" + tmp;
	}
	return tmp;
}

// Remove all paths
for (var i = app.activeDocument.pathItems.length - 1; i >= 0; i--) {
    app.activeDocument.pathItems[i].remove();
}

// Remove all alphas
for (i = app.activeDocument.channels.length - 1; i >= 0; i--) {
    if (app.activeDocument.channels[i].kind == "ChannelType.MASKEDAREA" || app.activeDocument.channels[i].kind == "ChannelType.SELECTEDAREA") {
        app.activeDocument.channels[i].remove();
    }
}

// Save all layers
layersToFiles();
app.activeDocument.close(SaveOptions.DONOTSAVECHANGES);


///// FUNCTIONS /////

function layersToFiles() {
    var outputPath = app.activeDocument.path.fsName;
    processAllLayersAndSets(app.activeDocument);

    // Loop over top level layers
    function processAllLayersAndSets(obj) {
        // Process all layers
        for (var al = obj.artLayers.length - 1; 0 <= al; al--) {
            app.activeDocument.activeLayer = obj.artLayers[al];

            // Skip the Background layer
            if (!activeDocument.activeLayer.isBackgroundLayer) {

                var filename = app.activeDocument.activeLayer.name;
                dupeSelectedLayers(filename);
                activeDocument.trim(TrimType.TRANSPARENT);

                var sfwOptions = new ExportOptionsSaveForWeb();
                sfwOptions.format = SaveDocumentType.JPEG;
                sfwOptions.includeProfile = true;
                sfwOptions.interlaced = 0;
                sfwOptions.optimized = true;
                sfwOptions.quality = 75;
                var jpgFile = new File(outputPath + "/" + filename + ".jpg");
                app.activeDocument.exportDocument(jpgFile, ExportType.SAVEFORWEB, sfwOptions);

                var sfwOptions = new ExportOptionsSaveForWeb();

                app.activeDocument.close(SaveOptions.DONOTSAVECHANGES);

                function dupeSelectedLayers(theDocName) {
                    function s2t(s) {
                        return app.stringIDToTypeID(s);
                    }
                    var descriptor = new ActionDescriptor();
                    var reference = new ActionReference();
                    var reference2 = new ActionReference();
                    reference.putClass(s2t("document"));
                    descriptor.putReference(s2t("null"), reference);
                    descriptor.putString(s2t("name"), theDocName);
                    reference2.putEnumerated(s2t("layer"), s2t("ordinal"), s2t("targetEnum"));
                    descriptor.putReference(s2t("using"), reference2);
                    executeAction(s2t("make"), descriptor, DialogModes.NO);
                }
            }
        }
    }
}

function alphasToLayers() {
    // Loop over the alpha channels
    for (var i = activeDocument.channels.length - 1; i >= 0; i--) {
        if (app.activeDocument.channels[i].kind === ChannelType.SELECTEDAREA || app.activeDocument.channels[i].kind === ChannelType.MASKEDAREA) {
            var theChannel = new Array(app.activeDocument.channels[i]);
            app.activeDocument.activeChannels = theChannel;
            // Set a selection from each channel
            var idset = stringIDToTypeID("set");
            var desc1095 = new ActionDescriptor();
            var idnull = stringIDToTypeID("null");
            var ref448 = new ActionReference();
            var idchannel = stringIDToTypeID("channel");
            var idselection = stringIDToTypeID("selection");
            ref448.putProperty(idchannel, idselection);
            desc1095.putReference(idnull, ref448);
            var idto = stringIDToTypeID("to");
            var ref449 = new ActionReference();
            var idchannel = stringIDToTypeID("channel");
            var idordinal = stringIDToTypeID("ordinal");
            var idtargetEnum = stringIDToTypeID("targetEnum");
            ref449.putEnumerated(idchannel, idordinal, idtargetEnum);
            desc1095.putReference(idto, ref449);
            executeAction(idset, desc1095, DialogModes.NO);
            // Select the RGB composite channel
            var idselect = stringIDToTypeID("select");
            var desc1109 = new ActionDescriptor();
            var idnull = stringIDToTypeID("null");
            var ref462 = new ActionReference();
            var idchannel = stringIDToTypeID("channel");
            var idchannel = stringIDToTypeID("channel");
            var idRGB = stringIDToTypeID("RGB");
            ref462.putEnumerated(idchannel, idchannel, idRGB);
            desc1109.putReference(idnull, ref462);
            executeAction(idselect, desc1109, DialogModes.NO);
            // Copy the selection to a new layer
            var idcopyToLayer = stringIDToTypeID("copyToLayer");
			executeAction(idcopyToLayer, undefined, DialogModes.NO);
            // Select the Background layer
            var idselect = stringIDToTypeID("select");
            var desc1118 = new ActionDescriptor();
            var idnull = stringIDToTypeID("null");
            var ref468 = new ActionReference();
            var idlayer = stringIDToTypeID("layer");
            ref468.putName(idlayer, "Background");
            desc1118.putReference(idnull, ref468);
            var idmakeVisible = stringIDToTypeID("makeVisible");
            desc1118.putBoolean(idmakeVisible, false);
            var idlayerID = stringIDToTypeID("layerID");
            var list43 = new ActionList();
            list43.putInteger(1);
            desc1118.putList(idlayerID, list43);
            executeAction(idselect, desc1118, DialogModes.NO);
        }
    }
}

function pathsToRectangularSelectionToAlpha() {

    for (i = app.activeDocument.pathItems.length - 1; i > -1; i--) {

        // Select each path in the loop
        thePath = app.activeDocument.pathItems[i];
        thePath.select();

        // Path to selection
        function s2t(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(s2t("null"), reference);
        reference2.putEnumerated(s2t("path"), s2t("ordinal"), s2t("targetEnum"));
        descriptor.putReference(s2t("to"), reference2);
        descriptor.putInteger(s2t("version"), 1);
        descriptor.putBoolean(s2t("vectorMaskParams"), true);
        executeAction(s2t("set"), descriptor, DialogModes.NO);

        // Selection to rectangle
        var theBounds = app.activeDocument.selection.bounds;
        var theArray = [[theBounds[0], theBounds[1]], [theBounds[2], theBounds[1]], [theBounds[2], theBounds[3]], [theBounds[0], theBounds[3]]];
        app.activeDocument.selection.select(theArray, SelectionType.REPLACE, 0, false);

        // Selection to alpha channel
        var idduplicate = stringIDToTypeID( "duplicate" );
        var desc828 = new ActionDescriptor();
        var idnull = stringIDToTypeID( "null" );
        var ref327 = new ActionReference();
        var idchannel = stringIDToTypeID( "channel" );
        var idselection = stringIDToTypeID( "selection" );
        ref327.putProperty( idchannel, idselection );
        desc828.putReference( idnull, ref327 );
        executeAction( idduplicate, desc828, DialogModes.NO );

        app.activeDocument.selection.deselect();

    }
}


function workpathToSeparatePaths() {

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

}

 

https://prepression.blogspot.com/2017/11/downloading-and-installing-adobe-scripts.html

 

3 replies

Stephen Marsh
Community Expert
Stephen MarshCommunity ExpertCorrect answer
Community Expert
February 29, 2024

The following script will save each coin to JPEG in the same folder as the original with the scanned black background in an approximately "square-ish" crop.

 

This isn't the most elegant or cleanest code, but it should get the job done. Tested on an Intel Mac with Ps2021 and Ps2024.

This script is only intended for the current active document, one open document at a time. If it works for you, it could be recorded into an action for use with the File > Automate > Batch command.

 

/*
Isolate Multi Coin Scan Sheet to Individual Coins.jsx
v1.0 - 29th February 2024, Stephen Marsh
https://community.adobe.com/t5/photoshop-ecosystem-discussions/how-do-i-seperate-subjects-into-different-seperate-files-automatically/td-p/14449644
*/

#target photoshop

// Select > Select Subject
var idautoCutout = stringIDToTypeID( "autoCutout" );
    var desc547 = new ActionDescriptor();
    var idsampleAllLayers = stringIDToTypeID( "sampleAllLayers" );
    desc547.putBoolean( idsampleAllLayers, false );
executeAction( idautoCutout, desc547, DialogModes.NO );

// Contract selection to remove minor imperfections
var idcontract = stringIDToTypeID( "contract" );
    var desc549 = new ActionDescriptor();
    var idby = stringIDToTypeID( "by" );
    var idpixelsUnit = stringIDToTypeID( "pixelsUnit" );
    desc549.putUnitDouble( idby, idpixelsUnit, 50 );
    var idselectionModifyEffectAtCanvasBounds = stringIDToTypeID( "selectionModifyEffectAtCanvasBounds" );
    desc549.putBoolean( idselectionModifyEffectAtCanvasBounds, false );
executeAction( idcontract, desc549, DialogModes.NO );

// Smooth the selection to further reduce minor imperfections
var idsmoothness = stringIDToTypeID( "smoothness" );
    var desc554 = new ActionDescriptor();
    var idradius = stringIDToTypeID( "radius" );
    var idpixelsUnit = stringIDToTypeID( "pixelsUnit" );
    desc554.putUnitDouble( idradius, idpixelsUnit, 25 );
    var idselectionModifyEffectAtCanvasBounds = stringIDToTypeID( "selectionModifyEffectAtCanvasBounds" );
    desc554.putBoolean( idselectionModifyEffectAtCanvasBounds, false );
executeAction( idsmoothness, desc554, DialogModes.NO );

// Expand the selection for the crop area
var idexpand = stringIDToTypeID( "expand" );
    var desc556 = new ActionDescriptor();
    var idby = stringIDToTypeID( "by" );
    var idpixelsUnit = stringIDToTypeID( "pixelsUnit" );
    desc556.putUnitDouble( idby, idpixelsUnit, 100 );
    var idselectionModifyEffectAtCanvasBounds = stringIDToTypeID( "selectionModifyEffectAtCanvasBounds" );
    desc556.putBoolean( idselectionModifyEffectAtCanvasBounds, false );
executeAction( idexpand, desc556, DialogModes.NO );

// Create a temporary work path from the selection
var idmake = stringIDToTypeID( "make" );
    var desc574 = new ActionDescriptor();
    var idnull = stringIDToTypeID( "null" );
        var ref189 = new ActionReference();
        var idpath = stringIDToTypeID( "path" );
        ref189.putClass( idpath );
    desc574.putReference( idnull, ref189 );
    var idfrom = stringIDToTypeID( "from" );
        var ref190 = new ActionReference();
        var idselectionClass = stringIDToTypeID( "selectionClass" );
        var idselection = stringIDToTypeID( "selection" );
        ref190.putProperty( idselectionClass, idselection );
    desc574.putReference( idfrom, ref190 );
    var idtolerance = stringIDToTypeID( "tolerance" );
    var idpixelsUnit = stringIDToTypeID( "pixelsUnit" );
    desc574.putUnitDouble( idtolerance, idpixelsUnit, 1 );
executeAction(idmake, desc574, DialogModes.NO);

// Create separate paths
workpathToSeparatePaths()

// Remove the top/first working path
app.activeDocument.pathItems[0].remove();

// Create rectangular selection channels
pathsToRectangularSelectionToAlpha();

// Create layers from the alphas
alphasToLayers();

// Delete the Background layer
app.activeDocument.backgroundLayer.remove();

// Rename the layers
var docName = app.activeDocument.name.replace(/\.[^\.]+$/, '');
var zeroPadLength = 3;
var startNumber = 1;
for (var i = 0; i < activeDocument.layers.length; i++) {
		activeDocument.layers[i].name = docName + "_" + zeroPad(startNumber, zeroPadLength);
		startNumber++
	}
function zeroPad(num, digit) {
	var tmp = num.toString();
	while (tmp.length < digit) {
		tmp = "0" + tmp;
	}
	return tmp;
}

// Remove all paths
for (var i = app.activeDocument.pathItems.length - 1; i >= 0; i--) {
    app.activeDocument.pathItems[i].remove();
}

// Remove all alphas
for (i = app.activeDocument.channels.length - 1; i >= 0; i--) {
    if (app.activeDocument.channels[i].kind == "ChannelType.MASKEDAREA" || app.activeDocument.channels[i].kind == "ChannelType.SELECTEDAREA") {
        app.activeDocument.channels[i].remove();
    }
}

// Save all layers
layersToFiles();
app.activeDocument.close(SaveOptions.DONOTSAVECHANGES);


///// FUNCTIONS /////

function layersToFiles() {
    var outputPath = app.activeDocument.path.fsName;
    processAllLayersAndSets(app.activeDocument);

    // Loop over top level layers
    function processAllLayersAndSets(obj) {
        // Process all layers
        for (var al = obj.artLayers.length - 1; 0 <= al; al--) {
            app.activeDocument.activeLayer = obj.artLayers[al];

            // Skip the Background layer
            if (!activeDocument.activeLayer.isBackgroundLayer) {

                var filename = app.activeDocument.activeLayer.name;
                dupeSelectedLayers(filename);
                activeDocument.trim(TrimType.TRANSPARENT);

                var sfwOptions = new ExportOptionsSaveForWeb();
                sfwOptions.format = SaveDocumentType.JPEG;
                sfwOptions.includeProfile = true;
                sfwOptions.interlaced = 0;
                sfwOptions.optimized = true;
                sfwOptions.quality = 75;
                var jpgFile = new File(outputPath + "/" + filename + ".jpg");
                app.activeDocument.exportDocument(jpgFile, ExportType.SAVEFORWEB, sfwOptions);

                var sfwOptions = new ExportOptionsSaveForWeb();

                app.activeDocument.close(SaveOptions.DONOTSAVECHANGES);

                function dupeSelectedLayers(theDocName) {
                    function s2t(s) {
                        return app.stringIDToTypeID(s);
                    }
                    var descriptor = new ActionDescriptor();
                    var reference = new ActionReference();
                    var reference2 = new ActionReference();
                    reference.putClass(s2t("document"));
                    descriptor.putReference(s2t("null"), reference);
                    descriptor.putString(s2t("name"), theDocName);
                    reference2.putEnumerated(s2t("layer"), s2t("ordinal"), s2t("targetEnum"));
                    descriptor.putReference(s2t("using"), reference2);
                    executeAction(s2t("make"), descriptor, DialogModes.NO);
                }
            }
        }
    }
}

function alphasToLayers() {
    // Loop over the alpha channels
    for (var i = activeDocument.channels.length - 1; i >= 0; i--) {
        if (app.activeDocument.channels[i].kind === ChannelType.SELECTEDAREA || app.activeDocument.channels[i].kind === ChannelType.MASKEDAREA) {
            var theChannel = new Array(app.activeDocument.channels[i]);
            app.activeDocument.activeChannels = theChannel;
            // Set a selection from each channel
            var idset = stringIDToTypeID("set");
            var desc1095 = new ActionDescriptor();
            var idnull = stringIDToTypeID("null");
            var ref448 = new ActionReference();
            var idchannel = stringIDToTypeID("channel");
            var idselection = stringIDToTypeID("selection");
            ref448.putProperty(idchannel, idselection);
            desc1095.putReference(idnull, ref448);
            var idto = stringIDToTypeID("to");
            var ref449 = new ActionReference();
            var idchannel = stringIDToTypeID("channel");
            var idordinal = stringIDToTypeID("ordinal");
            var idtargetEnum = stringIDToTypeID("targetEnum");
            ref449.putEnumerated(idchannel, idordinal, idtargetEnum);
            desc1095.putReference(idto, ref449);
            executeAction(idset, desc1095, DialogModes.NO);
            // Select the RGB composite channel
            var idselect = stringIDToTypeID("select");
            var desc1109 = new ActionDescriptor();
            var idnull = stringIDToTypeID("null");
            var ref462 = new ActionReference();
            var idchannel = stringIDToTypeID("channel");
            var idchannel = stringIDToTypeID("channel");
            var idRGB = stringIDToTypeID("RGB");
            ref462.putEnumerated(idchannel, idchannel, idRGB);
            desc1109.putReference(idnull, ref462);
            executeAction(idselect, desc1109, DialogModes.NO);
            // Copy the selection to a new layer
            var idcopyToLayer = stringIDToTypeID("copyToLayer");
			executeAction(idcopyToLayer, undefined, DialogModes.NO);
            // Select the Background layer
            var idselect = stringIDToTypeID("select");
            var desc1118 = new ActionDescriptor();
            var idnull = stringIDToTypeID("null");
            var ref468 = new ActionReference();
            var idlayer = stringIDToTypeID("layer");
            ref468.putName(idlayer, "Background");
            desc1118.putReference(idnull, ref468);
            var idmakeVisible = stringIDToTypeID("makeVisible");
            desc1118.putBoolean(idmakeVisible, false);
            var idlayerID = stringIDToTypeID("layerID");
            var list43 = new ActionList();
            list43.putInteger(1);
            desc1118.putList(idlayerID, list43);
            executeAction(idselect, desc1118, DialogModes.NO);
        }
    }
}

function pathsToRectangularSelectionToAlpha() {

    for (i = app.activeDocument.pathItems.length - 1; i > -1; i--) {

        // Select each path in the loop
        thePath = app.activeDocument.pathItems[i];
        thePath.select();

        // Path to selection
        function s2t(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(s2t("null"), reference);
        reference2.putEnumerated(s2t("path"), s2t("ordinal"), s2t("targetEnum"));
        descriptor.putReference(s2t("to"), reference2);
        descriptor.putInteger(s2t("version"), 1);
        descriptor.putBoolean(s2t("vectorMaskParams"), true);
        executeAction(s2t("set"), descriptor, DialogModes.NO);

        // Selection to rectangle
        var theBounds = app.activeDocument.selection.bounds;
        var theArray = [[theBounds[0], theBounds[1]], [theBounds[2], theBounds[1]], [theBounds[2], theBounds[3]], [theBounds[0], theBounds[3]]];
        app.activeDocument.selection.select(theArray, SelectionType.REPLACE, 0, false);

        // Selection to alpha channel
        var idduplicate = stringIDToTypeID( "duplicate" );
        var desc828 = new ActionDescriptor();
        var idnull = stringIDToTypeID( "null" );
        var ref327 = new ActionReference();
        var idchannel = stringIDToTypeID( "channel" );
        var idselection = stringIDToTypeID( "selection" );
        ref327.putProperty( idchannel, idselection );
        desc828.putReference( idnull, ref327 );
        executeAction( idduplicate, desc828, DialogModes.NO );

        app.activeDocument.selection.deselect();

    }
}


function workpathToSeparatePaths() {

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

}

 

https://prepression.blogspot.com/2017/11/downloading-and-installing-adobe-scripts.html

 

Known Participant
March 4, 2024

Hello, I tried running the script, but how do I add the path to my script? As I am really new to this, I don't really know how to make photoshop find the script. Thanks already for the effort. 

Stephen Marsh
Community Expert
Community Expert
March 4, 2024

It's all detailed in the link provided at the foot of the script code:

 

https://prepression.blogspot.com/2017/11/downloading-and-installing-adobe-scripts.html

Stephen Marsh
Community Expert
Community Expert
February 27, 2024

@defaultsexaxvdwtesy 

 

The File > Automate > Crop & Straighten Photos command was not designed for this task, but I tried it anyway... It correctly isolated 4 out of 5 coins... However, it tried to straighten them, which you likely don't require. Anyway, it was just to see "what happened" and I didn't have any realistic expectations anyway.

 

So, what can be done to make this less tedious?

 

Select > Select Subject did isolate all 5 coins. You can then use Layer > New > Layer via Copy to isolate the 5 coins to a single transparent background, which is key to the next step...

 

I then used the "Split to Layers" script to isolate each image to a single layer:

 

https://photoshopscripts.wordpress.com/2012/12/09/split-to-layers/

https://github.com/ES-Collection/Photoshop-Scripts/blob/master/Split%202%20Layers.jsx

https://prepression.blogspot.com/2017/11/downloading-and-installing-adobe-scripts.html

 

You can then select all layers in the layers panel and right click and select the "Export As" option to save each isolated coin to a separate PNG/JPG/GIF file - Or use the File > Export > Layers to Files script if you need different file formats.

 

There are further workflow steps that could be added to semi-automate this, or perhaps fully automate... But I'd suggest baby steps first.

 

P.S. Are you looking for a square-cropped image with the scanned black background, or a square-cropped image with the coin isolated to a circle on a transparent background?

Known Participant
February 27, 2024

Hello thanks for the help already, but I have 2000 images with scans of coins and I would like to have them cropped per coin in seperate files, is there an easier way in photoshop to extract them? 

Stephen Marsh
Community Expert
Community Expert
February 29, 2024

Hello, I am looking for a squared-cropped image and the background is fine like this being scanned. Wow, I would really appreciate that. 


quote

Hello, I am looking for a squared-cropped image and the background is fine like this being scanned. Wow, I would really appreciate that. 


By @defaultsexaxvdwtesy

 

 

So, how did the script work for you?

Nancy OShea
Community Expert
Community Expert
February 27, 2024

Look at your Layers panel. 

Are these images flattened to a single layer or on separate layers?

 

Nancy O'Shea— Product User & Community Expert
Nancy OShea
Community Expert
Community Expert
February 27, 2024

Native Photoshop files (.psd) containing separate layers can export Layers to individual Files automatically.

Go to FILE > Export > Layers to Files.

 

 

 

 

 

Nancy O'Shea— Product User & Community Expert