• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
3

Descriptor-Info

Participant ,
Dec 23, 2016 Dec 23, 2016

Copy link to clipboard

Copied

Hey guys, I wanted to share a little JSX module I made to recursively get all the properties in an ActionDescriptor. It's always been a struggle to read the contents of an Action Descriptor, so I wanted something fast that could give me all this information without having to loop through every property manually.

I've seen many scripts out there trying to accomplish something similar, all of them with different and interesting approaches. I've definitely picked up a lot of ideas from these forums. I wasn't getting what I was looking for unfortunately, so I made my own module. This will mostly be used as a read-only JSON to look for the property that you need.

Here you will find the public repo for the project with all its information. Feel free to bring up ideas, bugs, compatibility issues, etc.

GitHub - JavierAroche/descriptor-info

Here's an example of how to use it.

Usage

descriptorInfo.getProperties( desc );

// Sample code for getting Descriptor properties with getProperties

// Include the descriptorInfo module

#include "~/Development/personal/descriptor-info/jsx/descriptor-info.jsx"

// ActionDescriptor example

var ref = new ActionReference();

ref.putEnumerated( charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );

var desc = executeActionGet(ref);

// Retrieve its properties by running the getProperties function, passing the ActionDescriptor as a param

var descObject = descriptorInfo.getProperties( desc );

JSON object example: GitHub - JavierAroche/descriptor-info - JSON Example

Supported Descriptors

  • DescValueType.BOOLEANTYPE
  • DescValueType.CLASSTYPE
  • DescValueType.DOUBLETYPE
  • DescValueType.ENUMERATEDTYPE
  • DescValueType.INTEGERTYPE
  • DescValueType.LISTTYPE
  • DescValueType.OBJECTTYPE
  • DescValueType.REFERENCETYPE
  • DescValueType.STRINGTYPE
  • DescValueType.UNITDOUBLE
  • DescValueType.ALIASTYPE
  • DescValueType.RAWTYPE

Known Limitations

REFERENCETYPE Descriptors will only return the Descriptor linked, but not it's actual properties. Adding this without properly testing can fall in an endless loop.

RAWTYPE Descriptors, usually labeled "legacyContentData", will return the value as unicode. You will have to parse it separately as the data varies too much.

Hope you guys find this useful and helps you better understand Action Descriptors. Feedback is always appreciated

PS. If you're using my Brackets-to-Photoshop extension, you can use the console.stringify function to print out the JSON descriptor to the console.

// Retrieve its properties by running the getProperties function, passing the ActionDescriptor as a param

var descObject = descriptorInfo.getProperties( desc );

console.stringify( descObject );

TOPICS
Actions and scripting

Views

5.4K

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe
Guide ,
Dec 24, 2016 Dec 24, 2016

Copy link to clipboard

Copied

It does not work in CS6 Windows10.

console.log(descProperties.stringID + ' - ' + err) line console is not defined.

There is nowhere where you are printing the results or reference to Json.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Dec 24, 2016 Dec 24, 2016

Copy link to clipboard

Copied

Hey SuperMerlin​ thanks for trying it out!

Are you using my Brackets-to-Photoshop extension?

GitHub - JavierAroche/brackets-to-photoshop

The Brackets extension has its own internal console module to extend this functionality, as well as its own console in the UI. It uses Adobe's Brackets editor, so if you're using ExtendScript Toolkit then console.log won't work.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Dec 24, 2016 Dec 24, 2016

Copy link to clipboard

Copied

Thanks for the info. As an old age pensioner I am a bit slow on grasping new tech

I have tried but still failed, as can not find where to run the code from within Brackets, I noticed in your notes it said...

"* This extension uses Photoshop's AppleScript API, so it will only work for MacOS users at the moment."

As I am on Windows 10 does this mean I can't use it?

Thanks for your patience!

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Dec 24, 2016 Dec 24, 2016

Copy link to clipboard

Copied

Ah you're on Windows! Yes, unfortunately I haven't implemented the Windows compatibility feature on my brackets extension. Hopefully I'll have some time to do it on January.

You can still use this descriptor-info module in ExtendScript Toolkit. The getProperties function will return an object, so you will need a JSON polyfill to stringify the object. I use this JSON polyifill all the time (Line 17).

https://github.com/JavierAroche/brackets-to-photoshop/blob/master/jsx/Helpers.jsx

Later today, maybe on Monday, I will add a little example to my repo with this polyfill included so you can just pick up the example and run it in ES Toolkit.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Dec 24, 2016 Dec 24, 2016

Copy link to clipboard

Copied

Thanks but I will stick with ESTK as I can get all the details I want.

But it might be useful for a lot of other people!

Keep up the good work Javier.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Dec 24, 2016 Dec 24, 2016

Copy link to clipboard

Copied

Good to see people like you on this forum. I think shortly I should start reading about json. Its style is quite readable, without many unimportant stuff for eyes you're enforced to see in ScriptListener / ActionManager code. Good job Javier!

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
Dec 27, 2016 Dec 27, 2016

Copy link to clipboard

Copied

Thx a lot. I will check it in January. Thanks also for MIT license.

"jam" framework does similar job, but it is under GPL license and GPL is connected with certain things, which I'm not sure.

JSON Action Manager | Tonton Pixel (website is sometimes offline)

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Dec 27, 2016 Dec 27, 2016

Copy link to clipboard

Copied

Thanks but I will stick with ESTK as I can get all the details I want.

But it might be useful for a lot of other people!

Keep up the good work Javier.

Thanks SuperMerlin​! I stopped using ESTK because it was very buggy. Modern browsers offer a lot of great new features, most of them are open source, and Brackets in particular has a pretty good platform to create extensions using Node, which opens up to endless possibilities.

By the way, I added an example JSX to my repo (JSON polyfill included) so you can run it directly in ESTK. If you can/want, give it a try

descriptor-info/example at master · JavierAroche/descriptor-info · GitHub

Good to see people like you on this forum. I think shortly I should start reading about json. Its style is quite readable, without many unimportant stuff for eyes you're enforced to see in ScriptListener / ActionManager code. Good job Javier!

Hey Kukurykus​, thank you! Yes, JSON is definitely something you want to look into. It's unfortunate that functions like JSON.stringify or JSON.parse are not included in ExtendScript. That's why I added a polyfill in the example, so it's easier to preview the returned object.

Thx a lot. I will check it in January. Thanks also for MIT license.

"jam" framework does similar job, but it is under GPL license and GPL is connected with certain things, which I'm not sure.

JSON Action Manager | Tonton Pixel (website is sometimes offline)

Hey Jarda Bereza​, no problem! Yeah, I saw Tonton Pixel's code, and we actually have similar results. The returned object has a different structure though. Chose whichever one works best for you. The good thing is now we have 2 options!

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
Jan 02, 2017 Jan 02, 2017

Copy link to clipboard

Copied

It seems to be very usefull and more readable than Tonton Pixel's code. But you are not solving messed up Char/StringIDs

E.g. grain instead green

"color": {

                "stringID": "color",

                "charID": "Clr ",

                "id": 1131180576,

                "key": 3,

                "type": "DescValueType.OBJECTTYPE",

                "value": {

                    "count": 3,

                    "typename": "ActionDescriptor"

                },

                "object": {

                    "red": {

                        "stringID": "red",

                        "charID": "Rd  ",

                        "id": 1382293536,

                        "key": 0,

                        "type": "DescValueType.DOUBLETYPE",

                        "value": 255

                    },

                    "grain": {

                        "stringID": "grain",

                        "charID": "Grn ",

                        "id": 1198681632,

                        "key": 1,

                        "type": "DescValueType.DOUBLETYPE",

                        "value": 255

                    },

                    "blue": {

                        "stringID": "blue",

                        "charID": "Bl  ",

                        "id": 1114382368,

                        "key": 2,

                        "type": "DescValueType.DOUBLETYPE",

                        "value": 255

                    }

                }

            },

I did some measurements because only with only selected two groups the script was runing 10+ seconds. Which is too long.

Every lines in code has under 20ms except this:

case 'DescValueType.REFERENCETYPE': listArray.push( executeActionGet( listItemValue ) );

