Skip to main content
Participating Frequently
March 26, 2024
Answered

How to create a basic save image UXP script?

  • March 26, 2024
  • 3 replies
  • 4544 views

I am new to Photoshop UXP scripts. I am trying to create a simple UXP script that will resize the current image in Photoshop and then save it to a user specified file location. So far, I have only written the image save code (i.e., no resize code), but it is not working. Here is the code:

 

const ps = require('photoshop');
const uxp = require('uxp');
const fs = uxp.storage.localFileSystem;
const core = ps.core;
const app = ps.app;
const img = app.activeDocument;

try {
    const file = await fs.getFileForSaving('', { types: [ 'jpg' ] });
    img.saveAs.jpg(file, { quality: 8 });
} catch (e) {
    core.showAlert(e.message);
    console.log(e);
}

 

I think the code is throwing on img.saveAs after I click the Save button on the Save dialog. However, I cannot get the PS debugger connected to the script, so I have no logs. Curiously, core.showAlert in the catch clause does not display an alert, so I'm completely blind. I can display an alert before the call to img.saveAs, but not immediately after that line., so it must be either throwing or completely crashing when I click the Save button.

 

A small dialog appears on the screen after I click the Save dialog's Save button. The dialog disappears in a flash (I can't even capture it with a screen recorder), but it looks like it might be a progress bar. The image file is not saved.

 

It's very frustrating to have no way to debug the problem, but it is what it is. Can anyone see what is wrong, or have any suggestions?

 

Correct answer Davide_Barranca12040269

Hi,

I've just copied and pasted your code in a `.psjs` file, verbatim, with one minor correction:

 

await img.saveAs.jpg(file, { quality: 8 }); // 👈 note the await

 

I've one document open, I select File > Scripts > Browse...; point to the `.psjs` file; the save dialog pops up, I enter a filename; a progress bar briefly flashes; the file is correctly saved on disk.

 

Please note that:

  •  saveAs methods are asynchronous: they return a promise, hence the need to `await`.
  • Manifest permissions for disk access are needed only in the context of UXP plugins, not UXP scripts.
  • File management is one confusing piece of UXP. Although it is a paid resource, I devote an entire chapter to it in my Professional Photoshop UXP book.

 

I'd kindly remind the moderators to reset the `DAYS_SINCE_QUESTIONS_ABOUT_SAVING_FILES` counter. 🙃

 

 

3 replies

Davide_Barranca12040269
Braniac
April 10, 2024

Hi,

I've just copied and pasted your code in a `.psjs` file, verbatim, with one minor correction:

 

await img.saveAs.jpg(file, { quality: 8 }); // 👈 note the await

 

I've one document open, I select File > Scripts > Browse...; point to the `.psjs` file; the save dialog pops up, I enter a filename; a progress bar briefly flashes; the file is correctly saved on disk.

 

Please note that:

  •  saveAs methods are asynchronous: they return a promise, hence the need to `await`.
  • Manifest permissions for disk access are needed only in the context of UXP plugins, not UXP scripts.
  • File management is one confusing piece of UXP. Although it is a paid resource, I devote an entire chapter to it in my Professional Photoshop UXP book.

 

I'd kindly remind the moderators to reset the `DAYS_SINCE_QUESTIONS_ABOUT_SAVING_FILES` counter. 🙃

 

 

Davide Barranca - PS developer and authorwww.ps-scripting.com
Participating Frequently
April 11, 2024

Thanks @Davide_Barranca12040269! Although I have not actually tried your solution (I solved the problem via use of an action instead), your answer appears sensible and it sounds like you have tested it.

Still, it seems odd that the lack of an await on the saveAs would have prevented getFileForSaving from properly displaying the Save dialog since getFileForSaving is invoked before saveAs. Also, the missing await should not have been technically necessary for this case (although certainly a good practice!) since there is no code following the saveAs, and the event loop should not exit before all promises are resolved.

Davide_Barranca12040269
Braniac
April 11, 2024

Hiya!

When I tested your code, the save dialog did appear (hence, I guess, `file` was properly formed), but the image wasn't saved on disk: all I got was an empty file. What you say about the event loop makes total JavaScript sense; still, I've been bitten in the rear end so many times by a missing `await` in PS scripting that I tend to always use them.

 

Davide Barranca - PS developer and authorwww.ps-scripting.com
Inspiring
March 30, 2024

se vuoi salvare il file in una posizione devi creare un token di sessione. Non ho dubbi che sarai in grado di farlo.

 

I forgot another thing you need to modify and the manifest file you must give write and save permissions

Participating Frequently
March 30, 2024

After reading your reply, I found documentation on the manifest, but it indicated that providing a manifest is only applicable to plug-ins. UXP scripts use a manifest too, but it's an internal, immutable manifest. However, the UXP script manifest already provides full access permission to the file system, so no manifest change is needed for UXP scripts.

Inspiring
March 31, 2024

@Ciccillotto , Yes, I've been referring only to UXP scripts (psjs) from the beginning. I saw your comment about manifests and I thought that might be part of what I was missing to get my script working. But then I saw the Adobe docs state that configurable manifests are only applicable to plug-ins, so unfortunately, manifests do not help me.


psjs files are just single scripts, When we talk about UXP, we mean a panel with buttons. That's why I mentioned the manifest file. happy for you that you solved it.

Stephen Marsh
Braniac
March 26, 2024

Breaking out the popcorn...

Stephen Marsh
Braniac
March 30, 2024

Bump...

 

 

if (disgruntled === true) {
    I really don't wish to have a rant here, however, this topic, in a nutshell, is one of the fundmental problems with UXP scripting for new users or users experienced with ExtendScript. I hope that moving forward Adobe do a much better job of making such "simple things" accessible with clear, concise working examples of both DOM and batchPlay code.

} else {
    How could one who has an interest in the future of Adobe scripting otherwise feel?
}

 

 

I don't consider the following to be helpful.

 

https://developer.adobe.com/photoshop/uxp/2022/scripting/samples/#access-the-local-filesystem 

 

Participating Frequently
March 30, 2024

@Stephen Marsh, Ok, thanks, at least I understand the situation a bit better now.

 

And, yes, I agree, Adobe's filesystem sample was not helpful. I had already found that same example on a different page and I was dumbfounded as to why Adobe was presenting an example of how to save a text file, rather than a useful example of how to save an image file. I then found an activeDocument.saveAs.jpg example elsewhere, but alas, that wasn't enough to get my script working.

 

Everything worked out in the end because I was able to write a UXP script to calculate the reduced image dimensions I needed and resize the image to those new dimensions, which was the script's main purpose. I then invoked the UXP script from a custom Photoshop action. The action then displays the file save dialog after invoking the script. That worked very well for my situation.