Copy link to clipboard
Copied
Hi everyone,
i'm pretty new to scripting so i would really love to have some suggestions. i'm trying to code a script that does the following steps:
1.open the selected files (not from folder) in a layered photoshop stack
2. align them
3. read the shortest layer name and saves to a variable (let's call it "product")
4. create some layerset
5. saves the file to the parent directory of the source with the "product" name
6. close the file
i searched on the forum for a solution for long time but my scripting skills are too basic.
i'm not sure if it's better to do this form bridge or directly from ps.
at the moment i'm trying both the ways but don't figure out how to solve.
for the bridge script i've found some hint from this forum but this doesn't open the layered stack...
#target bridge
/*if( BridgeTalk.appName == "bridge" ) {
stacksToLayers = new MenuElement("command", "Stacks To Layers", "at the end of Tools");
}
stacksToLayers.onSelect = function () { */
var stacks = app.document.selections;
var stackCount = stacks.length;
for(var s = 0;s<stackCount;s++){
var stackFiles = getStackFiles( stacks
);if(stackFiles.length> 1){
var bt = new BridgeTalk;
bt.target = "photoshop";
var myScript = ("var ftn = " + psRemote.toSource() + "; ftn("+stackFiles.toSource()+");");
bt.body = myScript;
bt.onResult = function( inBT ) {myReturnValue(inBT.body); }
bt.send(500);
}
}
function getStackFiles( stack ){
var files = new Array();
for( var f = 0; f<stackCount;f++){
files.push(stacks
.spec); }
return files;
};
function myReturnValue(str){
res = str;
}
// don't have comments in the psRemote function
function psRemote(stackFiles){
var loadLayersFromScript = true;
var strPresets = localize ("$$$/ApplicationPresetsFolder/Presets=Presets");
var strScripts = localize ("$$$/PSBI/Automate/ImageProcessor/Photoshop/Scripts=Scripts");
var strFile2Stack = "Load Files into Stack.jsx";
var ipFilePath = app.path + "/" + strPresets + "/" + strScripts + "/" + strFile2Stack;
var ipFile = new File (ipFilePath);
$.evalFile( ipFile );
loadLayers.intoStack(stackFiles);
var saveFile = new File('~/desktop/'+app.activeDocument.name+'.psd');
app.activeDocument.saveAs(saveFile);
}
//}// app.activeDocument.close(SaveOptions.DONOTSA
VECHANGES);
from debugging it stops on bt.send(500); line repeating this command....
$.level = 0; app.synchronousMode = false;
on the ps script part i have similar issue, the layered files doesn't open... here the code
var fileList= File.openDialog("seleziona i files",undefined,true);
for (i = 0; i <= fileList.length-1; i++) {
alert(fileList.path + "/" +fileList.name);
// or open or do somethig else
}
if ( fileList != null ){
runLoadStack();
}
function runLoadStack( fileList ){
var loadLayersFromScript = true;// must be set before the include
// @include '/C/Program Files/Adobe/Adobe Photoshop CC 2017/Presets/Scripts/Load Files into Stack.jsx'
var aFlag = true;
loadLayers.intoStack( fileList, aFlag );
}
the other parts of the script i should be able to manage...
anyone could help me?
thank you a lot and a great hug form Italy
Alessio
Copy link to clipboard
Copied
sorry i wrote too fast ![]()
it also saves the psd in the same folder with 2 layers inside a layerset
GREATTTTT
Copy link to clipboard
Copied
I tried the older version of the script with other stacks and everything is working correctly... actually the problem was with the pictures i used to test it.. never thought about this ![]()
i think you are a great programmer, for real!
Copy link to clipboard
Copied
What's wrong with pictures you used for test, why they don't have resolution? What is difference between them and regular ones? Can you also check my last post - I updated it. Regarding being great programmer - I think SuperMerlin is greater ![]()
Copy link to clipboard
Copied
is there a way to save the file in tif format to the parent directory?
i've tryed
aD.saveAs(File(decodeURI(v[0]).slice(0, -3).parent + '.tif'))
but is not working..
anyway thanks a lot for your time and experience. Hope to see the results of all this efforts!
Don't know supermerlin, but of course you know what you're doing
Copy link to clipboard
Copied
I think it can be changed to .tif on the condition you will use tif options which you store to tif variable and then use this:
aD.saveAs(File(decodeURI(v[0]).slice(0, -3) + 'tif'), tif)
You can actually set default resolution to 300 in this Bridge part of script:
w = m().width, h = m().height, x = m().xResolution || 300
As I said in post with original script that's not done yet. Now after you tested it and suggested some changes, I'll write them.
Copy link to clipboard
Copied
Hi,
hope this finds you well!!
do you think you are going to work on this in the next days? if not i wil try to make the changes, let's see what happens ![]()
anyway thank you again for your efforts
Copy link to clipboard
Copied
I'm sorry for delay. I had to focus on other huge project I started actually before your script. But it's almost finished, so I will try today evening to finish also this one for you. If not today then probably tomorrow. Thx for patience, and of course that's something interesting to me to get it done ![]()
Copy link to clipboard
Copied
Hi Kukurykus,
i want to share with you the result of my hard coding day ![]()
this is where i am at the moment:
the structure of the folders and layers is working good
the script saves the file in the parent parent folder of the stack
it saves a tiff with lzw compression and name it with the right filename
i know i'm a donk in coding, but i'm pretty happy about how it is working ![]()
#target bridge
/*if( BridgeTalk.appName == "bridge" ) {
batchone = new MenuElement("command", "batchone", "at the end of Tools");
}
batchone.onSelect = function () { */
if (sLen = (stck = (ad = app.document).stacks).length) {
ad.chooseMenuItem('CollapseAllStacks')
for(arr = Array(sLen), i = 0; i < sLen; i++) {
arr = [], tLen = (img = stck.thumbnails).length
for(j = tLen - 1; j >= 0; j--) arr
= img .spec m = function() {return img[0].core.quickMetadata}
w = m().width, h = m().height, x = m().xResolution
r = !((Math.abs(new Thumbnail(arr[0]).rotation / 90) + 2) % 3)
if (r) h = ([w = h, m().width])[1]; arr[tLen] = {w: w, h: h, x: x || 300}
}
}
function Ps(v) {
displayDialogs = DialogModes.NO
function openingAlligningSaving(v) {
(dsc1 = new ActionDescriptor()).putPath(sTT('null'), v)
dsc1.putEnumerated(sTT('freeTransformCenterState'), sTT('quadCenterState'), sTT('QCSAverage'));
(dsc2 = new ActionDescriptor()).putUnitDouble(sTT('horizontal'), sTT('pixelsUnit'), 0)
dsc2.putUnitDouble(sTT('vertical'), sTT('pixelsUnit'), 0)
dsc1.putObject(sTT('offset'), sTT('offset'), dsc2)
executeAction(sTT('placeEvent'), dsc1)
}
function sTT(v) {return stringIDToTypeID(v)}
(ref1 = new ActionReference()).putProperty(sTT('property'), sTT('generalPreferences'))
ref1.putEnumerated(sTT('application'), sTT('ordinal'), sTT('targetEnum'));
(dsc1 = new ActionDescriptor()).putReference(sTT('null'), ref1);
(dsc2 = new ActionDescriptor()).putBoolean(sTT('placeRasterSmartObject'), false)
dsc1.putObject(sTT('to'), sTT('generalPreferences'), dsc2)
executeAction(sTT('set'), dsc1)
prf = preferences.rulerUnits, preferences.rulerUnits = Units.PIXELS;
for(i = 0; i < v.length; i++) {
documents.add((whx = v[v.length - 1]).w, whx.h, whx.x)
for(j = 0; j < v.length - 1; j++) openingAlligningSaving(v
); // var srcDoc = app.activeDocument;
// var nome = srcDoc.layers[0].name;
// alert(nome)
(aD = activeDocument).selection.selectAll();
(ref1= new ActionReference()).putEnumerated
(sTT('layer'), sTT('ordinal'), sTT('targetEnum'));
(dsc1 = new ActionDescriptor()).putReference(sTT('null'), ref1)
executeAction(sTT('selectAllLayers'), dsc1);
/* TEMPORARY */(function algn(v1, v2) {
dsc1.putEnumerated(sTT('using'), sTT('alignDistributeSelector'),
sTT(v1)), executeAction(sTT('align'), dsc1); if (v2) algn('ADSLefts')
})('ADSTops', true);/* TEMPORARY */
(ref2 = new ActionReference()).putClass(sTT('layerSection'));
(dsc1 = new ActionDescriptor()).putReference(sTT('null'), ref2);
dsc1.putReference(sTT('from'), ref1), executeAction(sTT('make'), dsc1)
dsc1.putReference(sTT('null'), ref1);
(dsc2 = new ActionDescriptor()).putString(sTT('name'), 'Montaggio')
dsc1.putObject(sTT('to'), sTT('layer'), dsc2)
executeAction(sTT('set'), dsc1, DialogModes.NO)
var srcDoc = app.activeDocument;
var newGroup = srcDoc.layerSets.add();
newGroup.name = "Scontorno";
var newTemp = srcDoc.layerSets["Scontorno"].artLayers.add();
newTemp.name = "temp";
srcDoc.layerSets["Montaggio"].move(srcDoc.layerSets["Scontorno"].layers["temp"], ElementPlacement.PLACEBEFORE);
srcDoc.layerSets["Scontorno"].layers["temp"].remove();
aD.selection.deselect(), aD.backgroundLayer.remove()
var nomeDir = String(v[0]);
// alert(nomeDir);
var cal = nomeDir.lastIndexOf("/");
var nomeFile = String(nomeDir).slice(cal+1);
var lung = String(File(decodeURI(v[0].parent.parent)));
alert(lung)
var newNamePath = lung + '/' + nomeFile.slice(0,-3) + 'tif';
tiffSaveOptions = new TiffSaveOptions();
tiffSaveOptions.embedColorProfile = true;
tiffSaveOptions.alphaChannels = true;
tiffSaveOptions.layers = true;
tiffSaveOptions.imageCompression = TIFFEncoding.TIFFLZW;
aD.saveAs(File(newNamePath), tiffSaveOptions, true,Extension.LOWERCASE);
aD.close(SaveOptions.DONOTSAVECHANGES)
/*
(ref = new ActionReference()).putEnumerated
(sTT('layer'), sTT('ordinal'), sTT('targetEnum'));
(dsc = new ActionDescriptor()).putReference(sTT('null'), ref )
dsc.putEnumerated( sTT('using'), sTT('alignDistributeSelector'), sTT('ADSContent'))
dsc.putEnumerated( sTT('apply'), sTT('projection'), sTT('perspective')), executeAction(sTT('align'), dsc)
*/
}
preferences.rulerUnits = Units.PIXELS = prf
}
//alert(sLen = (stck = (ad = app.document).stacks).length);
arr = arr.toSource(),
(bT = new BridgeTalk()).target = 'photoshop'
bT.body = Ps.toString() + '\nPs(' + arr + ')', bT.send()
//};
Copy link to clipboard
Copied
Yestarday I had no time while today I woke up late, but now I have time to focus on it what I'm going to do for next hours ![]()
For now I had time to focus on the hardest for me thing, so Br part. Now you can decide which Stacks you want to process:
sel = (ad = app.document).selectionLength
if (arr = [], sel && sLen = (stck = ad.stacks).length) {
ad.chooseMenuItem('CollapseAllStacks'), str = ''
for(i = 0; i < sel; i++) str += ad.selections.name + '|'
function iO(v) {return str.indexOf(v)}; for(i = 0; i < sLen; i++) {
if (iO((itm = (s = stck).thumbnails[0].name + '|')) + 1) {
str = str.replace(itm, ''), image = stck.thumbnails
arr[l = arr.length] = new Array, tLen = image.length
for(j = tLen - 1; j >= 0; j--) arr
= image .spec m = function() {return image[0].core.quickMetadata}
w = m().width, h = m().height, x = m().xResolution || 300
r = !((Math.abs(new Thumbnail(arr
[0]).rotation / 90) + 2) % 3) if (r) h = ([w = h, m().width])[1]; arr
[tLen] = {w: w, h: h, x: x} if (arr.length == sel) break;
}
}
}
Also change last 2 lines to:
arr = arr.toSource(), (bT = new BridgeTalk()).target = 'photoshop'
if (arr.length) bT.body = Ps.toString() + '\nPs(' + arr + ')', bT.send()
It still does not work with nasted folders (so Smart Objects in Smart Objects if that was Ps). I will do it after all other parts...
ah btw I noticed you marked as correct solution wrong one in this topic: apply layer mask / that was mine, not yours ![]()
Here are another improvements. Now you can keep original resolution of each layer in created document as well as keep original dimension of all stacked layers so if they were bigger/smaller or had other orientation it will be taken into account. It also is storing layer names to choose the shortest and save new .psd with its name. So it is doing now almost everything. EDIT: there was a bug. It opened all next stack with dimension of first stuck. Now it works correctly. I also added files will be saved as tif's. I changed also order of layers beeing placed in a file. Previously there was wrong order, not the same as Stacks got. Last thing is you can run it now clicking right mouse button on selected thumbnail(s) to choose last item called 'Stacks':
#target bridge
Stacks = new MenuElement('command', 'Stacks', 'at the end of Thumbnail')
Stacks.onSelect = function() {
sel = (ad = app.document).selectionLength
if (arr = [], sel && sLen = (stck = ad.stacks).length) {
ad.chooseMenuItem('CollapseAllStacks'), str = ''
for(i = 0; i < sel; i++) str += ad.selections.name + '|'
function iO(v) {return str.indexOf(v)}; for(i = 0; i < sLen; i++) {
if (iO((itm = (s = stck).thumbnails[0].name + '|')) + 1) {
str = str.replace(itm, ''), image = stck.thumbnails
arr[l = arr.length] = new Array // array of all stacks
m = function() {return image
.core.quickMetadata} for(tLen = image.length, j = 0; j < tLen; j++) {
arr
= Array(2), arr [0] = image .spec w = m().width, h = m().height, x = m().xResolution || 300
r = !((Math.abs(new Thumbnail(arr
[0]).rotation / 90) + 2) % 3) if (r) h = ([w = h, m().width])[1]; arr
[1] = {w: w, h: h, x: x} }
if (arr.length == sel) break;
}
}
}
function Ps(v) {
function placing(v1, v2) {
(dsc1 = new ActionDescriptor()).putPath(sTT('null'), v1)
dsc1.putEnumerated(sTT('freeTransformCenterState'),
sTT('quadCenterState'), sTT('QCSAverage'))
dsc2 = new ActionDescriptor();
(function loop(v) {
(arr = v ? ['width', 'height'] :
['horizontal', 'vertical'])
for(I = 0; I < arr.length;) {
(v ? dsc1 : dsc2).putUnitDouble(sTT(arr[I++]),
sTT((v ? 'percent' : 'pixels') + 'Unit'), v || 0)
}
if (!v) loop(v2)
})()
dsc1.putObject(sTT('offset'), sTT('offset'), dsc2)
executeAction(sTT('placeEvent'), dsc1)
}
displayDialogs = DialogModes.NO; function sTT(v) {return stringIDToTypeID(v)}
(ref = new ActionReference()).putProperty(sTT('property'),
gP = sTT('generalPreferences')), ref.putClass(sTT('application'))
dsc = executeActionGet(ref).getObjectValue(sTT('generalPreferences'))
.getBoolean(pRSO = sTT('placeRasterSmartObject'))
function plc(v) {
(dsc1 = new ActionDescriptor()).putReference(sTT('null'), ref);
(dsc2 = new ActionDescriptor()).putBoolean(pRSO, v)
dsc1.putObject(sTT('to'), gP, dsc2), executeAction(sTT('set'), dsc1)
}
if (dsc) plc(!dsc); prf = preferences.rulerUnits, preferences.rulerUnits = Units.PIXELS
for(i = 0; i < v.length; i++) {whx = v[0][1]
documents.add(whx.w, whx.h, whx.x), nme = ''
for(aD = activeDocument, j = v.length - 1; j >= 0; j--) {
whx = v
[1]; if (j) { w = aD.width, h = aD.height, nW = w - whx.w, nH = h - whx.h
function con(v1, v2) {return (v1 + (v2 < 0 && Math.abs(v2)) || 0)}
aD.resizeCanvas(con(w, nW), con(h, nH), AnchorPosition.TOPLEFT)
}
placing(v
[0], whx.x / aD.resolution * 100) if (nn = aD.activeLayer.name, !nme) nme = nn
else if(nn.length < nme.length) nme = nn
}
aD.selection.selectAll();
(ref1= new ActionReference()).putEnumerated
(sTT('layer'), sTT('ordinal'), sTT('targetEnum'));
(dsc1 = new ActionDescriptor()).putReference(sTT('null'), ref1)
executeAction(sTT('selectAllLayers'), dsc1);
(function algn(v1, v2) {
dsc1.putEnumerated(sTT('using'), sTT('alignDistributeSelector'),
sTT(v1)), executeAction(sTT('align'), dsc1); if (v2) algn('ADSLefts')
})('ADSTops', true);
(ref2 = new ActionReference()).putClass(sTT('layerSection'));
(dsc1 = new ActionDescriptor()).putReference(sTT('null'), ref2)
dsc1.putReference(sTT('from'), ref1), executeAction(sTT('make'), dsc1)
dsc1.putReference(sTT('null'), ref1), lS = 'Scontorno';
(dsc2 = new ActionDescriptor()).putString(sTT('name'), lS)
dsc1.putObject(sTT('to'), sTT('layer'), dsc2)
executeAction(sTT('set'), dsc1)
tif = new TiffSaveOptions, tif.alphaChannels
= tif.layers = tif.embedColorProfile = true
tif.imageCompression = TIFFEncoding.TIFFLZW
aD.selection.deselect(), aD.backgroundLayer.remove()
aD.saveAs(File(v[0][0].path + '/' + nme), tif)
aD.close(SaveOptions.DONOTSAVECHANGES)
}
preferences.rulerUnits = Units.PIXELS = prf; if (dsc) plc(dsc)
}
arr = arr.toSource(), (bT = new BridgeTalk()).target = 'photoshop'
if (arr.length) bT.body = Ps.toString() + '\nPs(' + arr + ')', bT.send()
}
The last thing I have to do is to make a loop over Br Stacks so they can be opened in Ps in subfolder imitating deeper stacks.
Get ready! An upgraded Adobe Community experience is coming in January.
Learn more