Copy link to clipboard
Copied
Hi there,
I'm looking for a solution that will save me a heap of time in a Photoshop process I'm responsible for at work.
I have to create UV squares for use in Blender that contain on average 6 posters per 2k square. As we often deal with 100s of posters per project we assign each poster a code, and I manually type each poster's code over the top of the image to be used as a guide for the team doing the unwrapping in Blender. Example pictures attached.
Since all the posters I import into Photoshop are already coded properly, both the file name and layer name represent the posters code. What I'm looking for is a script or process within Photoshop that would allow me to attach either the layer name or the file name to the corresponding image on the UV square, instead of me manually typing each of them out (long process and error prone), so the result would be something like the attached image with the red identification text next to each image.
This would save me loads of time so I massively appreciate any help anyone could offer.
Thanks,
Alex
The script uses a sample text layer (you can create it manually or with an action for each file). The script remembers the formatting settings of this layer, makes it invisible, and then makes labels for all pixel layers of the document and smart objects (the settings for alignment, displacement, merging of layers can be set in the first variables of the script).
Before starting the script, the layer with the sample text must be selected.
#target photoshop
var align = ['right', 'bottom'], // [x,
...
Copy link to clipboard
Copied
Do you know anything about scripting Photoshop? Do you use menu File>Scripts>Load files into a Stack to import all the poster?
Copy link to clipboard
Copied
From the sample image, I'm guessing that there may be six layers, one for each image.
What happens when you have added text layers? Are there 6 text layers in addition to the original 6 image layers, or are they combined into the underlying image?
Copy link to clipboard
Copied
The script uses a sample text layer (you can create it manually or with an action for each file). The script remembers the formatting settings of this layer, makes it invisible, and then makes labels for all pixel layers of the document and smart objects (the settings for alignment, displacement, merging of layers can be set in the first variables of the script).
Before starting the script, the layer with the sample text must be selected.
#target photoshop
var align = ['right', 'bottom'], // [x, y] x - right or left, y - top or bottom
offset = [-20, -20], // [x, y] pixels
mergeLayers = true, // merge txt with layer or not
lr = new AM('layer');
if (textKey = lr.getProperty('textKey')) {
lr.hideLayerByID(lr.getProperty('layerID'))
var doc = new AM('document'),
len = doc.getProperty('numberOfLayers'),
lrs = [];
for (i = 1; i <= len; i++) {
var lrKind = lr.getProperty('layerKind', i, true)
if (lrKind == 1 || lrKind == 5) {
lrs.push({
name: lr.getProperty('name', i, true),
id: lr.getProperty('layerID', i, true),
bounds: lr.getProperty('bounds')
})
}
}
len = lrs.length
var txt = new AM('textLayer')
for (i = 0; i < len; i++) {
lr.selectLayerByIDList([lrs[i].id]);
var id = (lr.makeTextLayer(textKey)).getInteger(stringIDToTypeID('layerID'));
(d = new ActionDescriptor).putString(stringIDToTypeID('textKey'), lrs[i].name);
txt.setPropertyByDesc(d)
txt.moveLayer(layerOffcet(lr.getProperty('bounds', lrs[i].id), lr.getProperty('bounds', id), align, offset))
if (mergeLayers) { lr.selectLayerByIDList([lrs[i].id, id]); lr.mergeLayers() }
}
}
function layerOffcet(src, tgt, align, offset) {
return [src.getInteger(stringIDToTypeID(align[0])) - tgt.getInteger(stringIDToTypeID(align[0])) + offset[0],
src.getInteger(stringIDToTypeID(align[1])) - tgt.getInteger(stringIDToTypeID(align[1])) + offset[1]]
}
function AM(target) {
var s2t = stringIDToTypeID,
t2s = typeIDToStringID;
target = s2t(target)
this.getProperty = 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'));
return executeActionGet(r).hasKey(property) ? getDescValue(executeActionGet(r), property) : null
}
this.setPropertyByDesc = function (desc, id, idxMode) {
var r = new ActionReference();
id ? (idxMode ? r.putIndex(target, id) : r.putIdentifier(target, id))
: r.putEnumerated(target, s2t('ordinal'), s2t('targetEnum'));
(d = new ActionDescriptor).putReference(s2t('null'), r);
d.putObject(s2t('to'), target, desc);
executeAction(s2t('set'), d, DialogModes.NO);
}
switch (t2s(target)) {
case 'layer':
case 'textLayer':
this.hideLayerByID = function (id) {
(r = new ActionReference()).putIdentifier(s2t('layer'), id);
(l = new ActionList()).putReference(r);
(d = new ActionDescriptor()).putList(s2t('null'), l);
executeAction(s2t('hide'), d, DialogModes.NO);
}
this.selectLayerByIDList = function (IDList) {
var ref = new ActionReference()
for (var i = 0; i < IDList.length; i++) {
ref.putIdentifier(s2t("layer"), IDList[i])
}
var desc = new ActionDescriptor()
desc.putReference(s2t("null"), ref)
executeAction(s2t("select"), desc, DialogModes.NO)
}
this.makeTextLayer = function (textKey) {
(r = new ActionReference()).putClass(s2t('textLayer'));
(d = new ActionDescriptor()).putReference(s2t('null'), r);
d.putObject(s2t('using'), s2t('textLayer'), textKey);
return executeAction(s2t('make'), d, DialogModes.NO);
}
this.moveLayer = function (offset) {
(r = new ActionReference()).putEnumerated(s2t('layer'), s2t('ordinal'), s2t('targetEnum'));
(d = new ActionDescriptor()).putReference(s2t('null'), r);
(d1 = new ActionDescriptor()).putUnitDouble(s2t('horizontal'), s2t('pixelsUnit'), offset[0]);
d1.putUnitDouble(s2t('vertical'), s2t('pixelsUnit'), offset[1]);
d.putObject(s2t('to'), s2t('offset'), d1);
executeAction(s2t('move'), d, DialogModes.NO);
}
this.mergeLayers = function () {
executeAction(s2t("mergeLayers"), new ActionDescriptor(), DialogModes.NO);
}
break;
}
function getDescValue(d, p) {
switch (d.getType(p)) {
case DescValueType.OBJECTTYPE: return (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 [t2s(d.getEnumerationType(p)), t2s(d.getEnumerationValue(p))];
default: break;
};
}
}
Copy link to clipboard
Copied
I've just tested this and it works perfectly - thankyou so much!