Copy link to clipboard
Copied
Hi everyone,
I would like to request some help with the following; I want to create a batch of text images where every single letter has a different color like in the image attached. I know how to use variables to generate multiple text designs, and I know how to manually change text color, but I was wondering if there is any way I can automatically make sure every subsequent letter (in every text image) gets a different color?
Many thanks!
For text layers try this script:
#target photoshop
var s2t = stringIDToTypeID;
(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++) {
(r = new ActionReference()).putProperty(s2t('property'), p = s2t('textKey'));
r.putIdentifier(s2t('layer'), lrs.getReference(i).getIdentifier(s2t('layerID')));
if (exec
...
If you mean first script, put on top of it:
arr = [], clrs = ['004fab', '00cfb3', 'ff7000', '14a41c', 'ffd802',
'f64397', '4be715', 'ffbbb1', '8243d0', 'ff0834', 'ffd802'];
Then replace:
with(c.hsb) {
saturation = 100, brightness = 95; do{hue = Math.random() * 360}
while(Math.abs(hueDifference - hue) < 60); hueDifference = hue
}
to:
!arr.length &&
arr = [].slice.call(clrs)
c.rgb.hexValue = arr.shift()
Copy link to clipboard
Copied
For text layers try this script:
#target photoshop
var s2t = stringIDToTypeID;
(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++) {
(r = new ActionReference()).putProperty(s2t('property'), p = s2t('textKey'));
r.putIdentifier(s2t('layer'), lrs.getReference(i).getIdentifier(s2t('layerID')));
if (executeActionGet(r).hasKey(p)) {
var textKey = executeActionGet(r).getObjectValue(p),
style = textKey.getList(s2t('textStyleRange')).getObjectValue(0),
text = textKey.getString(p),
l = new ActionList(),
hueDifference = 0;
for (var x = 0; x < text.length; x++) {
var k = copyDesc(style, new ActionDescriptor()),
s = k.getObjectValue(s2t('textStyle'));
k.putInteger(s2t('from'), x)
k.putInteger(s2t('to'), x + 1)
var c = new SolidColor;
with (c.hsb) {
saturation = 100
brightness = 95
do { hue = Math.random() * 360 } while (Math.abs(hueDifference - hue) < 60)
hueDifference = hue
}
var d = new ActionDescriptor();
d.putDouble(s2t('red'), c.rgb.red)
d.putDouble(s2t('grain'), c.rgb.green)
d.putDouble(s2t('blue'), c.rgb.blue)
s.putObject(s2t('color'), s2t('RGBColor'), d)
k.putObject(s2t('textStyle'), s2t('textStyle'), s)
l.putObject(s2t('textStyleRange'), k)
}
if (l.count) {
textKey.putList(s2t('textStyleRange'), l)
var d = new ActionDescriptor();
(r = new ActionReference()).putIdentifier(s2t('layer'), lrs.getReference(i).getIdentifier(s2t('layerID')));
d.putReference(s2t('null'), r);
d.putObject(s2t('to'), s2t('textLayer'), textKey);
executeAction(s2t('set'), d, DialogModes.NO);
}
}
}
function copyDesc(from, to) {
for (var i = 0; i < from.count; i++) {
var k = from.getKey(i);
if (to.hasKey(k)) continue;
switch (from.getType(k)) {
case DescValueType.ALIASTYPE: to.putPath(k, from.getPath(k)); break;
case DescValueType.BOOLEANTYPE: to.putBoolean(k, from.getBoolean(k)); break;
case DescValueType.CLASSTYPE: to.putClass(k, from.getClass(k)); break;
case DescValueType.DOUBLETYPE: to.putDouble(k, from.getDouble(k)); break;
case DescValueType.INTEGERTYPE: to.putInteger(k, from.getInteger(k)); break;
case DescValueType.LISTTYPE: to.putList(k, from.getList(k)); break;
case DescValueType.RAWTYPE: to.putData(k, from.getData(k)); break;
case DescValueType.STRINGTYPE: to.putString(k, from.getString(k)); break;
case DescValueType.LARGEINTEGERTYPE: to.putLargeInteger(k, from.getLargeInteger(k)); break;
case DescValueType.REFERENCETYPE: to.putReference(k, from.getReference(k)); break;
case DescValueType.OBJECTTYPE: to.putObject(k, from.getObjectType(k), from.getObjectValue(k)); break;
case DescValueType.ENUMERATEDTYPE: to.putEnumerated(k, from.getEnumerationType(k), from.getEnumerationValue(k)); break;
case DescValueType.UNITDOUBLE: to.putUnitDouble(k, from.getUnitDoubleType(k), from.getUnitDoubleValue(k)); break;
}
}
return to
}
* save this code to a text file, change its extension to .jsx, place it in the presets folder (Adobe Photoshop\Presets\Scripts\). Restart Photoshop, the script will appear in the File -> Scripts menu, after that manual launch, hotkey launch, recording to the action will be available.
This script works with styles of text layers. Randomly generated colors are used (the result is not always perfect, but each run of the script will produce a new set of color). It can work both with text typed in one layer, and with separate letters in different selected layers.
For other layers (where each letter on separate layer) it will be more convenient to work with color fill using effects with this script (set random fill FX to every selected layer). Also here is example of use HSL intead HSB in script above:
#target photoshop
var s2t = stringIDToTypeID;
(r = new ActionReference()).putProperty(s2t('property'), p = s2t('targetLayersIDs'));
r.putEnumerated(s2t('document'), s2t('ordinal'), s2t('targetEnum'));
var lrs = executeActionGet(r).getList(p),
hueDifference = 0;
for (var i = 0; i < lrs.count; i++) {
(d = new ActionDescriptor()).putReference(s2t('null'), lrs.getReference(i));
executeAction(s2t('select'), d, DialogModes.NO);
(r = new ActionReference()).putProperty(s2t("property"), p = s2t("layerEffects"));
r.putEnumerated(s2t('layer'), s2t('ordinal'), s2t('targetEnum'));
var fx = executeActionGet(r).hasKey(p) ? executeActionGet(r).getObjectValue(p) : new ActionDescriptor(),
currentFill = fx.hasKey(p = s2t("solidFill")) ? fx.getObjectValue(p) : new ActionDescriptor();
if (fx.hasKey(p = s2t("solidFillMulti"))) fx.erase(p);
var saturation = 100,
lightness = 50,
hue = 0;
do { hue = Math.random() * 360 } while (Math.abs(hueDifference - hue) < 60);
hueDifference = hue
var RGB = hslToRgb(hue, saturation, lightness)
var d = new ActionDescriptor();
d.putDouble(s2t('red'), RGB[0])
d.putDouble(s2t('grain'), RGB[1])
d.putDouble(s2t('blue'), RGB[2])
currentFill.putObject(s2t("color"), s2t("RGBColor"), d);
fx.putObject(s2t("solidFill"), s2t("solidFill"), currentFill);
(d = new ActionDescriptor()).putReference(s2t("null"), r);
d.putObject(s2t("to"), s2t("layerEffects"), fx);
executeAction(s2t("set"), d, DialogModes.NO);
}
var r = new ActionReference();
for (var i = 0; i < lrs.count; i++) { r.putIdentifier(s2t('layer'), lrs.getReference(i).getIdentifier(s2t('layerID'))) }
(d = new ActionDescriptor()).putReference(s2t('null'), r);
executeAction(s2t('select'), d, DialogModes.NO);
function hslToRgb(h, s, l) {
s /= 100;
l /= 100;
var c = (1 - Math.abs(2 * l - 1)) * s,
x = c * (1 - Math.abs((h / 60) % 2 - 1)),
m = l - c / 2,
r = 0,
g = 0,
b = 0;
if (0 <= h && h < 60) {
r = c; g = x; b = 0;
} else if (60 <= h && h < 120) {
r = x; g = c; b = 0;
} else if (120 <= h && h < 180) {
r = 0; g = c; b = x;
} else if (180 <= h && h < 240) {
r = 0; g = x; b = c;
} else if (240 <= h && h < 300) {
r = x; g = 0; b = c;
} else if (300 <= h && h < 360) {
r = c; g = 0; b = x;
}
return [Math.round((r + m) * 255), Math.round((g + m) * 255), Math.round((b + m) * 255)]
}
If you can create a set of predefined colors or rules by which to determine the color difference, then the color palette can be more accurate.
Copy link to clipboard
Copied
Hi Jazz-y,
First of all, thank you so much for your reply, I was afraid I was going to have to do it all manually! To follow up, suppose I have a list of colors that I would like to use in a certain order, how would I have to change the script? For example;
004fab
00cfb3
ff7000
14a41c
ffd802
f64397
4be715
ffbbb1
8243d0
ff0834
ffd802
And then after the last one start over again with the first color?
Thanks again!
Kind regards,
Copy link to clipboard
Copied
If you mean first script, put on top of it:
arr = [], clrs = ['004fab', '00cfb3', 'ff7000', '14a41c', 'ffd802',
'f64397', '4be715', 'ffbbb1', '8243d0', 'ff0834', 'ffd802'];
Then replace:
with(c.hsb) {
saturation = 100, brightness = 95; do{hue = Math.random() * 360}
while(Math.abs(hueDifference - hue) < 60); hueDifference = hue
}
to:
!arr.length &&
arr = [].slice.call(clrs)
c.rgb.hexValue = arr.shift()
Copy link to clipboard
Copied
Hi Kukurykus,
Thank you, I got it all to work. I did notice however that the colors are still randomized once I run the script, so I have to run it a couple times if I don't like the order. Do you know how I can make sure the colors only follow a certain order? For example; first color 004fab, second color 00cfb3, third color ff7000, etcetera.
Many thanks!
Kind regards
Copy link to clipboard
Copied
I tested my update to the given code and it works as requested, without randomization.
Copy link to clipboard
Copied
I tried it again and it worked indeed. Must've done something wrong the first time.
Thanks again!
Copy link to clipboard
Copied
Hey can you give me please the correct Script ? cause it dident work for me !! Thanks.
Copy link to clipboard
Copied
Hi there,
Is there any way to apply each pattern like image (layer or smart object) for each letter in the whole layer text?
Example: I have 10 different images or patterns and I have a layer text that has 10 letters, so how can I apply each pattern/image for each letter in a certain order and when the last pattern/image in the list was applied then they will start over again with the first pattern/image.
Hope for any comment to help!