Photoshop 24.6.0 doc.channels.getByName(); not working

Updated to 24.6.0 and when I try to get a channel by its name using the DOM I get an empty object.

app.activeDocument.channels.getByName(CHANNEL_NAME);

This used to work good in the past version, here I have an “empty” log.

EDIT*

I have the same error with batchPlay if I try to copy the channel into a new doc…

async function duplicateChannelInOnDifferentDoc(channelName, targetDoc) {
    // console.log(channelName);
    // console.log(targetDoc);
  await batchPlay([
    {
      "_obj": "duplicate",
      "_target": [
        {
          "_ref": "channel",
          "_enum": "ordinal",
          "_value": "targetEnum"
        }
      ],
      "to": {
        "_ref": "document",
        "_name": targetDoc
      },
      "name": channelName,
      "_isCommand": true
    }
  ], {})
}

I get this message again:

Error: NAPI API failure: String expected

This was an old bug and it is now active again in PS 24.6.0

What is your channel name? I need more info to reproduce an issue.

  1. sample PSD file
  2. what code fails
  3. what do you expect to have
  4. what do you actually get
  5. what do you pass in variables

There for small change where components channel names were converted to lowercase. And using “getByName” I think you also had to call them in lowercase. But that was wrong. Now those should be called as they appear in UI. e.g. “Red” instead of “red”. Anyway, this approach will work only in English localization of Photoshop as different languages have different channel names.

1 Like

May I suggest to introduce constants for all default channel names? Then we wouldn’t care what language it is if constants have assigned names based on language

Well, that is what I fixed in DOM. Recently component channels worked only in English. Once Changelog is updated you should see it there.

And of course, you have Document.componentChannels array, and based on document color mode you can tell what index in the array has e.g. green color component in RGB e.g. document.componentChannels[1] is for “Green” channel in RGB.

2 Likes

I have a simple PSD with two layers. I created a channel called “OC_Layer 1”.

image

The code that fails are these two, first with DOM and second with BatchPlay, no success with any of both, you can try it yourself.

// DOM

const channel = app.activeDocument.channels.getByName("OC_Layer 1");

// This is logging null in the console
console.log(channel);

// This of course fails as the channel const is null
await channel.duplicate();

If you try this code yourself, you’ll see that

  1. the code channel.duplicate(); will give you an error as the channel is null. It is not working anymore to get a channel by the name using the .getByName() function

  2. It will give you an error on duplicate function as the channel const is null.

I already tried to use batchPlay to duplicate the channel using this code:

try {
// In targetDoc I use the doc I want to duplicate the channel to, Here I used the second doc as an example
const targetDoc = app.documents[1];

// BatchPlay code to duplicate the channel into the targetDoc
await batchPlay([
            {
              "_obj": "duplicate",
              "_target": [
                {
                  "_ref": "channel",
                  "_enum": "ordinal",
                  "_value": "targetEnum"
                }
              ],
              "to": {
                "_ref": "document",
                "_name": targetDoc
              },
              "name": "OC_Layer 1",
              "_isCommand": true
            }
          ], {})

}catch(e) {
 console.log(e);
}

However this is logging me this error:

Error: NAPI API failure: String expected

Hope this is clear enough, let me know if you need more info Jarda.

Is your batchPlay error due to you passing the whole targetDoc object and not just targetDoc.name perhaps?

1 Like

Indeed the problem with the batchPlay code was that I was passing the whole targetDoc obj instead only the targetDoc.name property. That’s why it was giving me an error.

With a previus function I had with DOM I needed to pass the whole doc into the doc.channel.cuplicate() function to duplicate it successfully, but to solve my DOM issue I went for batchPlay code, however with the batchPlay I need only the name of the document. It works well now, thank you very much you all for your help!

PS. doc.channels.getByName(); still not working on this version though. Even if it is in english, try your self.

I tried that but it works on my machine

Can you please run console.log(ps.app.activeDocument.channels[3].name === "OC_Layer 1") to verify that channel name has no hidden characters?

1 Like

Just tried and it works but only if I do it in the same document.

I found where was the problem, let me explain:

If you have 2 PSD open:

const docA = app.documents[0];
const docB = app.documents[1];

And if you try to get a channel from docA when docA is infrot ( activeDocument ) it works.

const channel = docA.channels.getByName("OC_Layer1");
// This logs the channel object without problem

BUT If you try to use the same code when the docB is the activeDocument it will get null.

So what I did was create a functiuon to bring to the front the document I want to get the channel from and run the getByName() function so the duplicate() function will work. With the Alchemist plugin I got a code for batchPlay to bring into the front the document I want but seems it needs an offset number form the activeDocument to make another document active.

This is the code from Alchemist:

// The 'offset' is the number of documents that the activeDocument needs to displace, e.g. -2 or 2.
await batchPlay(
  [
    {
      "_obj": "select",
      "_target": [
        {
          "_ref": "document",
          "_offset": offset
        }
      ]
    }
  ], {});

So I made this function to make it work:

async function setActiveDocument(doc) {

  let offset = 0;
  const activeDoc = await getDocIdx(app.activeDocument);
  const docIdx = await getDocIdx(doc);
  if (activeDoc < docIdx) {
    offset = docIdx - activeDoc;
  } else {
    offset = docIdx - activeDoc;
  }

  await batchPlay(
    [
      {
        "_obj": "select",
        "_target": [
          {
            "_ref": "document",
            "_offset": offset
          }
        ]
      }
    ], {});
}
  
async function getDocIdx(inputDoc) {
  for (let i = 0; i < app.documents.length; i++) {
    const doc = app.documents[i];
    if (doc.name === inputDoc.name) return i;
  }
}

I couldn’t find a way to make it work with the DOM something like the code bellow, so that’s why I made the function.

app.documents[2].bringToFront();

In resume:
The problem I found is that channels from another PSD cannot be called or get unless it is the activeDocument where the channels are being called, does this makes sense?

Hope this makes sense.

1 Like

Yes, thank you. This is helpful. I will look into how to fix this.

I see that activeDocument is read and write property. So you could do like this:
app.activeDocument = docB; to make document active.

1 Like

That is way easier thank you, don’t know why I didn’t try that before haha, I used to do app.activeDocument with CEP though. Thank you very much for the follow up!

Ok, I was able to find where is the error. I wrote a fix and sent it for review. Reference in batchPlay did not take document reference into consideration.

Thanks for reporting. I can’t tell yet in what PS version this will be fixed… it depends on the review. Please make sure to operate on active document until then.

3 Likes