Time spend here was 10.3 seconds and this line was performed six times.

I suggest comment this line because it doesn't seems to have valuable info now and it will be lightning fast.

The only difference is, that I don't see "count"

Before/After

2017-01-03_011810.jpg

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Jan 02, 2017 Jan 02, 2017

Copy link to clipboard

Copied

Hey Jarda Bereza​, thanks for taking the time to test this!

But you are not solving messed up Char/StringIDs

I'm only reading what's in the descriptor. I'm not changing any of the information, so it's accurate.

According to Tom Ruark's post here, stringIDToTypeID('grain') == stringIDToTypeID('green'). So it shouldn't be problem if you use the "grain" stringID.

Is there a reason you think I should modify messed up stringIDs? And do you know which other stringIDs are affected?

I suggest comment this line because it doesn't seems to have valuable info now and it will be lightning fast.

Yes, that's a good suggestion. I initially returned the descriptor so I could give the user the ability to use that referenced descriptor and analyze it. But, since this plugin is simply an info getter, it makes sense to not return a descriptor inside the object.

I'll include it in the v1.0.1 release. I'll post here when it's up.

Thanks!

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Jan 03, 2017 Jan 03, 2017

Copy link to clipboard

Copied

v1.0.1 is up! If you're using this JSX, please pull the latest JSX / example

https://github.com/JavierAroche/descriptor-info

Changelog

v1.0.1 (Jan 3 2017)

  • Added optional params to retrieve reference descriptors
  • Updated example to reflect new optional params

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
Jan 03, 2017 Jan 03, 2017

Copy link to clipboard

Copied

Here is mess table: Tonton-Pixel-Photoshop-Scripts/Decision table for conflicting StringIDs in Photoshop.pdf at master ·...

It is from: 2011 so maybe is not complete in 2017. I will check later if we need change it.

Anyway the power of your script is that i can read values and then use it on the next lines in code.

E.g.

var bgColor = descObject.artboard.object.color.object;

colorToHex(bgColor.red.value, bgColor.grain.value, bgColor.blue.value);

Which is awesome human friendly syntax if you compare this with script listener syntax.

But sometimes you will be forced to use unexpected names. This can cause a little confusion.

My next question is...

Is possible get value without writing ".value" ?

bgColor.red

//instead

bgColor.red.value

I can imagine that I will write .value everywhere because this is most important information and code will be a less readable. Maybe prototype._toString could handle this job? Everything else could be same. Also in ExtendScript Toolkit Data Browser would be more readable because you would see "left = 540" instead "left = [object Object] and you don't need go so deep in tree where is "value = 540" and then look above value of which.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Jan 03, 2017 Jan 03, 2017

Copy link to clipboard

Copied

But sometimes you will be forced to use unexpected names. This can cause a little confusion.

Is possible get value without writing ".value" ?

Jarda Bereza​, I see what you're saying on both points. I initially wrote this module to be a read only object. But it would be pretty cool to return a simplified object that you could use in your code.

I've thought about doing this before. Instead of having an object like the one in the repo README, you would get something simplified, like this:

{

    "name": "Background",

    "visible": true,

    "mode": "normal",

    "opacity": 255,

    "layerID": 1,

    "bounds": {

        "top": 0,

        "left": 0,

        "bottom": 2500,

        "right": 1594

    },

    "smartObject": {

        "placed": "rasterizeContent",,

        "documentID": "xmp.did:bfeed619-610f-4c23-9a5d-d03a5d55286e",

        "compsList": { ...

        },

        "linked": false,

        "fileReference": "imac_performance_and_design.psb"

    },

    "targetChannels": [

        {

          "typename": "ActionReference"

        },

        {

          "typename": "ActionReference"

        },

        {

          "typename": "ActionReference"

        }

    ],

    "channelRestrictions": [

        "red",

        "grain",

        "blue"

    ],

    ...

}

I do want to keep the current main functionality though, which is to give you all the properties of the descriptor object: stringID, charID, id, key, type and value. I think that information is also very useful.

"name": {
  "stringID": "name",
  "charID": "Nm ",
  "id": 1315774496,
  "key": 0,
  "type": "DescValueType.STRINGTYPE",
  "value": "Background"
  },

