Copy link to clipboard
Copied
Hi, I have just started trying to teach myself javascript. Based on preliminary research, it's become apparent that there are many functions in Photoshop that are either extremely cumbersome or impossible to code by hand without using the Script Listener.
My goal is as follows: first, I will manually load two photos as layers in a single document. Then I will manually place two or more color sampler points on the document. At this point I would like the script to create a curves adjustment layer (ideally clipped to layer 2) and place as individual channel anchor points the RGB data from the color sampler points on Layer 2, and then adjust the output of the points on each channel to the color sampler RGB values of layer 1.
As my first script, I realize this is probably going to be a lot of work.
I did find some code that returns the average value of manually placed color sampler points. Conceptually then, I would need to add code which creates a new curves adjustment layer and adds those RGB values (from a specific layer) as anchor points on the individual channels, and then hides one layer and looks at the RGB values of the color sampler points, and uses them as the output values for each anchor point.
Sounds simple enough from a conceptual standpoint.
I'm looking for some guidance on how to get started.
Which parts will I definitely need Scriptlistener for and will that be adequate to do the job?
How would you recommend I get started on this?
Thanks very much for any input.
Copy link to clipboard
Copied
it's become apparent that there are many functions in Photoshop that are either extremely cumbersome or impossible to code by hand without using the Script Listener.
Actually you may not need to use ScriptingListener.plugin yourself if you can find the code elsewhere but the
Document Object Model
will indeed not suffice for the task at hand (as far as I can tell) and you will have to use
Action Manager code.
DOM code may look neater and be more easy to read but it has drawbacks – that not all functions can be controlled thus being the probably most significant one.
I guess you need to record the creation of a Curves Layer with the appropriate number of points for the appropriate number of Channels and feed the numbers you collect from the ColorSamplers for the two Layers into that.
As you are vague about the actual number of ColorSamplers the task becomes more complicated and you may have to utilize a for-clause and a function for creating the points.
In my opinion this task is a problematic choice for a »first script«.
Copy link to clipboard
Copied
You should be able to get an average color from the colorSampler itself without any additional code as long as the area you want to average is one of the sizes in the sampler tool options. If the layers overlap you will need to hide/show the top layer to get the color from both layers as colorSampler reads the composite image.
Because you are doing most of the steps manually I don't think it would be too hard to script. I think an outline of the script would look something like this.
1. hide the top layer - DOM
2. read the color from the samplers and store the solidColor objects - DOM
3. show the top layer - DOM
4. read the colors again and store those - DOM
5. create a curve adjustment layer - Action Manager(scriptlistener)
6. move the adjustment layer to the top(if needed) and create clipping group - DOM
7. edit the adjustment layer using the stored color values - Action Manager
The hard part will be step 7. Especially if you want to have a flexible number of colorSampler/curve points. But with a little effort and maybe some help from this forum I think you can come up with a script that does what you want.
Copy link to clipboard
Copied
Thank you both for your thoughts. I see Action Manager = ScriptListener, which is good to know. I will be working almost always with two color sampler points, so based on what you've both indicated, that could simplify things. Is the Adobe Scripting Guide the best place to go to find the necessary commands to do steps 1-4, and 6?
In step 7, if I use the action Manager, how do I indicate I want to recall the stored color sampler values? I could be (and am probably) way off here, but I thought Action manager records scripting code based on what happens on the screen, so if the color sampler points are stored as variables in the script, it seems like I wouldn't be able to access them in the Photoshop interface to record with Action Manager. I.E. Action Manager would record the numerical value of the points that I move in the curves without tying them to the color sampler variables.
Conceptually it seems like it should be easy to write code that sets the color sampler points as variables, then calls the channels of the curves layer and sets the input and output numbers to the desired variables.
Thanks again for giving me some guidance.
Copy link to clipboard
Copied
I think that I was somewhat miss-leading. The scriptlistener plug-in outputs Action Manger code but that is not the same as it being equal. Yes, scirptlistener only records the settings used for that recorded acton. Sometimes you can use the code straight from the scriptlistener log but most of the time you will want to edit it so it uses variables instead of the hard coded settings.
I have been thinking about how this script would work. For one thing it would be limited to 4 points on the curve because of the ColorSampler limit of four samples. The ActionDescriptor for a curve expects the points to be in order so you would either need to place the colorSamplers in order i.e. the first sampler is for the black point of the curve or come up with a way to determine what sample is to be used for each curve point. Creating the curve descriptor will be the hardest part of writing a script to do this task.
As for the rest, yes, it is easy. I would do something like this...
// create a function fo hold most of the code
function createCurveAdjustmetFromColorSamplers(){
// first add some condition checks
// needs an open document in a color mode that supports layers
if(app.documents.length == 0 || ( app.activeDocument.mode == DocumentMode.BITMAP || app.activeDocument.mode == DocumentMode.INDEXEDCOLOR ) ){
alert('This script requires a document in Greyscale, RGB, CMYK, or Lab mode.');
return;
}
// check for at least two colorSamplers
if(app.activeDocument.colorSamplers.length < 2 ){
alert('This script requires at least two colorSamplers.');
return;
}
// last check for at least two layers - assume they will be on same level( not in layerSet )
if(app.activeDocument.layers.length < 2 ){
alert('This script requires at least two layers.');
return;
}
// create varaibles to hold the colorSampler's color property for each layer
// for the bottom layer
var outputArray = new Array();
// for top layer - array could also be created this way
var inputArray = [];
// store the number of samples because it will be needed in more than one place
var numberOfSamples = app.activeDocument.colorSamplers.length;
// hide the top layer
app.activeDocument.layers[0].visible = false;
// collect the samples from the bottom layer
for(var sampleIndex = 0; sampleIndex < numberOfSamples; sampleIndex++ ){
outputArray.push(app.activeDocument.colorSamplers[sampleIndex].color);
}
// turn the top layer back on
app.activeDocument.layers[0].visible = true;
// collect those samples
for(var sampleIndex = 0; sampleIndex < numberOfSamples; sampleIndex++ ){
inputArray.push(app.activeDocument.colorSamplers[sampleIndex].color);
}
// make sure the top layer is the activeLayer
app.activeDocument.activeLayer = app.activeDocument.layers[0];
// use Action Manager code to create new curve adjustment layer
makeCurveAdjustmentLayer();
}
function makeCurveAdjustmentLayer(){//works with any mode
var desc = new ActionDescriptor();
var ref = new ActionReference();
ref.putClass( charIDToTypeID( "AdjL" ) );
desc.putReference( charIDToTypeID( "null" ), ref );
var desc1 = new ActionDescriptor();
desc1.putClass( charIDToTypeID( "Type" ), charIDToTypeID("Crvs" ) );
desc.putObject( charIDToTypeID( "Usng" ), charIDToTypeID( "AdjL" ), desc1 );
executeAction( charIDToTypeID( "Mk " ), desc, DialogModes.NO );
}
// call the function to run the script
createCurveAdjustmetFromColorSamplers();
Copy link to clipboard
Copied
Thank you Michael! That's very helpful. I will look over the code and do some more research and come back when I have more specific questions.
Copy link to clipboard
Copied
The following function can be used to create RGB Curves Layers with varying numbers of points.
The Arrays for the source- and target values for the RGB-Channels are just listed in an Array themselves, so the first and second (red), third and fourth (green), fifth and sixth (blue) arrays should have identical numbers of elements.
And like I pointed out in the last post the source numbers in one Array should be different, I guess.
#target photoshop
var theArray = [[0, 128, 255], [0, 150, 255], [0, 128, 255], [0, 90, 255], [0, 75, 230, 255], [0, 30, 180, 255]];
rgbCurvesLayer (theArray);
////// make rgb curves layer //////
function rgbCurvesLayer (theArray) {
// =======================================================
var idMk = charIDToTypeID( "Mk " );
var desc5 = new ActionDescriptor();
var idnull = charIDToTypeID( "null" );
var ref2 = new ActionReference();
var idAdjL = charIDToTypeID( "AdjL" );
ref2.putClass( idAdjL );
desc5.putReference( idnull, ref2 );
var idUsng = charIDToTypeID( "Usng" );
var desc6 = new ActionDescriptor();
var idType = charIDToTypeID( "Type" );
var desc7 = new ActionDescriptor();
var idpresetKind = stringIDToTypeID( "presetKind" );
var idpresetKindType = stringIDToTypeID( "presetKindType" );
var idpresetKindDefault = stringIDToTypeID( "presetKindDefault" );
desc7.putEnumerated( idpresetKind, idpresetKindType, idpresetKindDefault );
var idCrvs = charIDToTypeID( "Crvs" );
desc6.putObject( idType, idCrvs, desc7 );
var idAdjL = charIDToTypeID( "AdjL" );
desc5.putObject( idUsng, idAdjL, desc6 );
executeAction( idMk, desc5, DialogModes.NO );
// =======================================================
var idsetd = charIDToTypeID( "setd" );
var desc8 = new ActionDescriptor();
var idnull = charIDToTypeID( "null" );
var ref3 = new ActionReference();
var idAdjL = charIDToTypeID( "AdjL" );
var idOrdn = charIDToTypeID( "Ordn" );
var idTrgt = charIDToTypeID( "Trgt" );
ref3.putEnumerated( idAdjL, idOrdn, idTrgt );
desc8.putReference( idnull, ref3 );
var idT = charIDToTypeID( "T " );
var desc9 = new ActionDescriptor();
var idpresetKind = stringIDToTypeID( "presetKind" );
var idpresetKindType = stringIDToTypeID( "presetKindType" );
var idpresetKindCustom = stringIDToTypeID( "presetKindCustom" );
desc9.putEnumerated( idpresetKind, idpresetKindType, idpresetKindCustom );
var idAdjs = charIDToTypeID( "Adjs" );
var list1 = new ActionList();
var desc10 = new ActionDescriptor();
var idChnl = charIDToTypeID( "Chnl" );
var ref4 = new ActionReference();
var idChnl = charIDToTypeID( "Chnl" );
var idChnl = charIDToTypeID( "Chnl" );
var idRd = charIDToTypeID( "Rd " );
ref4.putEnumerated( idChnl, idChnl, idRd );
desc10.putReference( idChnl, ref4 );
var idCrv = charIDToTypeID( "Crv " );
var list2 = new ActionList();
// add r points;
for (var m = 0; m < theArray[0].length; m++) {
addCurvePoint (list2, theArray[0]
, theArray[1] ) };
desc10.putList( idCrv, list2 );
var idCrvA = charIDToTypeID( "CrvA" );
list1.putObject( idCrvA, desc10 );
var desc15 = new ActionDescriptor();
var idChnl = charIDToTypeID( "Chnl" );
var ref5 = new ActionReference();
var idChnl = charIDToTypeID( "Chnl" );
var idChnl = charIDToTypeID( "Chnl" );
var idGrn = charIDToTypeID( "Grn " );
ref5.putEnumerated( idChnl, idChnl, idGrn );
desc15.putReference( idChnl, ref5 );
var idCrv = charIDToTypeID( "Crv " );
var list3 = new ActionList();
// add g points;
for (var m = 0; m < theArray[2].length; m++) {
addCurvePoint (list3, theArray[2]
, theArray[3] ) };
desc15.putList( idCrv, list3 );
var idCrvA = charIDToTypeID( "CrvA" );
list1.putObject( idCrvA, desc15 );
var desc20 = new ActionDescriptor();
var idChnl = charIDToTypeID( "Chnl" );
var ref6 = new ActionReference();
var idChnl = charIDToTypeID( "Chnl" );
var idChnl = charIDToTypeID( "Chnl" );
var idBl = charIDToTypeID( "Bl " );
ref6.putEnumerated( idChnl, idChnl, idBl );
desc20.putReference( idChnl, ref6 );
var idCrv = charIDToTypeID( "Crv " );
var list4 = new ActionList();
// add b points;
for (var m = 0; m < theArray[4].length; m++) {
addCurvePoint (list4, theArray[4]
, theArray[5] ) };
desc20.putList( idCrv, list4 );
var idCrvA = charIDToTypeID( "CrvA" );
list1.putObject( idCrvA, desc20 );
desc9.putList( idAdjs, list1 );
var idCrvs = charIDToTypeID( "Crvs" );
desc8.putObject( idT, idCrvs, desc9 );
executeAction( idsetd, desc8, DialogModes.NO );
//
return app.activeDocument.activeLayer;
////// add curve point //////
function addCurvePoint (theList, valueHor, valueVer) {
var desc11 = new ActionDescriptor();
var idHrzn = charIDToTypeID( "Hrzn" );
desc11.putDouble( idHrzn, valueHor );
var idVrtc = charIDToTypeID( "Vrtc" );
desc11.putDouble( idVrtc, valueVer );
var idPnt = charIDToTypeID( "Pnt " );
theList.putObject( idPnt, desc11 );
};
};
Copy link to clipboard
Copied
Another possible issue might be if two sampled points have identical source values but different target values.
Copy link to clipboard
Copied
Creating the curve descriptor will be the hardest part of writing a script to do this task.
I think getting the color values in order and checking if 0 or 255 have been picked or if they should be added to the ColorSamplers’ values and making sure no identical input values appear for any channel may be the tougher part.
Jbean25, could you post a pair of images (with the ColorSamplers) to show what a likely combination of actual images may be?
Copy link to clipboard
Copied
I think getting the color values in order and checking if 0 or 255 have been picked or if they should be added to the ColorSamplers’ values and making sure no identical input values appear for any channel may be the tougher part.
I guess I was thinking of creating an edit curve adjustment that could be used to create any curve adjustment layer in any color mode. A general function that could be used by any scripts.
But yes, all of the points you listed need to be addressed as part of creating the arguments to what ever function is used.
Copy link to clipboard
Copied
I guess I was thinking of creating an edit curve adjustment that could be used to create any curve adjustment layer in any color mode.
You are right (edit: a Curves Layer function for all elligible color modes seems demanding).
I just assumed RGB would be the natural choice – which of course it need not be.
Copy link to clipboard
Copied
Here are a couple photos. The color sampler points did not show up in the photos when inserted, so I've marked them on the top photo. The goal is ultimately to blend the sky of the darker photo in the brighter exposure. And the best way to do this is actually to use the color sampler points from both layers and take the average of them, and set the average as the output (not swap the values as I indicated in my initial post). I didn't think this extra step of figuring out the average would require much effort once I figured out how to do the heavy lifting, so please excuse me if that confused things. For the photos below, I would load the photos as layers. Then using the sampler point on the left, I would look at the RGB values of it and then hide that layer and look at the RGB sampler values of the same point on the photo below it. Then I would take the average of the R value for the top and bottom and use as the output for the curve layers I create, one for each photo. (the input is obtained by shift+clicking on the color sampler on each layer). I would repeat the process for the right most color sampler point, so that each curve now has two anchor points on each RGB channel.
That sounds long winded, but I hope it makes sense. And again, I apologize for any inconvenience.
Copy link to clipboard
Copied
The markings were unneccesary (and disruptive) as the Color Pickers were saved with the image.
Could you show what result you intend?
As the images seem to be RGB anyway, have you tried combining Michael’s code with the function I posted?
Copy link to clipboard
Copied
Hi c.pfaffenbichler,
I have had some computer issues the last few days and am just now able to work on this in earnest.
First, I tried to run the Michael's code in the script editor, but it returned an error. I believe this is because of the conditions set, which required layers to be active, etc. I'm nost sure then, what use the script editor will be in this particular case. Next I then ran it in CS5, and separately ran your code in CS5 as well.
Michael's code created a new curves layer, and if I understand it correctly, set the groundwork for me to be able to add in curves points using the color sampler variables he created.
Your code returned a curves layer with anchor points in the R,G,B channels, the input and output values are not entirely clear to me upon trying to parse the code. The B channel for some reason was assigned two anchor points with output values. The net effect of the curves adjustment was to make the photo much more red in appearance. I realize I need to learn a lot more code to really understand these scripts that have been writtenn
I'm reattaching the photos with a 3rd, which is the result of the adjustment. I have removed the painted circles around the color sampler points. The top most photo below is the adjusted photo, the second is the darker sky exposure and the lowest photo is a brighter exposure for the hills and river. The brightness of the sky in the top photo is kind of mid-way between the brighter and darker photos. The main thing is that it, and the background hills retains detail, which can be adjusted later in photoshop.
Copy link to clipboard
Copied
I should note that masks were created to reveal the adjustment selectively.
Also, thank you very much for your help and the time you have spent on this.
Copy link to clipboard
Copied
The function I had provided was an example into which you would need to feed the values you got with Mike’s code.
The code below would create a Curves Layer as shown in the screenshot, but I’m not sure it would work reasonably for all cases.
// with code by mike hale;
// 2012, use it at your own risk;
// call the function to run the script
#target photoshop
createCurveAdjustmetFromColorSamplers();
// create a function fo hold most of the code
function createCurveAdjustmetFromColorSamplers(){
// first add some condition checks
// needs an open document in a color mode that supports layers
if(app.documents.length == 0 || ( app.activeDocument.mode == DocumentMode.BITMAP || app.activeDocument.mode == DocumentMode.INDEXEDCOLOR ) ){
alert('This script requires a document in Greyscale, RGB, CMYK, or Lab mode.');
return;
}
// check for at least two colorSamplers
if(app.activeDocument.colorSamplers.length < 2 ){
alert('This script requires at least two colorSamplers.');
return;
}
// last check for at least two layers - assume they will be on same level( not in layerSet )
if(app.activeDocument.layers.length < 2 ){
alert('This script requires at least two layers.');
return;
}
// create varaibles to hold the colorSampler's color property for each layer
// for the bottom layer
var outputArray = new Array();
// for top layer - array could also be created this way
var inputArray = [];
// store the number of samples because it will be needed in more than one place
var numberOfSamples = app.activeDocument.colorSamplers.length;
// hide the top layer
app.activeDocument.layers[0].visible = false;
// collect the samples from the bottom layer
for(var sampleIndex = 0; sampleIndex < numberOfSamples; sampleIndex++ ){
outputArray.push(app.activeDocument.colorSamplers[sampleIndex].color);
}
// turn the top layer back on
app.activeDocument.layers[0].visible = true;
// collect those samples
for(var sampleIndex = 0; sampleIndex < numberOfSamples; sampleIndex++ ){
inputArray.push(app.activeDocument.colorSamplers[sampleIndex].color);
}
// make sure the top layer is the activeLayer
app.activeDocument.activeLayer = app.activeDocument.layers[0];
// create arrays of the color values:
var theArray = [[0, 0, 0, 0, 0, 0]];
for (var m = 0; m < inputArray.length; m++) {
theArray.push([inputArray
.rgb.red, outputArray .rgb.red, inputArray .rgb.green, outputArray .rgb.green, inputArray .rgb.blue, outputArray .rgb.blue]); };
theArray.push([255, 255, 255, 255, 255, 255]);
// sort;
theArray.sort(sortArrayByIndexedItem);
// makeCurveAdjustmentLayer();
rgbCurvesLayer (theArray)
};
////// make rgb curves layer //////
function rgbCurvesLayer (theArray) {
// =======================================================
var idMk = charIDToTypeID( "Mk " );
var desc5 = new ActionDescriptor();
var idnull = charIDToTypeID( "null" );
var ref2 = new ActionReference();
var idAdjL = charIDToTypeID( "AdjL" );
ref2.putClass( idAdjL );
desc5.putReference( idnull, ref2 );
var idUsng = charIDToTypeID( "Usng" );
var desc6 = new ActionDescriptor();
var idType = charIDToTypeID( "Type" );
var desc7 = new ActionDescriptor();
var idpresetKind = stringIDToTypeID( "presetKind" );
var idpresetKindType = stringIDToTypeID( "presetKindType" );
var idpresetKindDefault = stringIDToTypeID( "presetKindDefault" );
desc7.putEnumerated( idpresetKind, idpresetKindType, idpresetKindDefault );
var idCrvs = charIDToTypeID( "Crvs" );
desc6.putObject( idType, idCrvs, desc7 );
var idAdjL = charIDToTypeID( "AdjL" );
desc5.putObject( idUsng, idAdjL, desc6 );
executeAction( idMk, desc5, DialogModes.NO );
// =======================================================
var idsetd = charIDToTypeID( "setd" );
var desc8 = new ActionDescriptor();
var idnull = charIDToTypeID( "null" );
var ref3 = new ActionReference();
var idAdjL = charIDToTypeID( "AdjL" );
var idOrdn = charIDToTypeID( "Ordn" );
var idTrgt = charIDToTypeID( "Trgt" );
ref3.putEnumerated( idAdjL, idOrdn, idTrgt );
desc8.putReference( idnull, ref3 );
var idT = charIDToTypeID( "T " );
var desc9 = new ActionDescriptor();
var idpresetKind = stringIDToTypeID( "presetKind" );
var idpresetKindType = stringIDToTypeID( "presetKindType" );
var idpresetKindCustom = stringIDToTypeID( "presetKindCustom" );
desc9.putEnumerated( idpresetKind, idpresetKindType, idpresetKindCustom );
var idAdjs = charIDToTypeID( "Adjs" );
var list1 = new ActionList();
var desc10 = new ActionDescriptor();
var idChnl = charIDToTypeID( "Chnl" );
var ref4 = new ActionReference();
var idChnl = charIDToTypeID( "Chnl" );
var idChnl = charIDToTypeID( "Chnl" );
var idRd = charIDToTypeID( "Rd " );
ref4.putEnumerated( idChnl, idChnl, idRd );
desc10.putReference( idChnl, ref4 );
var idCrv = charIDToTypeID( "Crv " );
var list2 = new ActionList();
// add r points;
for (var m = 0; m < theArray.length; m++) {
addCurvePoint (list2, theArray
, 0) };
desc10.putList( idCrv, list2 );
var idCrvA = charIDToTypeID( "CrvA" );
list1.putObject( idCrvA, desc10 );
var desc15 = new ActionDescriptor();
var idChnl = charIDToTypeID( "Chnl" );
var ref5 = new ActionReference();
var idChnl = charIDToTypeID( "Chnl" );
var idChnl = charIDToTypeID( "Chnl" );
var idGrn = charIDToTypeID( "Grn " );
ref5.putEnumerated( idChnl, idChnl, idGrn );
desc15.putReference( idChnl, ref5 );
var idCrv = charIDToTypeID( "Crv " );
var list3 = new ActionList();
// add g points;
for (var m = 0; m < theArray.length; m++) {
addCurvePoint (list3, theArray
, 2) };
desc15.putList( idCrv, list3 );
var idCrvA = charIDToTypeID( "CrvA" );
list1.putObject( idCrvA, desc15 );
var desc20 = new ActionDescriptor();
var idChnl = charIDToTypeID( "Chnl" );
var ref6 = new ActionReference();
var idChnl = charIDToTypeID( "Chnl" );
var idChnl = charIDToTypeID( "Chnl" );
var idBl = charIDToTypeID( "Bl " );
ref6.putEnumerated( idChnl, idChnl, idBl );
desc20.putReference( idChnl, ref6 );
var idCrv = charIDToTypeID( "Crv " );
var list4 = new ActionList();
// add b points;
for (var m = 0; m < theArray.length; m++) {
addCurvePoint (list4, theArray
, 4) };
desc20.putList( idCrv, list4 );
var idCrvA = charIDToTypeID( "CrvA" );
list1.putObject( idCrvA, desc20 );
desc9.putList( idAdjs, list1 );
var idCrvs = charIDToTypeID( "Crvs" );
desc8.putObject( idT, idCrvs, desc9 );
executeAction( idsetd, desc8, DialogModes.NO );
//
return app.activeDocument.activeLayer;
////// add curve point //////
function addCurvePoint (theList, valueHor, theNumber) {
var desc11 = new ActionDescriptor();
var idHrzn = charIDToTypeID( "Hrzn" );
desc11.putDouble( idHrzn, valueHor[theNumber] );
var idVrtc = charIDToTypeID( "Vrtc" );
desc11.putDouble( idVrtc, valueHor[theNumber+1] );
var idPnt = charIDToTypeID( "Pnt " );
theList.putObject( idPnt, desc11 );
};
};
////// sort a double array, thanks to sam, http://www.rhinocerus.net/forum/lang-javascript/ //////
function sortArrayByIndexedItem(a,b) {
var theIndex = 0;
if (a[theIndex]<b[theIndex]) return -1;
if (a[theIndex]>b[theIndex]) return 1;
return 0;
};
Copy link to clipboard
Copied
Hi! I am currently trying to achieve pretty much the same as @Jbean25 in Photoshop CC. I need to adjust the curve so that the RGB numbers of ColorSampler1 match the numbers of ColorSampler2. I have two layers and only two ColorSamplers set manually. But when I try to run the script from above created by @c.pfaffenbichler I get error messages like:
Error 8800: General Photoshop error occurred. This functionality may not be available in this version of Photoshop.
I tried it on an older PC with CS6 and got the same result, so it doesn`t seem to be about the software version.
What am I doing wrong? I`ll attach a small .psd file of what I am trying to achieve.
Thank you!
Copy link to clipboard
Copied
That’s not what the Script is intended to do; the Script is intended to adjust the Curves Layer based on the Colorpicker values at the same position on two Layers, not adjust the values of one Colorpicker according to another Colorpicker.
Copy link to clipboard
Copied
One problem can be when one of the Channels has white or black pixels at the Colorpicker position.
That could result in multiple points being set for the curves at identical positions which does not work out.
Filtering out such conflicting data seems possible but it seems doubtful whether it’s worth the trouble.
Edit: Thinking about it I guess any multiples in any Channel would cause problems.