Photoshop CC eye dropper tool script - scripting

I have a batch action to place a pure white background behind an image. I want to be able to select the color from a fixed pixel position on each photo. When I record the eye dropper in actions it only records the color i picked, not the action of picking the color. I have looked into scripting and tried various solutions on the web.
This is the script I have tried:
var docRef = app.activeDocument;
var pixelLoc = [32,42];
var colorSamplerRef = docRef.colorSamplers.add(pixelLoc);
app.foregroundColor = colorSamplerRef.color;
It doesn't perform the action I need though. Which is select - > color range -> eye dropper tool on fixed position

To achieve this you can create a custom function which invokes the Color Range generated selection, (named selectColorRange in the example gist below).
The selectColorRange function utilizes new ActionDescripter() to configure the properties, which are akin to the settings options shown in the dialog box when you manually choose Select -> Color Range from the Menu bar. This function is invoked after adding the colorSampler at a given x/y coordinate as follows:
selectColorRange(sampledColor, 80); // <-- Specify the fuzziness as required.
Note how we pass in the previous sampledColor value, and a fuzziness value of 80, (which is the default value used in Photoshop).
Example gist:
var docRef = app.activeDocument; // Assumes a document is active.
// Remove any Color Samplers that may already exist.
docRef.colorSamplers.removeAll();
// deselct any selection that may already exist.
docRef.selection.deselect();
// Get color sample from a given x,y coordinate.
var pixelLoc = [32,42];
var colorSampleRef = docRef.colorSamplers.add(pixelLoc);
var sampledColor = colorSampleRef.color;
// Set the foreground color to the sampled color.
app.foregroundColor = sampledColor;
/**
* Invokes and configures `Select > Color Range` from menu bar.
* #param {Object} color - The sampled color object.
* #param {Number} [fuzziness=80] - The Fuziness value (between 0-200).
*/
function selectColorRange(color, fuzziness) {
fuzziness = (typeof fuzziness !== 'undefined') ? fuzziness : 80;
var d1 = new ActionDescriptor();
// Set the amount of Fuzziness.
d1.putInteger(charIDToTypeID('Fzns'), fuzziness);
// Set invert option to false.
d1.putBoolean(charIDToTypeID('Invr'), false);
d1.putInteger(stringIDToTypeID('colorModel'), 0);
// Set the lAB value for Minimum.
var d2 = new ActionDescriptor();
d2.putDouble(charIDToTypeID('Lmnc'), color.lab.l);
d2.putDouble(charIDToTypeID('A '), color.lab.a);
d2.putDouble(charIDToTypeID('B '), color.lab.b);
d1.putObject(charIDToTypeID('Mnm '), charIDToTypeID('LbCl'), d2);
// Set the lAB value for Maximum.
var d3 = new ActionDescriptor();
d3.putDouble(charIDToTypeID('Lmnc'), color.lab.l);
d3.putDouble(charIDToTypeID('A '), color.lab.a);
d3.putDouble(charIDToTypeID('B '), color.lab.b);
d1.putObject(charIDToTypeID('Mxm '), charIDToTypeID('LbCl'), d3);
// Run the Color Range command without showing dialog.
executeAction(charIDToTypeID('ClrR'), d1, DialogModes.NO);
}
// Invoke the function passing in the sample
// color and default fuzziness value.
selectColorRange(sampledColor, 80);
//docRef.selection.clear();
//docRef.selection.fill(app.foregroundColor);
// Remove the Color Sampler.
colorSampleRef.remove();
Additional notes:
Photoshop allows a maximum of four color samplers to be added. If the document already included four color samplers then we'd get an error when attempting to add another one. To avoid the potential of this happening we invoke docRef.colorSamplers.removeAll(); to remove them all first.
Also, to ensure the resultant selection (i.e. the selection created after invoking the selectColorRange function), is not affected by any existing selection(s) we deselect them all first by invoking docRef.selection.deselect();
Finally, the color sampler that we initially added is removed by calling colorSampleRef.remove();
I'm unsure from your question what you intend to to with the selection once it's been created. As an example;
Lets say you wanted to clear the contents of the selection then you'd invoke docRef.selection.clear();.
If you wanted to fill the resultant selection with the previously sampled color then call docRef.selection.fill(app.foregroundColor);

Related

Photoshop Scripting select contents of a layer & color