I think what I'll do is rework this module to return a simplified object, like the one I listed above, which would be the default returned object. And, I will add an "extended" flag to the descParams, which will retrieve the full object as it does right now (as listed in the README).

So it would look something like this in your JSX

var descFlags = {

    reference : false,

    extended : true

};

var descObject = descriptorInfo.getProperties( desc, descFlags );

What do you think?

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
Jan 03, 2017 Jan 03, 2017

Copy link to clipboard

Copied

Yes, this solution would be perfect! 🙂

And my code using your "framework" would be readable as never before 🙂

It also could a little bit improve performance if you read hunderds of layers and extended version will be disabled.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Jan 03, 2017 Jan 03, 2017

Copy link to clipboard

Copied

And my code using your "framework" would be readable as never before 🙂

Cool!

I will definitely work on that update and release a v1.0.2 as soon as I get some free time to work on this.

Thanks for trying it out and for the input!

For the messed up charIDs and stringIDs. I might have another flag to resolve those specific issues. I like the idea of delivering exactly what's in the descriptor, but I do want the module to have the flexibility to pass a specific parameter so you can return what you need.

It would look something like this:

var descFlags = { 

    reference : false, 

    extended : true,

    fixIDs : true

}; 

      

var descObject = descriptorInfo.getProperties( desc, descFlags ); 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
Jan 03, 2017 Jan 03, 2017

Copy link to clipboard

Copied

It think fixIDs option would be ok.

I wonder if there is any possibility to get list of all descriptors that can be disassembled.

You can read app preferences, but not all preferences as I know, history states, paths panel, channels pannel, documents... what else?

I am thinking about possibility to more easy way how to get properties.

Something like:

descObject = descriptorInfo.getSelectedLayersProperties( descFlags );

or

decsObject = descriptorInfo.getLayersPropertiesByIndex( [45,20,123], descFlags );

or

decsObject = descriptorInfo.getLayersPropertiesById( [45,20,123], descFlags );

similar for app settings and next frequently used things.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Jan 03, 2017 Jan 03, 2017

Copy link to clipboard

Copied

Hey Jarda Bereza​, I feel like that would deviate a little bit from the module's core functionality.

I do agree that we need an extended Photoshop API. We've actually built our own internal Photoshop API / NPM module at work (with over 100 setter / getter functions), combining Photoshop's JavaScript API and ActionManager code. We made it so it can be used inside Generator, in a CEP Panel, or in a standalone node module that connects to Photoshop. But unfortunately it's internal only

We have function such as:

  • getDocumentTree (retrieves the entire document tree, including contents inside nested smart objects)
  • getOpenDocuments
  • getCurrentDocumentInfo
  • getCurrentDocumentLayers
  • getSmartObjectFilename
  • removeLayerById
  • selectLayerById
  • getRulerUnits
  • setSnapTransformsToPixelGrid
  • ...

Which makes it super useful to not have to repeat code and maintain.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Jan 13, 2017 Jan 13, 2017

Copy link to clipboard

Copied

Hey guys,

I just realized v1.0.2 of my descriptor-info JSX module. I've simplified the object returned to make it more useable. I've updated the object examples in the README to show the new changes.

Please check it out, if you have some time.

https://github.com/JavierAroche/descriptor-info

v1.0.2 (Jan 13 2017)

  • Added optional params to retrieve extended descriptor information
  • Updated example to reflect new optional params

Jarda Bereza​, let me know what you think!

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
Jan 14, 2017 Jan 14, 2017

Copy link to clipboard

Copied

This is pretty good 🙂

I will rewrite my old code.

"desc.bounds.top" will be better than

"desc['bounds'][1][1]['top'][1][1]"

and still faster than classic DOM.

Maybe JAM framework can also do that but I am not able figure it. If I turn off "parse friednly" i see

desc.boundsNoMask.<object>.rectangle.top But I am not able get inside <object>

I think reference flag is not self-explaning. I am not sure if true means off or on.

