Copy link to clipboard
Copied
Let's say I've got 1000 discreet squares in my .psd file. Would it be possible to fill them all with random colors? Preferably with no duplicates?
The actual final file will have probably somewhere between ~2000 and ~5000 shapes (not all of them regular), which should all filled with a flat, distinct RGB color. It could be done by hand... but I'd much prefer to automate this task, if possible.
Thanks in advance for reading and assistance!
Copy link to clipboard
Copied
what are squares? this selection, mask, pixels in one layer, pixels in different layers, closed paths in one layer, vector shapes in different layers, etc.
it would be ideal if you could upload a test file that would make your task clear
P.s. set random color to all selected layers using fill FX
Copy link to clipboard
Copied
Thanks for your answer, this is about the gist of it. Specifically, I should have said multiple, seperate active selections (as in several disconnected selected areas on the same layer).
Copy link to clipboard
Copied
So how is this selection made? Can you post an example? From what you describe, it might be possible to create a alpha mask of the selection, then go through that and detect each separate selection, and apply a random color, but that would still take a long time, even with a script.
Copy link to clipboard
Copied
As I understand it, the selection is created on the basis of a pixel layer (that is, it is a set of some objects separated by transparency or color).
Copy link to clipboard
Copied
Shape layer are fill layers with vector layer mask. To have 5000 different solid color discreet shapes you would be dealing withe 5000 layers. A pattern could have 5000 colors so you could flatten your 5000 shape layer define a define the is the merge if 5000 colored shapes. however if there was overlap between layers some shapes will be altered, wiped, out or even blender into more than 5000 colors and shapes.
An active selection can have 5000 separate areas but it can not bet filled with 5000 colors. 5000 different selection can be filled with 5000 colors like as swatch color panel.
Copy link to clipboard
Copied
There is one problem with shape layers - they need to be selected before changing the color (at least I couldn't do it any other way).I made a test document with 3200 layers. This code changes the color of the selected layers at a rate of about 3 layers per second. It's very slow 😞
#target photoshop
var s2t = stringIDToTypeID;
doProgress("", "main()")
function main() {
(r = new ActionReference()).putProperty(s2t('property'), p = s2t('targetLayersIDs'));
r.putEnumerated(s2t('document'), s2t('ordinal'), s2t('targetEnum'));
var lrs = executeActionGet(r).getList(p);
for (var i = 0; i < lrs.count; i++) {
app.updateProgress(i + 1, lrs.count);
app.changeProgressText(i);
(r = new ActionReference()).putIdentifier(s2t('layer'), lrs.getReference(i).getIdentifier(s2t('layerID')));
(d = new ActionDescriptor()).putReference(s2t('null'), r);
executeAction(s2t('select'), d, DialogModes.NO);
(r = new ActionReference()).putEnumerated(s2t("contentLayer"), s2t("ordinal"), s2t("targetEnum"));
(d = new ActionDescriptor()).putReference(s2t("null"), r);
(d1 = new ActionDescriptor()).putDouble(s2t('red'), Math.random() * 255);
d1.putDouble(s2t('grain'), Math.random() * 255);
d1.putDouble(s2t('blue'), Math.random() * 255);
(d2 = new ActionDescriptor()).putObject(s2t("color"), s2t("RGBColor"), d1);
(d3 = new ActionDescriptor()).putObject(s2t("fillContents"), s2t("solidColorLayer"), d2);
d.putObject(s2t("to"), s2t("shapeStyle"), d3);
executeAction(s2t("set"), d, DialogModes.NO);
}
}
Copy link to clipboard
Copied
Yea, that many layers is going to really slow down PS. I do a lot of scripting creating gradients to layers and creating new layers. I end up doing it in pieces now and flattening a portion of it, just so I'm not sitting there all day.
Copy link to clipboard
Copied
Thanks for clearing things up, and yes I was referring to active selection--which is a shame, but understable. Thank you!
Copy link to clipboard
Copied
Try it. The fill is based on a selection. I added control over the repeatability of colors (they may be close, but not the same). It took about 25 minutes to fill 4000 selected objects
#target photoshop
activeDocument.suspendHistory('fill selection', 'main()')
function main() {
var doc = new AM('document'),
lr = new AM('layer'),
pth = new AM('path'),
channel = new AM('channel'),
presentColors = {};
doProgress("", "fillSelection()")
function fillSelection() {
if (doc.hasProperty('selection')) {
lr.makeChannelFromSelection('selection')
lr.makePathFromSelection(1);
lr.select(lr.newLayer('colors'))
var pathContents = pth.getProperty('pathContents').value.getList(stringIDToTypeID('pathComponents'))
try {
channel.delete('current fill')
channel.makeSelection('selection')
} catch (e) { }
for (var i = 0; i < pathContents.count; i++) {
updateProgress(i + 1, pathContents.count);
changeProgressText(i);
pth.makePathFromSubpath(pathContents.getObjectValue(i))
pth.makeSelectionFromPath()
lr.expandSelection(1)
lr.makeChannelFromSelection('current fill')
channel.select('current fill')
doc.deselect()
channel.invert()
channel.makeSelection('selection')
channel.subtractFromSelection('current fill')
channel.delete('current fill')
lr.fillByRandomColor(presentColors)
}
lr.deselect()
channel.delete('selection')
pth.delete()
}
}
}
function AM(target, order) {
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'), order ? s2t(order) : 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'), order ? s2t(order) : s2t('targetEnum'));
return executeActionGet(r).hasKey(property)
}
this.select = function (id) {
var r = new ActionReference();
if (typeof id == 'number') r.putIdentifier(target, id) else r.putName(target, id);
(d = new ActionDescriptor()).putReference(s2t('null'), r);
executeAction(s2t('select'), d, DialogModes.NO);
}
this.makeSelectionFromPath = function () {
(r = new ActionReference()).putProperty(s2t('channel'), s2t('selection'));
(d = new ActionDescriptor()).putReference(s2t('null'), r);
(r1 = new ActionReference()).putProperty(s2t('path'), s2t('workPath'));
d.putReference(s2t('to'), r1);
d.putBoolean(s2t('vectorMaskParams'), true);
executeAction(s2t('set'), d, DialogModes.NO);
}
this.deleteCurrentPath = function () {
(r = new ActionReference()).putProperty(s2t('path'), s2t('workPath'));
(d = new ActionDescriptor()).putReference(s2t('null'), r);
executeAction(s2t('delete'), d, DialogModes.NO);
}
this.makePathFromSelection = function (tolerance) {
tolerance = tolerance ? tolerance : 10;
(r = new ActionReference()).putClass(s2t('path'));
(d = new ActionDescriptor()).putReference(s2t('null'), r);
(r1 = new ActionReference()).putProperty(s2t('selectionClass'), s2t('selection'));
d.putReference(s2t('from'), r1);
d.putUnitDouble(s2t('tolerance'), s2t('pixelsUnit'), tolerance);
executeAction(s2t('make'), d, DialogModes.NO);
}
this.makePathFromSubpath = function (pth) {
(r = new ActionReference()).putProperty(stringIDToTypeID("path"), stringIDToTypeID("workPath"));
(d = new ActionDescriptor()).putReference(stringIDToTypeID("null"), r);
(l = new ActionList()).putObject(stringIDToTypeID("pathComponent"), pth);
d.putList(stringIDToTypeID("to"), l);
executeAction(stringIDToTypeID("set"), d, DialogModes.NO);
}
this.newLayer = function (name) {
(d1 = new ActionDescriptor()).putString(s2t('name'), name);
(d = new ActionDescriptor()).putObject(s2t('new'), s2t('layer'), d1);
return (executeAction(s2t('make'), d, DialogModes.NO)).getInteger(s2t('layerID'))
}
this.makeChannelFromSelection = function (name) {
(d = new ActionDescriptor()).putString(s2t("name"), name);
d.putEnumerated(s2t("colorIndicates"), s2t("maskIndicator"), s2t("selectedAreas"));
(d1 = new ActionDescriptor()).putObject(s2t("new"), s2t("channel"), d);
(r = new ActionReference()).putProperty(s2t("channel"), s2t("selection"));
d1.putReference(s2t("using"), r);
executeAction(s2t("make"), d1, DialogModes.NO);
}
this.deselect = function () {
(r = new ActionReference()).putProperty(s2t('channel'), s2t('selection'));
(d = new ActionDescriptor()).putReference(s2t('null'), r);
d.putEnumerated(s2t('to'), s2t('ordinal'), s2t('none'));
executeAction(s2t('set'), d, DialogModes.NO);
}
this.invert = function () {
executeAction(s2t("invert"), undefined, DialogModes.NO);
}
this.makeSelection = function (name) {
(r = new ActionReference()).putProperty(target, s2t('selection'));
(d = new ActionDescriptor()).putReference(s2t('null'), r);
(r1 = new ActionReference()).putName(target, name);
d.putReference(s2t('to'), r1);
executeAction(s2t('set'), d, DialogModes.NO);
}
this.subtractFromSelection = function (name) {
(r = new ActionReference()).putName(target, name);
(d = new ActionDescriptor()).putReference(s2t('null'), r);
(r1 = new ActionReference()).putProperty(target, s2t('selection'));
d.putReference(s2t('from'), r1);
executeAction(s2t('subtract'), d, DialogModes.NO);
}
this.expandSelection = function (px) {
(d = new ActionDescriptor()).putUnitDouble(s2t('by'), s2t('pixelsUnit'), px);
executeAction(s2t('expand'), d, DialogModes.NO);
}
this.delete = function (name) {
var r = new ActionReference();
if (name) r.putName(target, name) else r.putEnumerated(target, s2t('ordinal'), s2t('targetEnum'));
(d = new ActionDescriptor()).putReference(s2t('null'), r);
executeAction(s2t('delete'), d, DialogModes.NO);
}
this.fillByRandomColor = function (colorObj) {
var c = new SolidColor;
with (c.rgb) {
do {
red = Math.random() * 255
green = Math.random() * 255
blue = Math.random() * 255
} while (colorObj[hexValue])
colorObj[hexValue] = true;
(d = new ActionDescriptor()).putEnumerated(s2t("using"), s2t("fillContents"), s2t("color"));
(d1 = new ActionDescriptor()).putDouble(s2t("red"), red);
d1.putDouble(s2t("green"), green);
d1.putDouble(s2t("blue"), blue);
d.putObject(s2t("color"), s2t("RGBColor"), d1);
executeAction(s2t("fill"), d, DialogModes.NO);
}
}
function getDescValue(d, p) {
switch (d.getType(p)) {
case DescValueType.OBJECTTYPE: return { type: t2s(d.getObjectType(p)), value: d.getObjectValue(p) };
case DescValueType.LISTTYPE: return d.getList(p);
case DescValueType.REFERENCETYPE: return d.getReference(p);
case DescValueType.BOOLEANTYPE: return d.getBoolean(p);
case DescValueType.STRINGTYPE: return d.getString(p);
case DescValueType.INTEGERTYPE: return d.getInteger(p);
case DescValueType.LARGEINTEGERTYPE: return d.getLargeInteger(p);
case DescValueType.DOUBLETYPE: return d.getDouble(p);
case DescValueType.ALIASTYPE: return d.getPath(p);
case DescValueType.CLASSTYPE: return d.getClass(p);
case DescValueType.UNITDOUBLE: return (d.getUnitDoubleValue(p));
case DescValueType.ENUMERATEDTYPE: return { type: t2s(d.getEnumerationType(p)), value: t2s(d.getEnumerationValue(p)) };
default: break;
};
}
}