Copy link to clipboard
Copied
so i have a ton of images.
I have to apply a radial marquee and cut out the exterior excess.
Below is an example of what i have to do:
So i want to automate this, I will have images of all different shapes and sizes so i would want to be able to pick the size of the radial programatically.
Above you will see my colored diagram. i would always want my radial to start from the center but i would like to be able to choose the width (blue highlight) and height (red highlight) of the radial (green highlight). I would need something relative such as a percentage. it doesnt really matter at this point, i could work with pixels if need be.. as long as i am able to programmatically adjust the width and height.
Would anyone know how i can start doing this?
Copy link to clipboard
Copied
#target photoshop
var selWidth = 70, //percents
selHeight = 90, //percents
doc = new AM('document'),
res = doc.getProperty('resolution'),
docWidth = doc.getProperty('width') * res / 72,
docHeight = doc.getProperty('height') * res / 72;
doc.makeEllipseSelection(
(docHeight - docHeight * selHeight / 100) / 2,
(docWidth - docWidth * selWidth / 100) / 2,
docHeight - (docHeight - docHeight * selHeight / 100) / 2,
docWidth - (docWidth - docWidth * selWidth / 100) / 2,
true
)
function AM(target) {
var s2t = stringIDToTypeID,
t2s = typeIDToStringID;
target = target ? s2t(target) : null;
this.getProperty = function (property, id, idxMode) {
property = s2t(property);
(r = new ActionReference()).putProperty(s2t('property'), property);
id != undefined ? (idxMode ? r.putIndex(target, id) : r.putIdentifier(target, id)) :
r.putEnumerated(target, s2t('ordinal'), s2t('targetEnum'));
return getDescValue(executeActionGet(r), property)
}
this.hasProperty = function (property, id, idxMode) {
property = s2t(property);
(r = new ActionReference()).putProperty(s2t('property'), property);
id ? (idxMode ? r.putIndex(target, id) : r.putIdentifier(target, id))
: r.putEnumerated(target, s2t('ordinal'), s2t('targetEnum'));
try { return executeActionGet(r).hasKey(property) } catch (e) { return false }
}
this.descToObject = function (d) {
var o = {}
for (var i = 0; i < d.count; i++) {
var k = d.getKey(i)
o[t2s(k)] = getDescValue(d, k)
}
return o
}
this.makeEllipseSelection = function (top, left, bottom, right, AntA) {
(r = new ActionReference()).putProperty(s2t('channel'), s2t('selection'));
(d = new ActionDescriptor()).putReference(s2t('target'), r);
(d1 = new ActionDescriptor()).putUnitDouble(s2t('top'), s2t('pixelsUnit'), top);
d1.putUnitDouble(s2t('left'), s2t('pixelsUnit'), left);
d1.putUnitDouble(s2t('bottom'), s2t('pixelsUnit'), bottom);
d1.putUnitDouble(s2t('right'), s2t('pixelsUnit'), right);
d.putObject(s2t('to'), s2t('ellipse'), d1);
d.putBoolean(s2t('antiAlias'), AntA);
executeAction(s2t('set'), d, DialogModes.NO);
}
function getDescValue(d, k) {
switch (d.getType(k)) {
case DescValueType.OBJECTTYPE: return { type: t2s(d.getObjectType(k)), value: d.getObjectValue(k) };
case DescValueType.LISTTYPE: return d.getList(k);
case DescValueType.REFERENCETYPE: return d.getReference(k);
case DescValueType.BOOLEANTYPE: return d.getBoolean(k);
case DescValueType.STRINGTYPE: return d.getString(k);
case DescValueType.INTEGERTYPE: return d.getInteger(k);
case DescValueType.LARGEINTEGERTYPE: return d.getLargeInteger(k);
case DescValueType.DOUBLETYPE: return d.getDouble(k);
case DescValueType.ALIASTYPE: return d.getPath(k);
case DescValueType.CLASSTYPE: return d.getClass(k);
case DescValueType.UNITDOUBLE: return (d.getUnitDoubleValue(k));
case DescValueType.ENUMERATEDTYPE: return { type: t2s(d.getEnumerationType(k)), value: t2s(d.getEnumerationValue(k)) };
default: break;
};
}
}
Copy link to clipboard
Copied
@davidc88034496 - how did you go with the script from jazz-y?
Copy link to clipboard
Copied
So i still have to test it out. Im currently rushing through a ton of other things i have on my plate. Im going to give the script a try once i cross that road here on my end. I feel confident it will work though. I thought perhaps there would be an object oriented way of doing it rather than the ActionScript way but hey.. it is what it is.. hopefully ill get to it sometime this week. but im definitely going to need this script
Copy link to clipboard
Copied
@davidc88034496 wrote:
So i still have to test it out. Im currently rushing through a ton of other things i have on my plate. Im going to give the script a try once i cross that road here on my end. I feel confident it will work though.
Fair enough, we have a lot of "hit and run" posts, somebody asks for help, help is provided, then there is no reply.
@davidc88034496 wrote:
I thought perhaps there would be an object oriented way of doing it rather than the ActionScript way but hey.. it is what it is.. hopefully ill get to it sometime this week. but im definitely going to need this script
What exactly do you mean by "object oriented"? It can also be semi-automated using an action, rather than a script (in Photoshop, Actions and Scripts are two separate things, there is no ActionScript). The script from jazz-y was fully automated, this action approach is sem-automated. You have only provided a single image example, which was a tight/close crop which is easy to make into an eliptical shape from the canvas area. But what if the image is not nicely framed?
Here is an interactive action to create a vector layer mask. The mask is transformed during action playback to get the size and position correct. If you later change your mind, it can later be adjusted by transforming the path again, retaining the path object and vector mask properties for a "live" crop:
The script was recorded using arbitrary values that resulted in a 3.5:5 ratio, but this could be changed if you always wanted to start at a ratio of say 5:7 or 4:5 (8:10) etc.
Download link to action:
https://www.dropbox.com/s/71l6kqsjn2wocc5/Interactive%20Eliptical%20Vector%20Mask.atn?dl=0
Copy link to clipboard
Copied
@davidc88034496 wrote:So i want to automate this, I will have images of all different shapes and sizes so i would want to be able to pick the size of the radial programatically.
We have had scripting topics where a script leverages the facial recognition of the liquify command to automatically get an approximation of the face area, then an eliptical crop could be centred around that area etc...
Edit: Some links for later reference...
Copy link to clipboard
Copied
so what i mean by object oriented manner...
I was hoping there was an "object" already crafted by Adobe .. so for example.
var EclipseMarquee = New EclipseMarquee();
EclipseMarquee.Draw(x, y, width, height);
EclipseMarquee.MakeSelection();
EclipseMarquee.InvertSelection();
EclipseMarquee.Cut();
Where i can simply script the top and the job would be done. (The above is just a fake example) but i hope you get the idea.
I personally dont like the "ActionReference" code. I am not sure what its called exactly but if you look at Jazz-y code, he has that "function AM(target)" code with all that generated code. Im more use to Adobe XD where there is a ton of "objects" already created for you and you can do virtually anything by calling "objects" and methods that do the same thing you get with the GUI of Adobe XD.
but regardless, if it works it works so im grateful!
Using that liquify command seems like something i might need because yes, with all these images, they are of many different shapes and sizes. Usually they would have one subject. such as a model or person and we would want to create a gradient cut out around them.
Just please do bare with me though as i am still busy but i will have to start working on finding a solutiont to "radial cut-out" multiple pictures soon. So just give me a few days and ima come back to see what i can find. This is definitely something big and we would like to tackle it. Thanks so much!
Copy link to clipboard
Copied
@davidc88034496 wrote:
so what i mean by object oriented manner...
I was hoping there was an "object" already crafted by Adobe .. so for example.
var EclipseMarquee = New EclipseMarquee();
EclipseMarquee.Draw(x, y, width, height);
It is "easy enough" to create one using Action Manager code recorded by the Scripting Listener plug-in, wrapping it into a function with variables for the top/left/bottom/right values and then passing in parameters for these values when calling the function. The parameters are hard-coded, but simple prompts or a GUI could be created for live input, but that of course takes more work. Then you would add in other bits of code to perform the rest of the operation.
ellipticalSelectAll(0, 0, app.activeDocument.height.value, app.activeDocument.width.value, true);
function ellipticalSelectAll(top, left, bottom, right, antiAlias) {
var s2t = function (s) {
return app.stringIDToTypeID(s);
};
var descriptor = new ActionDescriptor();
var descriptor2 = new ActionDescriptor();
var reference = new ActionReference();
reference.putProperty( s2t( "channel" ), s2t( "selection" ));
descriptor.putReference( s2t( "null" ), reference );
descriptor2.putUnitDouble( s2t( "top" ), s2t( "pixelsUnit" ), top );
descriptor2.putUnitDouble( s2t( "left" ), s2t( "pixelsUnit" ), left );
descriptor2.putUnitDouble( s2t( "bottom" ), s2t( "pixelsUnit" ), bottom );
descriptor2.putUnitDouble( s2t( "right" ), s2t( "pixelsUnit" ), right );
descriptor.putObject( s2t( "to" ), s2t( "ellipse" ), descriptor2 );
descriptor.putBoolean( s2t( "antiAlias" ), antiAlias );
executeAction( s2t( "set" ), descriptor, DialogModes.NO );
}
https://gist.github.com/MarshySwamp/451f60096079084b818d693d8cf09547
You can combine such "helper scripts" as above into an action, where the script does what you can't do via an action but the action performs the bits that you can do. This is generally the best approach if you can't script or don't want/need to script.