Using a javascript script in Photoshop 2022 (v 23.0.1), I am trying to change the color of a single item in one of my layers. I can access the layer, but I cannot change the color of it's contents.
var document = activeDocument;
var groupA = document.layers["Group"];
var layerA = groupA.layers["Layer In Group"];
var layerB = groupA.layers["Clipping Mask for layerA"];
The layerA contains a single item which is colored white. I'd like to change it's color.
I assume I need to select the contents of that layer, then apply a color to it. But I'm not sure this is the best way to do this.
I could also add a clipping mask for that layer, then fill that with color. Would this be easier/better?
Ideally I'd like to change it using a hex color code, but any way I can change it would be fine.
UPDATE: I was able to solve the problem by making the layer the activeLayer in the document.
// set the active layer to the layer requiring fill color
document.activeLayer = layerB;
// getBodyFillColor() is my method that returns the correct color
var color = getBodyFillColor();
// Once I set the active layer, it's automatically the selection layer?? (not sure how this works)
document.selection.fill(color);
You could just fill with a colour:
// Fill colour
var myRGBCol = [255, 0, 128]; //define your colour here
var col = new SolidColor;
col.rgb.red = myRGBCol[0];
col.rgb.green = myRGBCol[1];
col.rgb.blue = myRGBCol[2];
var blend = ColorBlendMode.NORMAL; // Normal
var op = 100; // opacity
document.selection.fill(col, blend, op, false);

Script measurement tool in Photoshop to measure distance between two points

Can the measurement tool be scripted to measure a custom distance? Not an existing measurement, that is.
I would have thought it possible, but Abobe's documentation are sketchy
and there's not much info when it comes down to scripting the measurement tool. Or ruler, as it use to be known. More specifically a lack of examples using the ruler in a script.
Ideally I'd like to:
Script a measurement from x1,y1 to x2,y2
Determine its length, (preferably from a variable, not from a text file - see below)
Clear the ruler tool (so no ruler line appears)
Delete any measurements (so there are no recordings in the ruler window)
That's basic trig, right? But if you can't set the initial ruler then this is all for nothing.
The only thing on the list I've done is the last. :(
I stumble at the first hurdle not being able to set the ruler, which I thought would be app.activeDocument.recordMeasurements(); Only it gets returned as undefined or Unable to record measurements for selection.
As minimal working, this is pretty minimal:
// Let's stick to pixels as the units to make things easier.
// Switch off any dialog boxes
displayDialogs = DialogModes.ERROR; // OFF
// Get and set the units to pixels
var currentUnits = app.preferences.rulerUnits;
app.preferences.rulerUnits = Units.PIXELS;
// delete existing measurements
app.measurementLog.deleteMeasurements(); // THIS WORKS!!
// call the source document
var srcDoc = app.activeDocument;
// Set array to record measurements
var rulerArr = [];
// Set ruler measurement
measure_it(x1,y1,x2,y2); // this a fictional function
// not even the ScriptListener records the ruler tool in a useful form
// var d = app.activeDocument.recordMeasurements(MeasurementSource.MEASURESELECTION, rulerArr); // Unable to record measurements for selection
// var d = app.activeDocument.recordMeasurements(MeasurementSource.MEASURESELECTION); // Unable to record measurements for selection
var d = app.activeDocument.recordMeasurements(); // undefined
var ruler = app.measurementLog; // Is an object!
alert(ruler.length); // undefined
// There's an option to export to a text file
// Is that the only way to get the measurements?
// Can't this be don't internally?
var f = "D:\\temp\\ruler.txt";
ruler.exportMeasurements(f, MeasurementRange.ACTIVEMEASUREMENTS)
alert(app.measurementLog);
// put the units back to how it was
app.preferences.rulerUnits = currentUnits;
// Set Display Dialogs back to normal
displayDialogs = DialogModes.ALL; // NORMAL

How to set custom colors for Odoo 12 calendar view events?

