Copy link to clipboard
Copied
I thought I had mastered this but it turns out I haven't.
The ScriptListner does not appear to record the point plotted in a curves adjustment layer.
Any help appreciated
Ian
Hey ian-barber​, you're right. I missed the fact that different document modes require a different charID. Here's the updated function which will work on any document mode. I'm pretty sure I covered all of them, including all possible monotone / duotone / tritone / quadtone options.
...// Examples
var point1 = [28, 0];
var point2 = [37, 90];
var point3 = [163, 155];
var point4 = [253, 190];
// Add points to array
var points = [point1, point2, point3, point4];
// Execute
modifySelectedCur
Copy link to clipboard
Copied
ian-barber​, it did record the curve changes in the ScriptingListener for me.
I made a function to modify an active (selected) curves adjustment layer. It needs a minimum of 2 input points, and it can have as many points as you want. Each point is an array with an x and y coordinate.
// Examples
var point1 = [28, 0];
var point2 = [37, 90];
var point3 = [163, 155];
var point4 = [253, 190];
// Add points to array
var points = [point1, point2, point3, point4];
// Execute
modifySelectedCurvesLayer(points);
/*
* @param {Array} points
* --> forEach : [x, y]
*/
function modifySelectedCurvesLayer(points) {
if(points.length < 2) {
alert('Curves need a minimum of 2 points');
return false;
}
var desc = new ActionDescriptor();
var ref = new ActionReference();
ref.putEnumerated( charIDToTypeID( "AdjL" ), charIDToTypeID( "Ordn" ), charIDToTypeID( "Trgt" ) );
desc.putReference( charIDToTypeID( "null" ), ref );
var curvesLayerDesc = new ActionDescriptor();
curvesLayerDesc.putEnumerated( stringIDToTypeID( "presetKind" ), stringIDToTypeID( "presetKindType" ), stringIDToTypeID( "presetKindCustom" ) );
var chnlList = new ActionList();
var chnlDesc = new ActionDescriptor();
var channelRef = new ActionReference();
channelRef.putEnumerated( charIDToTypeID( "Chnl" ), charIDToTypeID( "Chnl" ), charIDToTypeID( "Cmps" ) );
chnlDesc.putReference( charIDToTypeID( "Chnl" ), channelRef );
var pointsList = new ActionList();
for(var i = 0; i < points.length; i++) {
var pointDesc = new ActionDescriptor();
pointDesc.putDouble( charIDToTypeID( "Hrzn" ), points[0] );
pointDesc.putDouble( charIDToTypeID( "Vrtc" ), points[1] );
pointsList.putObject( charIDToTypeID( "Pnt " ), pointDesc );
}
chnlDesc.putList( charIDToTypeID( "Crv " ), pointsList );
chnlList.putObject( charIDToTypeID( "CrvA" ), chnlDesc );
curvesLayerDesc.putList( charIDToTypeID( "Adjs" ), chnlList );
desc.putObject( charIDToTypeID( "T " ), charIDToTypeID( "Crvs" ), curvesLayerDesc );
executeAction( charIDToTypeID( "setd" ), desc, DialogModes.NO );
}
Hope it helps!
Copy link to clipboard
Copied
JavierAroche​, many thanks for the reply and the code. I will now study this to see if i can work it out.
Copy link to clipboard
Copied
The above code appears to work fine if the open document is in RGB but does not work if the open document is in grayscale mode.
Can anyone throw any light on as to why that would be ?
ian
Copy link to clipboard
Copied
Hey ian-barber​, you're right. I missed the fact that different document modes require a different charID. Here's the updated function which will work on any document mode. I'm pretty sure I covered all of them, including all possible monotone / duotone / tritone / quadtone options.
// Examples
var point1 = [28, 0];
var point2 = [37, 90];
var point3 = [163, 155];
var point4 = [253, 190];
// Add points to array
var points = [point1, point2, point3, point4];
// Execute
modifySelectedCurvesLayer(points);
/*
* @param {Array} points
* --> forEach : [x, y]
*/
function modifySelectedCurvesLayer(points) {
// Validate input
if(points.length < 2) {
alert('Curves need a minimum of 2 points');
return false;
}
// Analyze document mode
switch(app.activeDocument.mode.toString()) {
case "DocumentMode.RGB":
case "DocumentMode.CMYK":
var docModeCharID = "Cmps";
break;
case "DocumentMode.GRAYSCALE":
var docModeCharID = "Blck";
break;
case "DocumentMode.DUOTONE":
var channelName = app.activeDocument.channels[0].name;
if( channelName == "Monotone" ) {
var docModeCharID = "Mntn";
} else if( channelName == "Duotone" ) {
var docModeCharID = "Dtn ";
} else if( channelName == "Tritone" ) {
var docModeCharID = "Trtn";
} else if( channelName == "Quadtone" ) {
var docModeCharID = "Qdtn";
}
break;
case "DocumentMode.LAB":
var docModeCharID = "Lght";
break;
default:
break;
}
var desc = new ActionDescriptor();
var ref = new ActionReference();
ref.putEnumerated( charIDToTypeID( "AdjL" ), charIDToTypeID( "Ordn" ), charIDToTypeID( "Trgt" ) );
desc.putReference( charIDToTypeID( "null" ), ref );
var curvesLayerDesc = new ActionDescriptor();
curvesLayerDesc.putEnumerated( stringIDToTypeID( "presetKind" ), stringIDToTypeID( "presetKindType" ), stringIDToTypeID( "presetKindCustom" ) );
var chnlList = new ActionList();
var chnlDesc = new ActionDescriptor();
var channelRef = new ActionReference();
channelRef.putEnumerated( charIDToTypeID( "Chnl" ), charIDToTypeID( "Chnl" ), charIDToTypeID( docModeCharID ) );
chnlDesc.putReference( charIDToTypeID( "Chnl" ), channelRef );
var pointsList = new ActionList();
for(var i = 0; i < points.length; i++) {
var pointDesc = new ActionDescriptor();
pointDesc.putDouble( charIDToTypeID( "Hrzn" ), points[0] );
pointDesc.putDouble( charIDToTypeID( "Vrtc" ), points[1] );
pointsList.putObject( charIDToTypeID( "Pnt " ), pointDesc );
}
chnlDesc.putList( charIDToTypeID( "Crv " ), pointsList );
chnlList.putObject( charIDToTypeID( "CrvA" ), chnlDesc );
curvesLayerDesc.putList( charIDToTypeID( "Adjs" ), chnlList );
desc.putObject( charIDToTypeID( "T " ), charIDToTypeID( "Crvs" ), curvesLayerDesc );
executeAction( charIDToTypeID( "setd" ), desc, DialogModes.NO );
}
Copy link to clipboard
Copied
Hi Javier
It returns an error because it is entering an array and not a single number.
I have changed the code and it works now.
for(var i = 0; i < points.length; i++) {
var pointDesc = new ActionDescriptor();
pointDesc.putDouble( charIDToTypeID( "Hrzn" ), points[i][0] );
pointDesc.putDouble( charIDToTypeID( "Vrtc" ), points[i][1] );
pointsList.putObject( charIDToTypeID( "Pnt " ), pointDesc );
}
Copy link to clipboard
Copied
Thank you for your contribution, it was of great help.
I needed to add points to all RGB channels, so I added this possibility.
Since I am not familiar with the other modes, I leave the addition of the channels of these modes to more qualified people.
My example:
var point0 = [0, 0];
var point1 = [63, 63];
var point2 = [128, 128];
var point3 = [191, 191];
var point4 = [255, 255];
// Add points to arrays
var RGBPoints = [point0, point1, point2, point3, point4];
var RedPoints = [point0, point1, point2, point3, point4];
var GreenPoints = [point0, point1, point2, point3, point4];
var BluePoints = [point0, point1, point2, point3, point4];
var channelId;
// Execute
function valid(){
// Validate input
if(points.length < 2) {
alert('Curves need a minimum of 2 points');
return false;
}
// Analyze document mode
switch(app.activeDocument.mode.toString()) {
case "DocumentMode.RGB":{
for(j=0;j<=3;j++){
if(j==0){channelId = charIDToTypeID( "Cmps" );
modifySelectedCurvesLayer(RGBPoints);
}
if(j==1){channelId = charIDToTypeID( "Rd " );
modifySelectedCurvesLayer(RedPoints);
}
if(j==2){channelId = charIDToTypeID( "Grn " );
modifySelectedCurvesLayer(GreenPoints);
}
if(j==3){channelId = charIDToTypeID( "Bl " );
modifySelectedCurvesLayer(BluePoints);
}
}
};
case "DocumentMode.CMYK":
var docModeCharID = "Cmps";
break;
case "DocumentMode.GRAYSCALE":
var docModeCharID = "Blck";
break;
case "DocumentMode.DUOTONE":
var channelName = app.activeDocument.channels[0].name;
if( channelName == "Monotone" ) {
var docModeCharID = "Mntn";
} else if( channelName == "Duotone" ) {
var docModeCharID = "Dtn ";
} else if( channelName == "Tritone" ) {
var docModeCharID = "Trtn";
} else if( channelName == "Quadtone" ) {
var docModeCharID = "Qdtn";
}
break;
case "DocumentMode.LAB":
var docModeCharID = "Lght";
break;
default:
break;
}
};
function modifySelectedCurvesLayer(points) {
var desc = new ActionDescriptor();
var ref = new ActionReference();
ref.putEnumerated( charIDToTypeID( "AdjL" ), charIDToTypeID( "Ordn" ), charIDToTypeID( "Trgt" ) );
desc.putReference( charIDToTypeID( "null" ), ref );
var curvesLayerDesc = new ActionDescriptor();
curvesLayerDesc.putEnumerated( stringIDToTypeID( "presetKind" ), stringIDToTypeID( "presetKindType" ), stringIDToTypeID( "presetKindCustom" ) );
var chnlList = new ActionList();
var chnlDesc = new ActionDescriptor();
var channelRef = new ActionReference();
channelRef.putEnumerated( charIDToTypeID( "Chnl" ), charIDToTypeID( "Chnl" ), channelId );
chnlDesc.putReference( charIDToTypeID( "Chnl" ), channelRef );
var pointsList = new ActionList();
for(var i = 0; i < points.length; i++) {
var pointDesc = new ActionDescriptor();
pointDesc.putDouble( charIDToTypeID( "Hrzn" ), points[i][0] );
pointDesc.putDouble( charIDToTypeID( "Vrtc" ), points[i][1] );
pointsList.putObject( charIDToTypeID( "Pnt " ), pointDesc );
}
chnlDesc.putList( charIDToTypeID( "Crv " ), pointsList );
chnlList.putObject( charIDToTypeID( "CrvA" ), chnlDesc );
curvesLayerDesc.putList( charIDToTypeID( "Adjs" ), chnlList );
desc.putObject( charIDToTypeID( "T " ), charIDToTypeID( "Crvs" ), curvesLayerDesc );
executeAction( charIDToTypeID( "setd" ), desc, DialogModes.NO );
}
Copy link to clipboard
Copied
I'm trying to implement this code but gettin an illegal argument error on the second to last line:
desc.putObject( charIDToTypeID( "T " ), charIDToTypeID( "Crvs" ), curvesLayerDesc );
Very new to scripting for photoshop and using the action editor so any insight would be helpful. Thx.
Copy link to clipboard
Copied
it appears "T " argument needs 3 spaces in order to work. Very strange but this is the kind of small detail I expect to overlook when I'm exploring a new library
Copy link to clipboard
Copied
It is mentioned in various Adobe files, such as the Photoshop JavaScript Reference PDF:
However, I agree that one does have to look hard for such info!
Also: