Import Image as Layer

Thanks tomzag, after Aurore had no issue with the extra await, I thought I made a mistake. Your suggestion was correct, logical, and made it work!

I now have a working script that imports a layer and then resizes it to the canvas size:

const {executeAsModal} = require("photoshop").core;
const {batchPlay} = require("photoshop").action;
const {localFileSystem: fs} = require("uxp").storage;

const app = require('photoshop').app;
const currentDocument = app.activeDocument;

let docWidth = currentDocument.width;
let docHeight = currentDocument.height;

const gradientSize = 2000;

const scaleX = (docWidth / gradientSize) * 100;
const scaleY = (docHeight / gradientSize) * 100;

async function tokenify(url){
   return fs.createSessionToken(await fs.getEntryWithUrl("file:" + url));
}

async function importLayer() {
   const result = await batchPlay(
      [
         {
            _obj: "placeEvent",
            ID: 5,
            null: {
               _path: await tokenify("C:/STAPELVERARBEITUNG/Hintergrund_Artikel_Verlauf2000x2000MitteHeller.jpg"),
               _kind: "local"
            },
            freeTransformCenterState: {
               _enum: "quadCenterState",
               _value: "QCSAverage"
            },
            offset: {
               _obj: "offset",
               horizontal: {
                  _unit: "pixelsUnit",
                  _value: 0
               },
               vertical: {
                  _unit: "pixelsUnit",
                  _value: 0
               }
            },
            replaceLayer: {
               _obj: "placeEvent",
               to: {
                  _ref: "layer",
                  _id: 5
               }
            },
            _options: {
               dialogOptions: "dontDisplay"
            }
         }
      ],
      {}
   );
}

async function resizeLayer() {
   const result = await batchPlay(
      [
         {
            _obj: "transform",
            freeTransformCenterState: {
               _enum: "quadCenterState",
               _value: "QCSAverage"
            },
            offset: {
               _obj: "offset",
               horizontal: {
                  _unit: "pixelsUnit",
                  _value: 0
               },
               vertical: {
                  _unit: "pixelsUnit",
                  _value: 0
               }
            },
            width: {
               _unit: "percentUnit",
               _value: scaleX
            },
            height: {
               _unit: "percentUnit",
               _value: scaleY
            },
            replaceLayer: {
               _obj: "transform",
               from: {
                  _ref: "layer",
                  _id: 5
               },
               to: {
                  _ref: "layer",
                  _id: 5
               }
            },
            _options: {
               dialogOptions: "dontDisplay"
            }
         }
      ],
      {}
   );
}


async function runModalFunction() {
   await executeAsModal(importLayer, {"commandName": "importLayer"});
   await executeAsModal(resizeLayer, {"commandName": "resizeLayer"});
}

runModalFunction();

I do know there are a few things to reorganize once I implement this snippet into my bigger script, but I am happy it runs for now.
May I ask two last questions to properly understand what I am doing?
1.) In both batchplay functions, there is a “replaceLayer” section with a “ref” and “id”.
While importing the layer, what happens if another layer already has the id 5? It would be replaced, no? Shouldnt it find the first “unused” ID instead?

2.) Couldnt using the hardcoded id of 5 in the resizeLayer function potentially conflict if the above was fixed? Like, if another layer had the ID of 5, it would rescale the wrong layer or does it work on the selection?

Reading the documentation about batchplay, it says

  • The target for the command. This describes the (DOM) element that the command should operate on. The target is specified via the _target keyword. This property is sometimes omitted. If omitted, the command operates on a default element. The default element is typically the object that is active in the UI.

So what does the “replaceLayer” section in both batchPlay functions refer to?

edit: ChatGPT says I can delete it and then its using the active layer automatically. Is that true?

Here is an updated version of my script. Any advice on how to make it cleaner?

const {executeAsModal} = require("photoshop").core;
const {batchPlay} = require("photoshop").action;
const {localFileSystem: fs} = require("uxp").storage;

const app = require('photoshop').app;


async function tokenify(url){
   return fs.createSessionToken(await fs.getEntryWithUrl("file:" + url));
}

async function importLayer() {
   const result = await batchPlay(
      [
         {
            _obj: "placeEvent",
            null: {
               _path: await tokenify("C:/STAPELVERARBEITUNG/Hintergrund_Artikel_Verlauf2000x2000MitteHeller.jpg"),
               _kind: "local"
            },
            freeTransformCenterState: {
               _enum: "quadCenterState",
               _value: "QCSAverage"
            },
            offset: {
               _obj: "offset",
               horizontal: {
                  _unit: "pixelsUnit",
                  _value: 0
               },
               vertical: {
                  _unit: "pixelsUnit",
                  _value: 0
               }
            },
            _options: {
               dialogOptions: "dontDisplay"
            }
         }
      ],
      {}
   );
}

async function resizeLayer(scaleX, scaleY) {
   const result = await batchPlay(
      [
         {
            _obj: "transform",
            freeTransformCenterState: {
               _enum: "quadCenterState",
               _value: "QCSAverage"
            },
            offset: {
               _obj: "offset",
               horizontal: {
                  _unit: "pixelsUnit",
                  _value: 0
               },
               vertical: {
                  _unit: "pixelsUnit",
                  _value: 0
               }
            },
            width: {
               _unit: "percentUnit",
               _value: scaleX
            },
            height: {
               _unit: "percentUnit",
               _value: scaleY
            },
            _options: {
               dialogOptions: "dontDisplay"
            }
         }
      ],
      {}
   );
}

async function sendToBack() {
   const result = await batchPlay(
      [
         {
            _obj: "move",
            _target: [
               {
                  _ref: "layer",
                  _enum: "ordinal",
                  _value: "targetEnum"
               }
            ],
            to: {
               _ref: "layer",
               _enum: "ordinal",
               _value: "back"
            },
            _options: {
               dialogOptions: "dontDisplay"
            }
         }
      ],
      {}
   );
}


async function main() {
    const currentDoc = app.activeDocument;
    const gradientSize = 2000;
    
    await executeAsModal(importLayer, {commandName: "importLayer"});
    
    let scaleX = (currentDoc.width / gradientSize) * 100;
    let scaleY = (currentDoc.height / gradientSize) * 100;

    await executeAsModal(() => resizeLayer(scaleX, scaleY), {commandName: "resizeLayer", args: [scaleX, scaleY]});
    
    await executeAsModal(sendToBack, {commandName: "sendToBack"});
}

main();
1 Like