There is a good tutorial on how to achieve this in Odoo-8 here:
Tutorial , but it doesn't work on Odoo-12.
Odoo natively allows you to set a field of your model as a basis for color differentiation in calendar view.
<calendar ... color="your_model_field">
The problem is that he will decide automagically what color to assign to every value.
I need to be able to decide what color mapping to use.
Doing some diving in the web module js files, more specifically on
web/static/src/js/views/calendar/calendar_renderer.js on line 266
I found a promising function which appears to be the one responsible for deciding which color to set.
getColor: function (key) {
if (!key) {
return;
}
if (this.color_map[key]) {
return this.color_map[key];
}
// check if the key is a css color
if (typeof key === 'string' && key.match(/^((#[A-F0-9]{3})|(#[A-F0-9]{6})|((hsl|rgb)a?\(\s*(?:(\s*\d{1,3}%?\s*),?){3}(\s*,[0-9.]{1,4})?\))|)$/i)) {
return this.color_map[key] = key;
}
var index = (((_.keys(this.color_map).length + 1) * 5) % 24) + 1;
this.color_map[key] = index;
return index;
},
This function is fed the value of your field (for every calendar event) and returns the color to be used "supposedly" as background for the calendar event square.
According to the second if statement, if you manage to instantiate the CalendarRenderer class with a color_map object which has the possible values of your field as keys and color codes as values you should be ok.
According the the third if statement, if the values of your field are strings with color codes (#FFF, rgb(x, y, z) , etc) they will be set in the color_map object and returned to be used as background colors.
The last part I guess is how odoo decides on a color when no mapping is provided.
I tried both approaches with the same efect:
Image displaying the calendar view
Namely, all the calendar events are rendered with the default color taken from the fullcalendar.css stylesheet (line 529), but the color reference displays correctly on the sidebar to the right.
I would appreciate any light shed on this matter, It has to be possible to make this work!.
Thanks.

Adobe Photoshop Scripting - How to Select Bounding Box Around Current Selection?

Does anyone know whether it's possible, in Photoshop extend script, to convert an irregular selection (e.g. magic wand tool selection) into a rectangular selection encompassing the top, left, bottom and right bounds of the selection?
Here it is, I have documented the code so you can modify it later if you need. Also, check page 166 and following of Photoshop's JS reference manual, you may read more about selections - you can set feather, extend/intersect/etc. the selection if you need to.
Made for CS6, should work with latter.
#target photoshop
if (documents.length == 0) {
alert("nothing opened");
} else {
// start
//setup
var file = app.activeDocument;
var selec = file.selection;
//run
var bnds = selec.bounds; // get the bounds of current selection
var // save the particular pixel values
xLeft = bnds[0],
yTop = bnds[1],
xRight = bnds[2],
yBottom = bnds[3];
var newRect = [ [xLeft,yTop], [xLeft,yBottom], [xRight,yBottom], [xRight,yTop] ]; // set coords for selection, counter-clockwise
selec.deselect;
selec.select(newRect);
// end
}

constrain proportions while resizing images

I implemented drag and drop of images and now i want to constrain proportions of images while resizing.
/**
* Variable: constrainChildrenOnResize
*
* Specifies if children should be constrained according to the <constrainChildren>
* switch if cells are resized (including via <foldCells>). Default is false for
* backwards compatiblity.
*/
mxGraph.prototype.constrainChildrenOnResize = false;
i set this to true but its not working :s
What API/property i need for this functionality..
constrainChildrenOnResize is responsible for positioning and size of the children of resized cell. It means that children should keep their position relatively to the parent-cell.
In your case I would suggest to extend mxVertexHandler using union method. In this example you can see how to implement min-width/min-height restrictions. Using this example you are able to write your own rules for constrain.
Here is my simple solution:
var vertexHandlerUnion = mxVertexHandler.prototype.union;
mxVertexHandler.prototype.union = function (bounds) {
var result = vertexHandlerUnion.apply(this, arguments);
var coff = bounds.width / bounds.height
result.width = result.height * coff;
return result;
};
So this function is called every time you move mouse during dragging the resizer.
bounds - object, always same and represent old geometry of the cell (before resizing)
result - object, represents new values, which are going to be applied. Between this line ad return statement you can place any code you need to modify result.
In my simple example I just get the initial relation between width and height of the cell (coff) and then set new width by multiplying coff and new height. It will work if you drag corner or top/bottom. In real project this logic should be slightly extended, or you should make visible only corner handlers.
By the way, this code will work for all resizable cells on your graph. If you want to apply it only to images or some other kind of cells - you can put condition and check the cell type before recalculating. You can get current cell or its state via this.state.cell or this.state inside of union function.
For example only for vertecies:
... ...
var result = vertexHandlerUnion.apply(this, arguments);
if (this.state.cell.isVertex()) {
//calculations here
}
return result;