3.4 KiB
AI Edit
Photoshop CEP panel for image generation. It sends text prompts to your own image API, previews the result, and places generated PNGs into the active document as new masked layers.
Architecture
| Layer | File | Role |
|---|---|---|
| Panel UI | src/panels/ImageGenerator.jsx |
React + Tailwind, runs in the CEP CEF panel |
| Bridge | src/cep.js |
Node file/network access and evalScript calls |
| Host | cep/host/host.jsx |
ExtendScript: masked layer placement, file and prompt dialogs |
| Manifest | cep/CSXS/manifest.xml |
CEP extension declaration |
Node runs in the panel (--enable-nodejs --mixed-context), so temp files and HTTP
both go through Node rather than UXP storage or fetch.
Styling
Tailwind CSS 3, compiled by PostCSS into dist/styles/panel.css. Utility classes
carry the exact pixel values from the original design, so arbitrary values
(h-[47px], bg-[#2f2f2f]) are used throughout rather than the default scale.
tailwind.config.js— accent color, the rounded font stack, and thenarrow(max 340px) breakpointsrc/index.css— Tailwind entry plus base rules forhtml,body, and#root
src/styles.css and src/panels/ImageGenerator.css are the pre-Tailwind
originals. Nothing imports them; they are kept as the reference for the
original pixel values.
Prompt Input
The prompt box is a contentEditable div. CEF does not reliably receive IME
composition events, so the button above 词库 opens a native Photoshop
ScriptUI window for typing Chinese. Text crosses evalScript as
escape()-encoded ASCII in both directions.
API Shape
The default request is compatible with OpenAI-style image endpoints:
{
"model": "gpt-image-2",
"prompt": "your prompt",
"n": 1,
"size": "1024x1024",
"response_format": "b64_json"
}
Accepted response shapes:
{ "data": [{ "b64_json": "..." }] }
{ "data": [{ "url": "https://..." }] }
output and images arrays are also tolerated for gateway variants.
Photoshop Placement
Generated images first appear only in the panel's thumbnail list. Clicking a thumbnail places it as an embedded smart-object layer with a new layer mask. The selection that existed when generation started is saved as a temporary alpha channel, so the mask still uses the original selection even if the user changes the selection before clicking. Without a selection, the layer gets a reveal-all mask.
When a selection exists, its merged visible pixels are exported as the first
reference image. Uploaded reference files follow it. The panel sends these
images as data URLs in the request body's images array.
The request size is read from Photoshop: the full canvas dimensions are used without a selection, and the selection bounds are used when a selection exists.
Build
npm install
npm run build
Output goes to dist, which is the extension folder itself (dist/CSXS/manifest.xml).
Install
npm run cep:setup
This enables PlayerDebugMode for CSXS 9–12 and links dist into the Adobe
extensions folder. On Windows it writes to HKCU\Software\Adobe\CSXS.* and
creates a directory junction; on macOS it uses defaults write and a symlink.
Restart Photoshop, then open the panel from Plugins.
Development
npm run watch
Reload the panel from its flyout menu, or open http://localhost:8088 for
Chrome DevTools (the port comes from cep/.debug).