Copy link to clipboard
Copied
Hi, I'm trialing CC20.0.3 for manually counting objects on large files. The basic system works very well but I'm having difficulty in exporting the image with the count numbers in a format that others can use to verify my counts - ie prints or jpegs. I've tried several things including Merging all Layers, rasterising everything etc but can't get the numbers to be included in the image.
The only work around so far is using Print Screen and then stitiching the images together again but with the large files I'm using it's a tedious process!
If anyone has any ideas, I'd really appreciate the help.
Thanks
This (saved as a txt-file but with the extension »jsx« into the Presets/Scripts-Folder) might work:
...
// create text layers with numbers for count tool points;
// 2019, use it at your own risk;
#target photoshop
if (app.documents.length > 0) {
var ref = new ActionReference();
ref.putEnumerated( charIDToTypeID("Dcmn"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );
var docDesc = executeActionGet(ref);
if (docDesc.hasKey(stringIDToTypeID("countClass")) == true) {
// set to 72dpi and pixels;
var originalRu
Copy link to clipboard
Copied
If you want to convert the count points to pixel data you might have to use Scripting.
Copy link to clipboard
Copied
Just saw your post, c.pfaffenbichler after I posted mine. Any idea on a script that would capture the note location? The rest would be fairly easy, but I'm not too good with modifying AM code.
Copy link to clipboard
Copied
Thank you very much for this.
Copy link to clipboard
Copied
You might be able to do this using a script that gets the location of the counts, then replacing them with a actual text layer. I'm not sure how to capture this data, but if you post on the scripting forum, someone might know.
Copy link to clipboard
Copied
This (saved as a txt-file but with the extension »jsx« into the Presets/Scripts-Folder) might work:
// create text layers with numbers for count tool points;
// 2019, use it at your own risk;
#target photoshop
if (app.documents.length > 0) {
var ref = new ActionReference();
ref.putEnumerated( charIDToTypeID("Dcmn"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );
var docDesc = executeActionGet(ref);
if (docDesc.hasKey(stringIDToTypeID("countClass")) == true) {
// set to 72dpi and pixels;
var originalRulerUnits = preferences.rulerUnits;
preferences.rulerUnits = Units.PIXELS;
var myDocument = app.activeDocument;
var originalResolution = myDocument.resolution;
myDocument.resizeImage(undefined, undefined, 72, ResampleMethod.NONE);
// get coordinates;
var counter =docDesc.getList(stringIDToTypeID("countClass"));
var thePoints = new Array;
for (var c = 0; c < counter.count; c++) {
var thisOne = counter.getObjectValue(c);
thePoints.push([thisOne.getUnitDoubleValue(stringIDToTypeID("x")), thisOne.getUnitDoubleValue(stringIDToTypeID("y"))])
};
// create a smart object;
theArray = [[[[0,-3],[1.66,-3],[-1.66,-3],"SMOOTH"],
[[3,0],[3,1.66],[3,-1.66],"SMOOTH"],
[[0,3],[-1.66,3],[1.66,3],"SMOOTH"],
[[-3,0],[-3,-1.66],[-3,1.66],"SMOOTH"], true]];
var aPath = createPath10 (theArray, "circle");
aPath.select;
makeFillLayer ("circle", 0, 0, 0);
// convert to smart object ;
var id557 = charIDToTypeID( "slct" );
var desc108 = new ActionDescriptor();
var id558 = charIDToTypeID( "null" );
var ref77 = new ActionReference();
var id559 = charIDToTypeID( "Mn " );
var id560 = charIDToTypeID( "MnIt" );
var id561 = stringIDToTypeID( "newPlacedLayer" );
ref77.putEnumerated( id559, id560, id561 );
desc108.putReference( id558, ref77 );
executeAction( id557, desc108, DialogModes.NO );
var theSO = myDocument.activeLayer;
// remove path;
aPath.remove();
// create a set;
var theSet = myDocument.layerSets.add();
theSet.name = "connectTheDots";
// work through the path points;
for (var m = 0; m < thePoints.length; m++) {
var theArray = thePoints
; // make circle;
var theCircle = theSO.duplicate(theSet, ElementPlacement.PLACEATBEGINNING);
myDocument.activeLayer = theCircle;
theCircle.translate(theArray[0], theArray[1]);
theCircle.name = (m+1)+"_circle";
// make texts;
makeNumber (theSet, (m+1), theArray[0], theArray[1] - 12)
};
theSO.visible = false;
// reset image size;
myDocument.resizeImage(undefined, undefined, originalResolution, ResampleMethod.NONE);
preferences.rulerUnits = originalRulerUnits;
}
};
////////////////////////////////////
////////////////////////////////////
////////////////////////////////////
////// create number //////
function makeNumber (myDocument, theNumber, theX, theY) {
var textLayer = myDocument.artLayers.add();
textLayer.kind = LayerKind.TEXT;
textLayer.blendMode = BlendMode.NORMAL;
textLayer.opacity = 100;
var myTextRef = textLayer.textItem;
myTextRef.size = 24;
myTextRef.justification = Justification.CENTER;
myTextRef.font = "Courier";
var newColor = new SolidColor();
newColor.rgb.red = 0;
newColor.rgb.green = 0;
newColor.rgb.blue = 0;
myTextRef.color = newColor;
myTextRef.position = new Array(theX, theY);
myTextRef.contents = theNumber;
};
////// the fill-layer-function //////
function makeFillLayer (theName, theHue, theSat, theBright) {
// =======================================================
var idsetd = charIDToTypeID( "setd" );
var desc4 = new ActionDescriptor();
var idnull = charIDToTypeID( "null" );
var ref2 = new ActionReference();
var idClr = charIDToTypeID( "Clr " );
var idFrgC = charIDToTypeID( "FrgC" );
ref2.putProperty( idClr, idFrgC );
desc4.putReference( idnull, ref2 );
var idT = charIDToTypeID( "T " );
var desc5 = new ActionDescriptor();
var idH = charIDToTypeID( "H " );
var idAng = charIDToTypeID( "#Ang" );
desc5.putUnitDouble( idH, idAng, theHue );
var idStrt = charIDToTypeID( "Strt" );
desc5.putDouble( idStrt, theSat );
var idBrgh = charIDToTypeID( "Brgh" );
desc5.putDouble( idBrgh, theBright );
var idHSBC = charIDToTypeID( "HSBC" );
desc4.putObject( idT, idHSBC, desc5 );
executeAction( idsetd, desc4, DialogModes.NO );
// =======================================================
var id212 = charIDToTypeID( "Mk " );
var desc39 = new ActionDescriptor();
var id213 = charIDToTypeID( "null" );
var ref27 = new ActionReference();
var id214 = stringIDToTypeID( "contentLayer" );
ref27.putClass( id214 ); desc39.putReference( id213, ref27 );
var id215 = charIDToTypeID( "Usng" );
var desc40 = new ActionDescriptor();
var id216 = charIDToTypeID( "Type" );
var id217 = stringIDToTypeID( "solidColorLayer" );
desc40.putClass( id216, id217 );
var id218 = stringIDToTypeID( "contentLayer" );
desc39.putObject( id215, id218, desc40 );
executeAction( id212, desc39, DialogModes.NO );
app.activeDocument.activeLayer.name = theName;
return app.activeDocument.activeLayer
};
////// function to create path from array with one array per point that holds anchor, leftdirection, etc, 2010 //////
function createPath10 (theArray, thePathName) {
var originalRulerUnits = app.preferences.rulerUnits;
app.preferences.rulerUnits = Units.POINTS;
lineSubPathArray = new Array ();
if (theArray[theArray.length - 1].constructor != Array) {var numberOfPaths = theArray.length - 1}
else {var numberOfPaths = theArray.length};
for (var b = 0; b < numberOfPaths; b++) {
var lineArray = new Array ();
lineSubPathArray = new SubPathInfo();
if (theArray[theArray.length - 1].constructor == Array) {
lineSubPathArray.closed = true;
var numberOfPoints = theArray.length
}
else {
lineSubPathArray.closed = theArray[theArray.length - 1]
var numberOfPoints = theArray.length - 1
};
for (c = 0; c < numberOfPoints; c++) {
lineArray
= new PathPointInfo; switch (theArray
[3]) { case "CORNER":
lineArray
.kind = PointKind.CORNERPOINT; break;
case "SMOOTH":
lineArray
.kind = PointKind.SMOOTHPOINT; break;
default:
lineArray
.kind = PointKind.CORNERPOINT; break
};
lineArray
.anchor = theArray [0]; if (theArray
[1].length == 2) {lineArray .leftDirection = theArray [1]} else {lineArray
.leftDirection = theArray [0]}; if (theArray
[2].length == 2) {lineArray .rightDirection = theArray [2]} else {lineArray
.rightDirection = theArray [0]}; };
lineSubPathArray.operation = ShapeOperation.SHAPEXOR;
lineSubPathArray.entireSubPath = lineArray;
};
var myPathItem = app.activeDocument.pathItems.add(thePathName, lineSubPathArray);
app.preferences.rulerUnits = originalRulerUnits;
return myPathItem
};
Edit: Example:
Copy link to clipboard
Copied
Hi,
I hope this message gets through to you as I’m having a real problem in working out how to reply to posts in response to my original query. Think that might be something to do with Firefox which I’ll have to look into.
Just wanted to say a huge thank you for this script. I’m not particularly tech-minded but I’ll pluck up my courage and give it all a go!
Thanks again,
Malcolm
Copy link to clipboard
Copied
Hi,
Thank you again for this great result. That gives me the total population in layers which are easily manged from then on. This is really useful in its own right.
As I explained to Stephen Marsh (and should have mentioned in my original query - apologies) I'm dividing the population into 6 categories, with each category identified by a different colour. Is it somehow possible to run the script for each of the Count Groups I've set up and also replicate the colour of the circle and number for that group?
Many thanks,
Malcolm
Copy link to clipboard
Copied
Can you provide a sample image (with source and intended result)?
If the content is confidential fill it with black.
Copy link to clipboard
Copied
Hi. Thank you. Sample image attached. I hope this gives you enough information. It didn’t seem to load directly onto the forum page
Copy link to clipboard
Copied
Sorry, no images visible.
Did you try positing jpgs via the Insert Image icon?
Copy link to clipboard
Copied
Thanks for this. I’ll try again – maybe reduce it further.
Malcolm
Copy link to clipboard
Copied
Ah...finally. I hope this is large enough to be useful.
Copy link to clipboard
Copied
Sorry, but I meant the actual image with the count groups and count points.
I’ve looked into the count groups in the meantime and I have so far found no way to get their names and colors via conventional Scripting.
Are the groups always in the same order and have the same names and colors?
Copy link to clipboard
Copied
Could you give this a try?
The line
var theColorLabels = [[0,0,255], [0,255,0], [255,0,0], [0,255,255], [255,255,0], [255,0,255]];
sets up the (so far) 6 colors that are applied to the Groups as Color Overlays, so you may have to adapt it to your needs.
The Script is based on a fairly old »connect-the-dots«-Script and uses DOM code that runs slower than comparable AM-code for some things, like the type layer creation.
If the running time is an issue and you want to improve the Script’s performance feel free to post it over on
and ask for advice from the regulars over there.
// create text layers with numbers for count tool points;
// 2019, use it at your own risk;
#target "photoshop-130.064"
if (app.documents.length > 0) {
var ref = new ActionReference();
ref.putEnumerated( charIDToTypeID("Dcmn"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );
var docDesc = executeActionGet(ref);
if (docDesc.hasKey(stringIDToTypeID("countClass")) == true) {
// set to 72dpi and pixels;
var originalRulerUnits = preferences.rulerUnits;
preferences.rulerUnits = Units.PIXELS;
var myDocument = app.activeDocument;
var originalResolution = myDocument.resolution;
myDocument.resizeImage(undefined, undefined, 72, ResampleMethod.NONE);
// get coordinates;
var countClass =docDesc.getList(stringIDToTypeID("countClass"));
var thePoints = [[]];
var thisGroup = 0;
for (var c = 0; c < countClass.count; c++) {
var thisOne = countClass.getObjectValue(c);
var theGroup = thisOne.getInteger(stringIDToTypeID("group"));
if (c == 0) {thisGroup = theGroup};
if (thisGroup != theGroup) {
thePoints.push([]);
thisGroup = theGroup
};
//checkDesc2(thisOne);
thePoints[thePoints.length-1].push([thisOne.getUnitDoubleValue(stringIDToTypeID("x")), thisOne.getUnitDoubleValue(stringIDToTypeID("y"))])
};
// create a smart object;
theArray = [[[[0,-3],[1.66,-3],[-1.66,-3],"SMOOTH"],
[[3,0],[3,1.66],[3,-1.66],"SMOOTH"],
[[0,3],[-1.66,3],[1.66,3],"SMOOTH"],
[[-3,0],[-3,-1.66],[-3,1.66],"SMOOTH"], true]];
var aPath = createPath10 (theArray, "circle");
aPath.select;
makeFillLayer ("circle", 0, 0, 0);
// convert to smart object ;
var desc108 = new ActionDescriptor();
var ref77 = new ActionReference();
ref77.putEnumerated( charIDToTypeID( "Mn " ), charIDToTypeID( "MnIt" ), stringIDToTypeID( "newPlacedLayer" ) );
desc108.putReference( charIDToTypeID( "null" ), ref77 );
executeAction( charIDToTypeID( "slct" ), desc108, DialogModes.NO );
var theSO = myDocument.activeLayer;
// remove path;
aPath.remove();
var theColorLabels = [[0,0,255], [0,255,0], [255,0,0], [0,255,255], [255,255,0], [255,0,255]];
////////////////////////////////////
for (var n = 0; n < thePoints.length; n++) {
// create a set;
var theSet = myDocument.layerSets.add();
theSet.name = "group " + String(n+1);
colorOverlay (myDocument, theSet, theColorLabels
[0], theColorLabels [1], theColorLabels [2]); // work through the path points;
for (var m = 0; m < thePoints
.length; m++) { var theArray = thePoints
; // make circle;
var theCircle = theSO.duplicate(theSet, ElementPlacement.PLACEATBEGINNING);
myDocument.activeLayer = theCircle;
theCircle.translate(theArray[0], theArray[1]);
theCircle.name = (m+1)+"_circle";
// make texts;
makeNumber (theSet, (m+1), theArray[0], theArray[1] - 12)
};
};
////////////////////////////////////
theSO.visible = false;
// reset image size;
myDocument.resizeImage(undefined, undefined, originalResolution, ResampleMethod.NONE);
preferences.rulerUnits = originalRulerUnits;
}
};
////////////////////////////////////
////////////////////////////////////
////////////////////////////////////
////// create number //////
function makeNumber (myDocument, theNumber, theX, theY) {
var textLayer = myDocument.artLayers.add();
textLayer.kind = LayerKind.TEXT;
textLayer.blendMode = BlendMode.NORMAL;
textLayer.opacity = 100;
var myTextRef = textLayer.textItem;
myTextRef.size = 24;
myTextRef.justification = Justification.CENTER;
myTextRef.font = "Courier";
var newColor = new SolidColor();
newColor.rgb.red = 0;
newColor.rgb.green = 0;
newColor.rgb.blue = 0;
myTextRef.color = newColor;
myTextRef.position = new Array(theX, theY);
myTextRef.contents = theNumber;
};
////// the fill-layer-function //////
function makeFillLayer (theName, theHue, theSat, theBright) {
// =======================================================
var idsetd = charIDToTypeID( "setd" );
var desc4 = new ActionDescriptor();
var idnull = charIDToTypeID( "null" );
var ref2 = new ActionReference();
var idClr = charIDToTypeID( "Clr " );
var idFrgC = charIDToTypeID( "FrgC" );
ref2.putProperty( idClr, idFrgC );
desc4.putReference( idnull, ref2 );
var idT = charIDToTypeID( "T " );
var desc5 = new ActionDescriptor();
var idH = charIDToTypeID( "H " );
var idAng = charIDToTypeID( "#Ang" );
desc5.putUnitDouble( idH, idAng, theHue );
var idStrt = charIDToTypeID( "Strt" );
desc5.putDouble( idStrt, theSat );
var idBrgh = charIDToTypeID( "Brgh" );
desc5.putDouble( idBrgh, theBright );
var idHSBC = charIDToTypeID( "HSBC" );
desc4.putObject( idT, idHSBC, desc5 );
executeAction( idsetd, desc4, DialogModes.NO );
// =======================================================
var id212 = charIDToTypeID( "Mk " );
var desc39 = new ActionDescriptor();
var id213 = charIDToTypeID( "null" );
var ref27 = new ActionReference();
var id214 = stringIDToTypeID( "contentLayer" );
ref27.putClass( id214 ); desc39.putReference( id213, ref27 );
var id215 = charIDToTypeID( "Usng" );
var desc40 = new ActionDescriptor();
var id216 = charIDToTypeID( "Type" );
var id217 = stringIDToTypeID( "solidColorLayer" );
desc40.putClass( id216, id217 );
var id218 = stringIDToTypeID( "contentLayer" );
desc39.putObject( id215, id218, desc40 );
executeAction( id212, desc39, DialogModes.NO );
app.activeDocument.activeLayer.name = theName;
return app.activeDocument.activeLayer
};
////// function to create path from array with one array per point that holds anchor, leftdirection, etc, 2010 //////
function createPath10 (theArray, thePathName) {
var originalRulerUnits = app.preferences.rulerUnits;
app.preferences.rulerUnits = Units.POINTS;
lineSubPathArray = new Array ();
if (theArray[theArray.length - 1].constructor != Array) {var numberOfPaths = theArray.length - 1}
else {var numberOfPaths = theArray.length};
for (var b = 0; b < numberOfPaths; b++) {
var lineArray = new Array ();
lineSubPathArray = new SubPathInfo();
if (theArray[theArray.length - 1].constructor == Array) {
lineSubPathArray.closed = true;
var numberOfPoints = theArray.length
}
else {
lineSubPathArray.closed = theArray[theArray.length - 1]
var numberOfPoints = theArray.length - 1
};
for (c = 0; c < numberOfPoints; c++) {
lineArray
= new PathPointInfo; switch (theArray
[3]) { case "CORNER":
lineArray
.kind = PointKind.CORNERPOINT; break;
case "SMOOTH":
lineArray
.kind = PointKind.SMOOTHPOINT; break;
default:
lineArray
.kind = PointKind.CORNERPOINT; break
};
lineArray
.anchor = theArray [0]; if (theArray
[1].length == 2) {lineArray .leftDirection = theArray [1]} else {lineArray
.leftDirection = theArray [0]}; if (theArray
[2].length == 2) {lineArray .rightDirection = theArray [2]} else {lineArray
.rightDirection = theArray [0]}; };
lineSubPathArray.operation = ShapeOperation.SHAPEXOR;
lineSubPathArray.entireSubPath = lineArray;
};
var myPathItem = app.activeDocument.pathItems.add(thePathName, lineSubPathArray);
app.preferences.rulerUnits = originalRulerUnits;
return myPathItem
};
////// color overlay //////
function colorOverlay (myDocument, myLayer, theR, theG, theB) {
myDocument.activeLayer = myLayer;
// =======================================================
var idsetd = charIDToTypeID( "setd" );
var desc5 = new ActionDescriptor();
var idnull = charIDToTypeID( "null" );
var ref2 = new ActionReference();
var idPrpr = charIDToTypeID( "Prpr" );
var idLefx = charIDToTypeID( "Lefx" );
ref2.putProperty( idPrpr, idLefx );
var idLyr = charIDToTypeID( "Lyr " );
var idOrdn = charIDToTypeID( "Ordn" );
var idTrgt = charIDToTypeID( "Trgt" );
ref2.putEnumerated( idLyr, idOrdn, idTrgt );
desc5.putReference( idnull, ref2 );
var idT = charIDToTypeID( "T " );
var desc6 = new ActionDescriptor();
var idScl = charIDToTypeID( "Scl " );
var idPrc = charIDToTypeID( "#Prc" );
desc6.putUnitDouble( idScl, idPrc, 416.666667 );
var idSoFi = charIDToTypeID( "SoFi" );
var desc7 = new ActionDescriptor();
var idenab = charIDToTypeID( "enab" );
desc7.putBoolean( idenab, true );
var idMd = charIDToTypeID( "Md " );
var idBlnM = charIDToTypeID( "BlnM" );
var idNrml = charIDToTypeID( "Nrml" );
desc7.putEnumerated( idMd, idBlnM, idNrml );
var idOpct = charIDToTypeID( "Opct" );
var idPrc = charIDToTypeID( "#Prc" );
desc7.putUnitDouble( idOpct, idPrc, 100.000000 );
var idClr = charIDToTypeID( "Clr " );
var desc8 = new ActionDescriptor();
var idRd = charIDToTypeID( "Rd " );
desc8.putDouble( idRd, theR );
var idGrn = charIDToTypeID( "Grn " );
desc8.putDouble( idGrn, theG );
var idBl = charIDToTypeID( "Bl " );
desc8.putDouble( idBl, theB );
var idRGBC = charIDToTypeID( "RGBC" );
desc7.putObject( idClr, idRGBC, desc8 );
var idSoFi = charIDToTypeID( "SoFi" );
desc6.putObject( idSoFi, idSoFi, desc7 );
var idLefx = charIDToTypeID( "Lefx" );
desc5.putObject( idT, idLefx, desc6 );
executeAction( idsetd, desc5, DialogModes.NO );
};
Copy link to clipboard
Copied
Hi,
That seems to work very well. Thank you so much. That's going to make my life so much easier compared with doing a manual count layer as before. You've been very generous with your time and expertise - I really appreciate it.
Malcolm
Copy link to clipboard
Copied
I noticed something, though: The way I set it up in the Script empty count groups would be ignored.
That might mess up your color coding.
Copy link to clipboard
Copied
Thanks for this. I’ve got to process some more surveys over the next few days so I’ll check it out.
Best wishes.
Malcolm
Copy link to clipboard
Copied
Hi!
I need to convert Count Tool numbers to layers. Just found your script and it might be what I'm looking for. It seems however that I can't make it appear in the scripts menu.
I'm using Photoshop version 22.5.4. that will be replaced soon by the newer version when I get the new M1 mac.
Is there a compatibility issue with this script and this vesion of Photoshop or am I just doing something wrong?
Copy link to clipboard
Copied
Do others need to visually verify the position of each separate count, or just the total number of counts per image?
Copy link to clipboard
Copied
Hi,
Thanks for your question.
The population displayed in each image needs to be categorised into 6 different types with each object numbered, with the colour of the number identifying the category. The images are then sent off to have the totals and categorisation checked, so the moderators need to see everything in the image.
Copy link to clipboard
Copied
Fixed version of the second script:
#target photoshop
if (app.documents.length > 0) {
var ref = new ActionReference();
ref.putEnumerated(charIDToTypeID("Dcmn"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt"));
var docDesc = executeActionGet(ref);
if (docDesc.hasKey(stringIDToTypeID("countClass")) == true) {
// set to 72dpi and pixels;
var originalRulerUnits = preferences.rulerUnits;
preferences.rulerUnits = Units.PIXELS;
var myDocument = app.activeDocument;
var originalResolution = myDocument.resolution;
myDocument.resizeImage(undefined, undefined, 72, ResampleMethod.NONE);
// get coordinates;
var countClass = docDesc.getList(stringIDToTypeID("countClass"));
var thePoints = [
[]
];
var thisGroup = 0;
for (var c = 0; c < countClass.count; c++) {
var thisOne = countClass.getObjectValue(c);
var theGroup = thisOne.getInteger(stringIDToTypeID("group"));
if (c == 0) {
thisGroup = theGroup
};
if (thisGroup != theGroup) {
thePoints.push([]);
thisGroup = theGroup
};
//checkDesc2(thisOne);
thePoints[thePoints.length - 1].push([thisOne.getUnitDoubleValue(stringIDToTypeID("x")), thisOne.getUnitDoubleValue(stringIDToTypeID("y"))])
};
// create a smart object;
theArray = [[
[[0, -3],[1.66, -3],[-1.66, -3], "SMOOTH"],
[[3, 0],[3, 1.66],[3, -1.66], "SMOOTH"],
[[0, 3],[-1.66, 3],[1.66, 3], "SMOOTH"],
[[-3, 0],[-3, -1.66],[-3, 1.66], "SMOOTH"], true
]];
var aPath = createPath10(theArray, "circle");
aPath.select;
makeFillLayer("circle", 0, 0, 0);
// convert to smart object ;
var desc108 = new ActionDescriptor();
var ref77 = new ActionReference();
ref77.putEnumerated(charIDToTypeID("Mn "), charIDToTypeID("MnIt"), stringIDToTypeID("newPlacedLayer"));
desc108.putReference(charIDToTypeID("null"), ref77);
executeAction(charIDToTypeID("slct"), desc108, DialogModes.NO);
var theSO = myDocument.activeLayer;
// remove path;
aPath.remove();
var theColorLabels = [[0, 0, 255],[0, 255, 0],[255, 0, 0],[0, 255, 255],[255, 255, 0],[255, 0, 255]];
////////////////////////////////////
for (var n = 0; n < thePoints.length; n++) {
// create a set;
var theSet = myDocument.layerSets.add();
theSet.name = "group " + String(n + 1);
colorOverlay(myDocument, theSet, theColorLabels[n][0], theColorLabels[n][1], theColorLabels[n][2]);
// work through the path points;
for (var m = 0; m < thePoints[n].length; m++) {
var theArray = thePoints[n][m];
// make circle;
var theCircle = theSO.duplicate(theSet, ElementPlacement.PLACEATBEGINNING);
myDocument.activeLayer = theCircle;
theCircle.translate(theArray[0], theArray[1]);
theCircle.name = (m + 1) + "_circle";
// make texts;
makeNumber(theSet, (m + 1), theArray[0], theArray[1] - 12)
};
};
////////////////////////////////////
theSO.visible = false;
// reset image size;
myDocument.resizeImage(undefined, undefined, originalResolution, ResampleMethod.NONE);
preferences.rulerUnits = originalRulerUnits;
}
};
////////////////////////////////////
////////////////////////////////////
////////////////////////////////////
////// create number //////
function makeNumber(myDocument, theNumber, theX, theY) {
var textLayer = myDocument.artLayers.add();
textLayer.kind = LayerKind.TEXT;
textLayer.blendMode = BlendMode.NORMAL;
textLayer.opacity = 100;
var myTextRef = textLayer.textItem;
myTextRef.size = 24;
myTextRef.justification = Justification.CENTER;
myTextRef.font = "Courier";
var newColor = new SolidColor();
newColor.rgb.red = 0;
newColor.rgb.green = 0;
newColor.rgb.blue = 0;
myTextRef.color = newColor;
myTextRef.position = new Array(theX, theY);
myTextRef.contents = theNumber;
};
////// the fill-layer-function //////
function makeFillLayer(theName, theHue, theSat, theBright) {
// =======================================================
var idsetd = charIDToTypeID("setd");
var desc4 = new ActionDescriptor();
var idnull = charIDToTypeID("null");
var ref2 = new ActionReference();
var idClr = charIDToTypeID("Clr ");
var idFrgC = charIDToTypeID("FrgC");
ref2.putProperty(idClr, idFrgC);
desc4.putReference(idnull, ref2);
var idT = charIDToTypeID("T ");
var desc5 = new ActionDescriptor();
var idH = charIDToTypeID("H ");
var idAng = charIDToTypeID("#Ang");
desc5.putUnitDouble(idH, idAng, theHue);
var idStrt = charIDToTypeID("Strt");
desc5.putDouble(idStrt, theSat);
var idBrgh = charIDToTypeID("Brgh");
desc5.putDouble(idBrgh, theBright);
var idHSBC = charIDToTypeID("HSBC");
desc4.putObject(idT, idHSBC, desc5);
executeAction(idsetd, desc4, DialogModes.NO);
// =======================================================
var id212 = charIDToTypeID("Mk ");
var desc39 = new ActionDescriptor();
var id213 = charIDToTypeID("null");
var ref27 = new ActionReference();
var id214 = stringIDToTypeID("contentLayer");
ref27.putClass(id214);
desc39.putReference(id213, ref27);
var id215 = charIDToTypeID("Usng");
var desc40 = new ActionDescriptor();
var id216 = charIDToTypeID("Type");
var id217 = stringIDToTypeID("solidColorLayer");
desc40.putClass(id216, id217);
var id218 = stringIDToTypeID("contentLayer");
desc39.putObject(id215, id218, desc40);
executeAction(id212, desc39, DialogModes.NO);
app.activeDocument.activeLayer.name = theName;
return app.activeDocument.activeLayer
};
////// function to create path from array with one array per point that holds anchor, leftdirection, etc, 2010 //////
function createPath10(theArray, thePathName) {
var originalRulerUnits = app.preferences.rulerUnits;
app.preferences.rulerUnits = Units.POINTS;
lineSubPathArray = new Array();
if (theArray[theArray.length - 1].constructor != Array) {
var numberOfPaths = theArray.length - 1
} else {
var numberOfPaths = theArray.length
};
for (var b = 0; b < numberOfPaths; b++) {
var lineArray = new Array();
lineSubPathArray[b] = new SubPathInfo();
if (theArray[b][theArray[b].length - 1].constructor == Array) {
lineSubPathArray[b].closed = true;
var numberOfPoints = theArray[b].length
} else {
lineSubPathArray[b].closed = theArray[b][theArray[b].length - 1]
var numberOfPoints = theArray[b].length - 1
};
for (c = 0; c < numberOfPoints; c++) {
lineArray[c] = new PathPointInfo;
switch (theArray[b][c][3]) {
case "CORNER":
lineArray[c].kind = PointKind.CORNERPOINT;
break;
case "SMOOTH":
lineArray[c].kind = PointKind.SMOOTHPOINT;
break;
default:
lineArray[c].kind = PointKind.CORNERPOINT;
break
};
lineArray[c].anchor = theArray[b][c][0];
if (theArray[b][c][1].length == 2) {
lineArray[c].leftDirection = theArray[b][c][1]
} else {
lineArray[c].leftDirection = theArray[b][c][0]
};
if (theArray[b][c][2].length == 2) {
lineArray[c].rightDirection = theArray[b][c][2]
} else {
lineArray[c].rightDirection = theArray[b][c][0]
};
};
lineSubPathArray[b].operation = ShapeOperation.SHAPEXOR;
lineSubPathArray[b].entireSubPath = lineArray;
};
var myPathItem = app.activeDocument.pathItems.add(thePathName, lineSubPathArray);
app.preferences.rulerUnits = originalRulerUnits;
return myPathItem
};
////// color overlay //////
function colorOverlay(myDocument, myLayer, theR, theG, theB) {
myDocument.activeLayer = myLayer;
// =======================================================
var idsetd = charIDToTypeID("setd");
var desc5 = new ActionDescriptor();
var idnull = charIDToTypeID("null");
var ref2 = new ActionReference();
var idPrpr = charIDToTypeID("Prpr");
var idLefx = charIDToTypeID("Lefx");
ref2.putProperty(idPrpr, idLefx);
var idLyr = charIDToTypeID("Lyr ");
var idOrdn = charIDToTypeID("Ordn");
var idTrgt = charIDToTypeID("Trgt");
ref2.putEnumerated(idLyr, idOrdn, idTrgt);
desc5.putReference(idnull, ref2);
var idT = charIDToTypeID("T ");
var desc6 = new ActionDescriptor();
var idScl = charIDToTypeID("Scl ");
var idPrc = charIDToTypeID("#Prc");
desc6.putUnitDouble(idScl, idPrc, 416.666667);
var idSoFi = charIDToTypeID("SoFi");
var desc7 = new ActionDescriptor();
var idenab = charIDToTypeID("enab");
desc7.putBoolean(idenab, true);
var idMd = charIDToTypeID("Md ");
var idBlnM = charIDToTypeID("BlnM");
var idNrml = charIDToTypeID("Nrml");
desc7.putEnumerated(idMd, idBlnM, idNrml);
var idOpct = charIDToTypeID("Opct");
var idPrc = charIDToTypeID("#Prc");
desc7.putUnitDouble(idOpct, idPrc, 100.000000);
var idClr = charIDToTypeID("Clr ");
var desc8 = new ActionDescriptor();
var idRd = charIDToTypeID("Rd ");
desc8.putDouble(idRd, theR);
var idGrn = charIDToTypeID("Grn ");
desc8.putDouble(idGrn, theG);
var idBl = charIDToTypeID("Bl ");
desc8.putDouble(idBl, theB);
var idRGBC = charIDToTypeID("RGBC");
desc7.putObject(idClr, idRGBC, desc8);
var idSoFi = charIDToTypeID("SoFi");
desc6.putObject(idSoFi, idSoFi, desc7);
var idLefx = charIDToTypeID("Lefx");
desc5.putObject(idT, idLefx, desc6);
executeAction(idsetd, desc5, DialogModes.NO);
};
Copy link to clipboard
Copied
Hi,
Tom asked me to re-post the original script. This, I believe, is it:
// create text layers with numbers for count tool points;
// 2019, use it at your own risk;
#target photoshop
if (app.documents.length > 0) {
var ref = new ActionReference();
ref.putEnumerated( charIDToTypeID("Dcmn"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );
var docDesc = executeActionGet(ref);
if (docDesc.hasKey(stringIDToTypeID("countClass")) == true) {
// set to 72dpi and pixels;
var originalRulerUnits = preferences.rulerUnits;
preferences.rulerUnits = Units.PIXELS;
var myDocument = app.activeDocument;
var originalResolution = myDocument.resolution;
myDocument.resizeImage(undefined, undefined, 72, ResampleMethod.NONE);
// get coordinates;
var counter =docDesc.getList(stringIDToTypeID("countClass"));
var thePoints = new Array;
for (var c = 0; c < counter.count; c++) {
var thisOne = counter.getObjectValue(c);
thePoints.push([thisOne.getUnitDoubleValue(stringIDToTypeID("x")), thisOne.getUnitDoubleValue(stringIDToTypeID("y"))])
};
// create a smart object;
theArray = [[[[0,-3],[1.66,-3],[-1.66,-3],"SMOOTH"],
[[3,0],[3,1.66],[3,-1.66],"SMOOTH"],
[[0,3],[-1.66,3],[1.66,3],"SMOOTH"],
[[-3,0],[-3,-1.66],[-3,1.66],"SMOOTH"], true]];
var aPath = createPath10 (theArray, "circle");
aPath.select;
makeFillLayer ("circle", 0, 0, 0);
// convert to smart object ;
var id557 = charIDToTypeID( "slct" );
var desc108 = new ActionDescriptor();
var id558 = charIDToTypeID( "null" );
var ref77 = new ActionReference();
var id559 = charIDToTypeID( "Mn " );
var id560 = charIDToTypeID( "MnIt" );
var id561 = stringIDToTypeID( "newPlacedLayer" );
ref77.putEnumerated( id559, id560, id561 );
desc108.putReference( id558, ref77 );
executeAction( id557, desc108, DialogModes.NO );
var theSO = myDocument.activeLayer;
// remove path;
aPath.remove();
// create a set;
var theSet = myDocument.layerSets.add();
theSet.name = "connectTheDots";
// work through the path points;
for (var m = 0; m < thePoints.length; m++) {
var theArray = thePoints[m];
// make circle;
var theCircle = theSO.duplicate(theSet, ElementPlacement.PLACEATBEGINNING);
myDocument.activeLayer = theCircle;
theCircle.translate(theArray[0], theArray[1]);
theCircle.name = (m+1)+"_circle";
// make texts;
makeNumber (theSet, (m+1), theArray[0], theArray[1] - 12)
};
theSO.visible = false;
// reset image size;
myDocument.resizeImage(undefined, undefined, originalResolution, ResampleMethod.NONE);
preferences.rulerUnits = originalRulerUnits;
}
};
////////////////////////////////////
////////////////////////////////////
////////////////////////////////////
////// create number //////
function makeNumber (myDocument, theNumber, theX, theY) {
var textLayer = myDocument.artLayers.add();
textLayer.kind = LayerKind.TEXT;
textLayer.blendMode = BlendMode.NORMAL;
textLayer.opacity = 100;
var myTextRef = textLayer.textItem;
myTextRef.size = 24;
myTextRef.justification = Justification.CENTER;
myTextRef.font = "Courier";
var newColor = new SolidColor();
newColor.rgb.red = 0;
newColor.rgb.green = 0;
newColor.rgb.blue = 0;
myTextRef.color = newColor;
myTextRef.position = new Array(theX, theY);
myTextRef.contents = theNumber;
};
////// the fill-layer-function //////
function makeFillLayer (theName, theHue, theSat, theBright) {
// =======================================================
var idsetd = charIDToTypeID( "setd" );
var desc4 = new ActionDescriptor();
var idnull = charIDToTypeID( "null" );
var ref2 = new ActionReference();
var idClr = charIDToTypeID( "Clr " );
var idFrgC = charIDToTypeID( "FrgC" );
ref2.putProperty( idClr, idFrgC );
desc4.putReference( idnull, ref2 );
var idT = charIDToTypeID( "T " );
var desc5 = new ActionDescriptor();
var idH = charIDToTypeID( "H " );
var idAng = charIDToTypeID( "#Ang" );
desc5.putUnitDouble( idH, idAng, theHue );
var idStrt = charIDToTypeID( "Strt" );
desc5.putDouble( idStrt, theSat );
var idBrgh = charIDToTypeID( "Brgh" );
desc5.putDouble( idBrgh, theBright );
var idHSBC = charIDToTypeID( "HSBC" );
desc4.putObject( idT, idHSBC, desc5 );
executeAction( idsetd, desc4, DialogModes.NO );
// =======================================================
var id212 = charIDToTypeID( "Mk " );
var desc39 = new ActionDescriptor();
var id213 = charIDToTypeID( "null" );
var ref27 = new ActionReference();
var id214 = stringIDToTypeID( "contentLayer" );
ref27.putClass( id214 ); desc39.putReference( id213, ref27 );
var id215 = charIDToTypeID( "Usng" );
var desc40 = new ActionDescriptor();
var id216 = charIDToTypeID( "Type" );
var id217 = stringIDToTypeID( "solidColorLayer" );
desc40.putClass( id216, id217 );
var id218 = stringIDToTypeID( "contentLayer" );
desc39.putObject( id215, id218, desc40 );
executeAction( id212, desc39, DialogModes.NO );
app.activeDocument.activeLayer.name = theName;
return app.activeDocument.activeLayer
};
////// function to create path from array with one array per point that holds anchor, leftdirection, etc, 2010 //////
function createPath10 (theArray, thePathName) {
var originalRulerUnits = app.preferences.rulerUnits;
app.preferences.rulerUnits = Units.POINTS;
lineSubPathArray = new Array ();
if (theArray[theArray.length - 1].constructor != Array) {var numberOfPaths = theArray.length - 1}
else {var numberOfPaths = theArray.length};
for (var b = 0; b < numberOfPaths; b++) {
var lineArray = new Array ();
lineSubPathArray[b] = new SubPathInfo();
if (theArray[b][theArray[b].length - 1].constructor == Array) {
lineSubPathArray[b].closed = true;
var numberOfPoints = theArray[b].length
}
else {
lineSubPathArray[b].closed = theArray[b][theArray[b].length - 1]
var numberOfPoints = theArray[b].length - 1
};
for (c = 0; c < numberOfPoints; c++) {
lineArray[c] = new PathPointInfo;
switch (theArray[b][c][3]) {
case "CORNER":
lineArray[c].kind = PointKind.CORNERPOINT;
break;
case "SMOOTH":
lineArray[c].kind = PointKind.SMOOTHPOINT;
break;
default:
lineArray[c].kind = PointKind.CORNERPOINT;
break
};
lineArray[c].anchor = theArray[b][c][0];
if (theArray[b][c][1].length == 2) {lineArray[c].leftDirection = theArray[b][c][1]}
else {lineArray[c].leftDirection = theArray[b][c][0]};
if (theArray[b][c][2].length == 2) {lineArray[c].rightDirection = theArray[b][c][2]}
else {lineArray[c].rightDirection = theArray[b][c][0]};
};
lineSubPathArray[b].operation = ShapeOperation.SHAPEXOR;
lineSubPathArray[b].entireSubPath = lineArray;
};
var myPathItem = app.activeDocument.pathItems.add(thePathName, lineSubPathArray);
app.preferences.rulerUnits = originalRulerUnits;
return myPathItem
};
Copy link to clipboard
Copied
hi, i am also facing the same issue, i cant get the numbers included in the image. is there other ways to export image without scripting?