May next Idea is create some dictionary which will show you tree differences between Photoshop version. It could be somehow automated and it would compare JSON trees. It would open one PSD in different PS version and test same layer JSON trees. If you have Cloud subscription you have access to all version from CS6 to CC2017.

E.g. CS6 doesn't have "width" and "height" in "bounds" But I am not sure how output should look like. I really like this webpage: http://caniuse.com/#search=json 😄

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Jan 14, 2017 Jan 14, 2017

Copy link to clipboard

Copied

Thanks Jarda Bereza​!

Maybe JAM framework can also do that but I am not able figure it. If I turn off "parse friednly" i see

desc.boundsNoMask.<object>.rectangle.top But I am not able get inside <object>

I've only used the JAM framework to read the object, not use its properties. So I've never dealt with the structure of the object.

I think reference flag is not self-explaning. I am not sure if true means off or on.

This is my current description for the reference flag

  • Optional @flag {Boolean} reference - return reference descriptors. Could slightly affect speed.

Any suggestions as to what would make it a little more clear?

May next Idea is create some dictionary which will show you tree differences between Photoshop version. It could be somehow automated and it would compare JSON trees. It would open one PSD in different PS version and test same layer JSON trees. If you have Cloud subscription you have access to all version from CS6 to CC2017.

That would be interesting. Adobe has changed their descriptors. We don't have a cloud subscription at work, so I can't test all of them But it would be interesting to see.

E.g. CS6 doesn't have "width" and "height" in "bounds" But I am not sure how output should look like. I really like this webpage: http://caniuse.com/#search=json 😄

This module should just read whatever is in the descriptor, so if width and height in bounds are not there, it just won't show them.

I don't think JSON compatibility is an issue here. Using the JSON polyfill I included in the example you should be ok, it's plain JavaScript.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
Jan 14, 2017 Jan 14, 2017

Copy link to clipboard

Copied

Any suggestions as to what would make it a little more clear?

  • Optional @flag {Boolean} reference - if value is false then return reference descriptors. Could slightly affect speed. In some cases 10 seconds per descriptor.

Maybe I will try to compare property trees between PS versions in future. But I am not sure what is best a most usefull way, to show results. Can-I-use link was one way how to interpret these results. It wasn't about polyfill.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Jan 14, 2017 Jan 14, 2017

Copy link to clipboard

Copied

  • Optional @flag {Boolean} reference - if value is false then return reference descriptors. Could slightly affect speed. In some cases 10 seconds per descriptor.

If the reference flag is true, it will return de descriptor inside the reference object. So it will do a "executeActionGet( ref )", which is why it returns a descriptor, and could take a little longer.

If the reference flag is false, it will only return the reference object, which means if you want to use that reference later in your code, you'll have to do the "executeActionGet( ref )" by yourself. That's why it might be a little faster.

Maybe I will try to compare property trees between PS versions in future. But I am not sure what is best a most usefull way, to show results. Can-I-use link was one way how to interpret these results. It wasn't about polyfill.

Ah got it. I use this little github project to easily read my JSON objects. I find it super useful.

http://warfares.github.io/pretty-json/

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Jun 08, 2017 Jun 08, 2017

Copy link to clipboard

Copied

Hi JavierAroche​

Thank for your work. I can't get value of property of descObject by access descObject[property]

var descObject = descriptorInfo.getProperties( desc, descFlags );

JSON.stringify(descObject) ===> Failed here

==> so I switch to:

for (var property in descObject) {

              if (descObject.hasOwnProperty(property)) {

                  // do stuff

                  i++;

                  try {

                    arr.push(i+': '+(property)); // this is OK, I can get all property of descObject

                    //descObject[property] //this not OK, I can't get the value of property

                  }catch(e){

                    continue;

                  }

              }

          }

Do you have any advise?

Thanks,

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Jun 09, 2017 Jun 09, 2017

Copy link to clipboard

Copied

LATEST

Hi JavierAroche​

Sorry, look like issue came from psd file not from the code. If I use the code with simple and clean PSD, it is OK but for complex (that I'm not sure if layer name contain unicode character or any else...) code will not working normally. It's still show information to console but not write to text file as I expect.

Continue debugging.

Thanks,

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines