When batch saving JPG images, is it possible to skip the confirmation prompt?
I need to modify several JPEG, JPG, PNG, and BMP images to 350 dpi and 200mm width, then automatically save them as JPGs with optimal quality (12) and standard baseline.
I recorded an action.
Then I used the following script to repeat this action. However, when encountering PNG files, the action halts and prompts me to save the original PNG. This is annoying since I don't need to retain the original PNG format.
Additionally, while newer Photoshop versions allow disabling saving as a duplicate, it sometimes still takes effect, consistently saving duplicates—which is also frustrating.
Another issue is that actions always save to the previous directory instead of the new file's location, which is equally bothersome.
Thank you.
#target photoshop
app.bringToFront();
// Repeat the selected action N times
/////////////////////////////////////////////////////////////////////
// Function: GlobalVariables
// Usage: global action items that are reused
// Input: <none>
// Return: <none>
/////////////////////////////////////////////////////////////////////
function GlobalVariables() {
gClassActionSet = charIDToTypeID('ASet');
gClassAction = charIDToTypeID('Actn');
gKeyName = charIDToTypeID('Nm ');
gKeyNumberOfChildren = charIDToTypeID('NmbC');
}
/////////////////////////////////////////////////////////////////////
// Function: GetActionSetInfo
// Usage: walk all the items in the action palette and record the action set
// names and all the action children
// Input: <none>
// Return: the array of all the ActionData
// Note: This will throw an error during a normal execution. There is a bug
// in Photoshop that makes it impossible to get an acurate count of the number
// of action sets.
/////////////////////////////////////////////////////////////////////
function GetActionSetInfo() {
var actionSetInfo = new Array();
var setCounter = 1;
while (true) {
var ref = new ActionReference();
ref.putIndex(gClassActionSet, setCounter);
var desc = undefined;
try { desc = executeActionGet(ref); }
catch (e) { break; }
var actionData = new ActionData();
if (desc.hasKey(gKeyName)) {
actionData.name = desc.getString(gKeyName);
}
var numberChildren = 0;
if (desc.hasKey(gKeyNumberOfChildren)) {
numberChildren = desc.getInteger(gKeyNumberOfChildren);
}
if (numberChildren) {
actionData.children = GetActionInfo(setCounter, numberChildren);
actionSetInfo.push(actionData);
}
setCounter++;
}
return actionSetInfo;
}
/////////////////////////////////////////////////////////////////////
// Function: GetActionInfo
// Usage: used when walking through all the actions in the action set
// Input: action set index, number of actions in this action set
// Return: true or false, true if file or folder is to be displayed
/////////////////////////////////////////////////////////////////////
function GetActionInfo(setIndex, numChildren) {
var actionInfo = new Array();
for (var i = 1; i <= numChildren; i++) {
var ref = new ActionReference();
ref.putIndex(gClassAction, i);
ref.putIndex(gClassActionSet, setIndex);
var desc = undefined;
desc = executeActionGet(ref);
var actionData = new ActionData();
if (desc.hasKey(gKeyName)) {
actionData.name = desc.getString(gKeyName);
}
var numberChildren = 0;
if (desc.hasKey(gKeyNumberOfChildren)) {
numberChildren = desc.getInteger(gKeyNumberOfChildren);
}
actionInfo.push(actionData);
}
return actionInfo;
}
/////////////////////////////////////////////////////////////////////
// Function: ActionData
// Usage: this could be an action set or an action
// Input: <none>
// Return: a new Object of ActionData
/////////////////////////////////////////////////////////////////////
function ActionData() {
this.name = "";
this.children = undefined;
this.toString = function () {
var strTemp = this.name;
if (undefined != this.children) {
for (var i = 0; i < this.children.length; i++) {
strTemp += " " + this.children[i].toString();
}
}
return strTemp;
}
}
//////////
function CreateSnapshot(name) {
function cTID(s) { return app.charIDToTypeID(s); };
var desc = new ActionDescriptor();
var ref = new ActionReference();
ref.putClass(cTID('SnpS'));
desc.putReference(cTID('null'), ref);
var ref1 = new ActionReference();
ref1.putProperty(cTID('HstS'), cTID('CrnH'));
desc.putReference(cTID('From'), ref1);
desc.putString(cTID('Nm '), name);
desc.putEnumerated(cTID('Usng'), cTID('HstS'), cTID('FllD'));
executeAction(cTID('Mk '), desc, DialogModes.NO);
}
//////////
res = "dialog { \
text:'Repeat the selected action',\
group: Group{orientation: 'column',alignChildren:'left',\
corrdination: Panel { orientation: 'row', \
text: 'Select Action', \
cla: Group { orientation: 'row', \
d: DropDownList { alignment:'left' },\
}\
act: Group { orientation: 'row', \
d: DropDownList { alignment:'left' },\
}\
}, \
num: Group { orientation: 'row', \
s: StaticText { text:'Number of executions:' }, \
e: EditText { preferredSize: [50, 20] } ,\
}, \
Snapshot:Group{ orientation: 'row', \
c: Checkbox { preferredSize: [16, 16]} ,\
s: StaticText {text:'Create a snapshot (select appropriately based on the action content)'},\
}, \
},\
buttons: Group { orientation: 'row', alignment: 'right',\
Btnok: Button { text:'Confirmed', properties:{name:'ok'} }, \
Btncancel: Button { text:'Cancel', properties:{name:'cancel'} } \
} \
}";
win = new Window(res);
GlobalVariables();
var actionInfo = GetActionSetInfo();
var ddSet = win.group.corrdination.cla.d;
var ddAction = win.group.corrdination.act.d;
if (actionInfo.length > 0) {
for (var i = 0; i < actionInfo.length; i++) {
ddSet.add("item", actionInfo[i].name);
}
ddSet.items[0].selected = true;
ddSet.onChange = function () {
ddAction.removeAll();
for (var i = 0; i < actionInfo[this.selection.index].children.length; i++) {
ddAction.add("item", actionInfo[this.selection.index].children[i].name);
}
if (ddAction.items.length > 0) {
ddAction.items[0].selected = true;
}
ddSet.helpTip = ddSet.items[ddSet.selection.index].toString();
}
ddSet.onChange();
} else {
ddSet.enabled = false;
ddAction.enabled = false;
}
ddAction.onChange = function () {
ddAction.helpTip = ddAction.items[ddAction.selection.index].toString();
}
win.buttons.Btncancel.onClick = function () {
this.parent.parent.close();
}
win.buttons.Btnok.onClick = function () {
g = Number(win.group.num.e.text);
g = 200;//执行次数
if (g < 1) {
alert('-_-!!! It has to run at least once, right??')
win.group.num.e.text = '1';
g = 1
} else {
var b = win.group.Snapshot.c.value;
if (b && app.documents.length) { CreateSnapshot(g + "Before executing all actions"); } //For safety reasons, create a snapshot.
for (i = 0; i < g; i++) {
doAction(ddAction.selection, ddSet.selection) //Perform the selected action
}
this.parent.parent.close();
}
}
win.center();
win.show();
