32 Replies Latest reply on Mar 11, 2018 1:55 PM by Kukurykus

    Modifying Levels Adjustment Layer?

    jakebend Level 1

      I'm using PS CS6 x64 for Win7. I'm trying to figure out how to change the values on a "levels" adjustment layer using javascript. I can't find any info anywhere. Oddly, the scripting listener doesn't seem to pick up modifications to the adjustment layer.

      Anybody have any luck with this?

       

      (Edit: more info)

        • 1. Re: Modifying Levels Adjustment Layer?
          c.pfaffenbichler Level 9

          Why, what are you trying to achieve exactly?

           

          Edit: To get an idea about the complexity of evaluating the values in an existing Adjustment Layer (Curves in this case, though) check out

          http://ps-scripts.com/bb/viewtopic.php?f=9&t=3588&p=16244&hilit=curves+rawdata&sid=9a394db e6231de5114afed82e2e8c513#p16244

          • 2. Re: Modifying Levels Adjustment Layer?
            jakebend Level 1

            I need to make a non-destructive level adjustment to multiple layers in a specific layerset. The reason for scripting it is because it's part of a toolset for performing specific (repetative) mathematical adjustments to images. It's all part of a toolset I'm developing for physically conservative rendering techniques.

            The hacky workaround I'm using is to use Applescript to invoke a PS action that makes the adjustment I need, but I hate this solution.

            I could theoretically use curves instead of levels, but part of the adjustment is going from gamma to linear space (but still working in sRGB). That would mean I'd either need to set up a more complicated curve, or add an additional "exposure" adjustment layer. That's why I'm hoping to keep the levels adjustment layer.

            I haven't quite digested the information in that curves example. I'll look into it.

            • 3. Re: Modifying Levels Adjustment Layer?
              Michael L Hale Level 5

              The problem with both levels and curve adjustment layers is the settings are stored in a format that is not easy to read. Of the two levels is easier so if levels does all you need I would stick that using levels.

               

              Are you willing to use something that only works for RGB documents? Will just the master settings be enough or do you need to set each channel. Do you have any idea of how you would like the data from the setting stored. A large group of variables, an Array, or a custom object?

              • 4. Re: Modifying Levels Adjustment Layer?
                DBarranca Level 4

                As a side note to the other answers, it's true that ScriptingListener sometimes misses to record the ActionManager code relative to changes into an Adjustment Layer.

                Sometimes not.

                Sometimes you've to make active a different layer in order for SL to output something. Sometimes you reboot and it works the first go.

                (At least that's what I remember from when I had to deal with such things)

                 

                Davide

                www.davidebarranca.com

                • 5. Re: Modifying Levels Adjustment Layer?
                  jakebend Level 1

                  Michael,

                  The adjustment is specifically for RGB. Invividual channel manipulation isn't necessary, and master settings are all I need access to. I don't have a preference on how the data is stored. Why? how much data are we talking?

                  • 6. Re: Modifying Levels Adjustment Layer?
                    jakebend Level 1

                    Davide,

                    That's interesting information. I'll try rebooting.

                    • 7. Re: Modifying Levels Adjustment Layer?
                      Michael L Hale Level 5

                      Here is one way. If you don't need to deal with single channels you can delete the lines that contain channel#. You could also make dealing with the data easier by skipping the comp object and doing something like levelsOptions.inBlack = getShortFromStream( data, 2 );

                      var ref = new ActionReference();
                      ref.putEnumerated( charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") ); 
                      var data = executeActionGet(ref).getList(charIDToTypeID("Adjs")).getObjectValue(0).getData( stringIDToTypeID( 'legacyContentData' ) );
                      var check = getShortFromStream( data, 0 );
                      if(check != 2 ) throwError;// if not 2 then something is wrong
                      var levelsOptions = {};
                      levelsOptions.comp = {};
                      levelsOptions.channel1 = {};
                      levelsOptions.channel2 = {};
                      levelsOptions.channel3 = {};
                      levelsOptions.comp.inBlack = getShortFromStream( data, 2 );
                      levelsOptions.comp.inWhite = getShortFromStream( data, 4 );
                      levelsOptions.comp.outBlack = getShortFromStream( data, 6 );
                      levelsOptions.comp.outWhite = getShortFromStream( data, 8 );
                      levelsOptions.comp.gamma = getShortFromStream( data, 10 )/100;
                      levelsOptions.channel1.inBlack = getShortFromStream( data, 12 );
                      levelsOptions.channel1.inWhite = getShortFromStream( data, 14 );
                      levelsOptions.channel1.outBlack = getShortFromStream( data, 16 );
                      levelsOptions.channel1.outWhite = getShortFromStream( data, 18 );
                      levelsOptions.channel1.gamma = getShortFromStream( data, 20 )/100;
                      levelsOptions.channel2.inBlack = getShortFromStream( data, 22 );
                      levelsOptions.channel2.inWhite = getShortFromStream( data, 24 );
                      levelsOptions.channel2.outBlack = getShortFromStream( data, 26 );
                      levelsOptions.channel2.outWhite = getShortFromStream( data, 28 );
                      levelsOptions.channel2.gamma = getShortFromStream( data, 30 )/100;
                      levelsOptions.channel3.inBlack = getShortFromStream( data, 32 );
                      levelsOptions.channel3.inWhite = getShortFromStream( data, 34 );
                      levelsOptions.channel3.outBlack = getShortFromStream( data, 36 );
                      levelsOptions.channel3.outWhite = getShortFromStream( data, 38 );
                      levelsOptions.channel3.gamma = getShortFromStream( data, 40 )/100;
                      
                      
                      function getShortFromStream( stream, pointer ) {
                          var hi, low;
                          hi = stream.charCodeAt( pointer ) << 8 ;
                          low = stream.charCodeAt( pointer + 1 );
                          return hi + low;
                       };
                      
                      1 person found this helpful
                      • 8. Re: Modifying Levels Adjustment Layer?
                        DBarranca Level 4

                        Another route could be this function that lets you specify inputWhite, inputBlack, gamma, outputWhite, outputBlack

                         

                        setLevelAdj = function(inBlack, inWhite, gamma, outBlack, outWhite) {
                          var d, d1, d2, l, l1, l2, r, r1, s2t;
                          if (outBlack == null) {
                            outBlack = 0;
                          }
                          if (outWhite == null) {
                            outWhite = 255;
                          }
                          s2t = function(s) {
                            return app.stringIDToTypeID(s);
                          };
                          d = new ActionDescriptor();
                          r = new ActionReference();
                          r.putEnumerated(s2t('adjustmentLayer'), s2t('ordinal'), s2t('targetEnum'));
                          d.putReference(s2t('target'), r);
                          d1 = new ActionDescriptor();
                          d1.putEnumerated(s2t('presetKind'), s2t('presetKindType'), s2t('presetKindCustom'));
                          l = new ActionList();
                          d2 = new ActionDescriptor();
                          r1 = new ActionReference();
                          r1.putEnumerated(s2t('channel'), s2t('channel'), s2t('composite'));
                          d2.putReference(s2t('channel'), r1);
                          l1 = new ActionList();
                          l1.putInteger(inBlack);
                          l1.putInteger(inWhite);
                          d2.putList(s2t('input'), l1);
                          d2.putDouble(s2t('gamma'), gamma);
                          l2 = new ActionList();
                          l2.putInteger(outBlack);
                          l2.putInteger(outWhite);
                          d2.putList(s2t('output'), l2);
                          l.putObject(s2t('levelsAdjustment'), d2);
                          d1.putList(s2t('adjustment'), l);
                          d.putObject(s2t('to'), s2t('levels'), d1);
                          return executeAction(s2t('set'), d, DialogModes.NO);
                        };
                        

                         

                        Davide

                        • 9. Re: Modifying Levels Adjustment Layer?
                          Michael L Hale Level 5

                          I may have mis-understood and made things more complex than needed. I thought if the op wanted to modify an existing levels adjustment layer they would want to get the existing settings.

                          • 10. Re: Modifying Levels Adjustment Layer?
                            DBarranca Level 4

                            Mike,

                            how have you been able to get to that, does it comes from the PS file formats specs? (i.e.saved presets for Layers adjustments)

                            I've never been confortable with data stream, yet I'm willing to learn.

                            Well done!

                             

                            Davide

                            • 11. Re: Modifying Levels Adjustment Layer?
                              jakebend Level 1

                              That's exactly what I'm looking for. Thank you Davide.

                              • 12. Re: Modifying Levels Adjustment Layer?
                                Michael L Hale Level 5

                                First I wrote the data to a file after getting it from the layer descriptor. I then used a hexeditor to compare that file to the levels .alv file spec. It looked the same so I just followed the structure.

                                 

                                If you want to try working with binary data like this I strongly suggest that you do not run/test the code using ESTK. It will hang and you will have to close ESTK and Photoshop. I use ESTK most of the time when I am working on a script because of it's features. But after loosing work countless times because of a hang I now use a different editor and test run the script using the Photoshop File-Scripts-Browse menuItem.

                                • 13. Re: Modifying Levels Adjustment Layer?
                                  jakebend Level 1

                                  This is amazing. Where can I find documentation for this? I can't find anything like this in the SDK, and the scripting guides are not super useful.

                                  • 14. Re: Modifying Levels Adjustment Layer?
                                    DBarranca Level 4

                                    Mike can explain it better, but on my side it's mostly trial and error.

                                    For instance we've got a topic (I guess on PS-Scripts) where I was having a problem setting a Hue/Saturation adjustment layer.

                                    That's because newer versions of PS use a "legacyContentData" stream and not a descriptor with explicit slots for, say, hue, sat or whatever. (that's the why PS CS3 is super-handy when it comes to ScriptingListener)

                                     

                                    Turns out that the legacyContentData content was the same of a Hue/Sat preset file saved on disk - which is documented in the Photoshop File Formats pdf. So you can read bit after bit there, in order to retrieve the specified values - something about can be read here.

                                     

                                    Mike, can I ask you how did you write the descriptor to a file (I guess is something related to data streams, which I'm not - yet! - familiar with)?

                                     

                                    Davide

                                    • 15. Re: Modifying Levels Adjustment Layer?
                                      Michael L Hale Level 5

                                      I guess is something related to data streams

                                      It's really more about just writing to a file. It is true that it is a data stream but so is writing a text file. Action Descriptors have a toStream() and fromStream() method but those are not needed for this. Those methods are used to convert the entire descriptor between an object and binary data.

                                       

                                      We could write the legacyContentData to a file and then read the settings from that file. You would not need to keep track of the stream pointer that way. But as we don't need to keep the file it is better( and faster ) to read the settings from the variable.

                                      var ref = new ActionReference();
                                      ref.putEnumerated( charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") ); 
                                      var data = executeActionGet(ref).getList(charIDToTypeID("Adjs")).getObjectValue(0).getData( stringIDToTypeID( 'legacyContentData' ) );
                                      var datFile = new File('~/desktop/levlelsTest.dat');
                                      datFile.encoding = 'BINARY';
                                      datFile.open('w');
                                      datFile.write(data);
                                      datFile.close();
                                      
                                      • 16. Re: Modifying Levels Adjustment Layer?
                                        jakebend Level 1

                                        Wow.

                                        Thanks Michael and Davide, this is amazing.

                                        • 17. Re: Modifying Levels Adjustment Layer?
                                          photogyulai Level 1

                                          I guess i was lucky and after several try the script listener did pick up the settings of the levels adjustment layer setting.

                                          I saw some code up here, but it didnt worked for me (maybe cos different version?! i dont know)


                                          So here is the result >>

                                          (i put some comment where the adjustable variables are)

                                           

                                          var idsetd = charIDToTypeID( "setd" );

                                              var desc5 = new ActionDescriptor();

                                              var idnull = charIDToTypeID( "null" );

                                                  var ref2 = new ActionReference();

                                                  var idAdjL = charIDToTypeID( "AdjL" );

                                                  var idOrdn = charIDToTypeID( "Ordn" );

                                                  var idTrgt = charIDToTypeID( "Trgt" );

                                                  ref2.putEnumerated( idAdjL, idOrdn, idTrgt );

                                              desc5.putReference( idnull, ref2 );

                                              var idT = charIDToTypeID( "T   " );

                                                  var desc6 = new ActionDescriptor();

                                                  var idpresetKind = stringIDToTypeID( "presetKind" );

                                                  var idpresetKindType = stringIDToTypeID( "presetKindType" );

                                                  var idpresetKindCustom = stringIDToTypeID( "presetKindCustom" );

                                                  desc6.putEnumerated( idpresetKind, idpresetKindType, idpresetKindCustom );

                                                  var idAdjs = charIDToTypeID( "Adjs" );

                                                      var list1 = new ActionList();

                                                          var desc7 = new ActionDescriptor();

                                                          var idChnl = charIDToTypeID( "Chnl" );

                                                              var ref3 = new ActionReference();

                                                              var idChnl = charIDToTypeID( "Chnl" );

                                                              var idChnl = charIDToTypeID( "Chnl" );

                                                              var idCmps = charIDToTypeID( "Cmps" );

                                                              ref3.putEnumerated( idChnl, idChnl, idCmps );

                                                          desc7.putReference( idChnl, ref3 );

                                                          var idInpt = charIDToTypeID( "Inpt" );

                                                              var list2 = new ActionList();

                                                              list2.putInteger( 0 );     // Black point

                                                              list2.putInteger( 240 );  // White point

                                                          desc7.putList( idInpt, list2 );

                                                          var idGmm = charIDToTypeID( "Gmm " );

                                                          desc7.putDouble( idGmm, 1.30 );  //Gamma point

                                                      var idLvlA = charIDToTypeID( "LvlA" );

                                                      list1.putObject( idLvlA, desc7 );

                                                  desc6.putList( idAdjs, list1 );

                                              var idLvls = charIDToTypeID( "Lvls" );

                                              desc5.putObject( idT, idLvls, desc6 );

                                          executeAction( idsetd, desc5, DialogModes.NO );

                                          • 18. Re: Modifying Levels Adjustment Layer?
                                            Kukurykus Adobe Community Professional

                                            That's probably bug. To force ScriptListener to record changes made to Adjustment Layer you have for example to choose / create other layer. When you then open SL log you will find 2 new records while the 1st refers changes to Adjustment Layer.

                                            • 19. Re: Modifying Levels Adjustment Layer?
                                              Kukurykus Adobe Community Professional

                                              It's something I couldn't figure out long time with Adjustement Layer what I find now Michael L Hale did with no problem. I wonder what he used in his research to find stringIDToTypeID('legacyContentData') in that time? Who may give me answer?

                                              • 20. Re: Modifying Levels Adjustment Layer?
                                                Kukurykus Adobe Community Professional

                                                If you want to try working with binary data like this I strongly suggest that you do not run/test the code using ESTK. It will hang and you will have to close ESTK and Photoshop.

                                                 

                                                For those having same problem as Michael L Hale while don't want to use other editor, put any code reading binaries into:

                                                 

                                                (function(){
                                                    //    his/your script
                                                })()
                                                
                                                • 21. Re: Modifying Levels Adjustment Layer?
                                                  JJMack Most Valuable Participant

                                                  I find it hard to find out many things about many thing when I come to Adobe Scripting.  Adobe does make Changes to Photoshop Script. Adobe added bugs of fail to add support for new features like new interpolation methods setting the brake existing Scripts.  And I see users in here use new features.  You seem to need to manually compare  Adobe JavaScript references manual to see what has been added.  Compare CC 2014 with CC 2015 JavaScript reference for example Application methods

                                                  AddedCC2015.jpg

                                                  I also saw some code the Tom Ruark posted using doProcess in this forum. So I tried it in CC 2018 and there seem to be a problem in doProcess in CC 2018 that may be new  I no longer have CC 2015, CC 2015.5 and CC 2017 installed.

                                                   

                                                  Here is Tom's code with a little extra code thrown in.

                                                  /* The basic part of this script was posted by Tom Ruark to show how hard it is to catch ESC he wrote
                                                  "Depending on your operation it is difficult to capture the ESC key however. Your mileage may vary"
                                                  
                                                  
                                                  I had to try many many times to see ESC triger DoIt function's Catch Alert messages.
                                                  However doProgressSubTask did return the DoIt function failed when ESC was used and doProgressSubTask 
                                                  caught ESC. So where User use the ESC key gets cough can vary and what is done can vary. For when the 
                                                  DoIt function did catch the user cancelled it message that fact but took no action to return that fact 
                                                  so the script keep on adding layers after I dismissed the DoIT message user cancelled.
                                                  
                                                  
                                                  As Tom wrote your mileage may vary so keep hitting the ESC the script may be able to be stopped else where 
                                                  where ESC will not be ignored or just noted. 
                                                  
                                                  
                                                  Note: doProcess, doForceProcess and doProgressSubTask seems to have been add to Photoshop Scripting in CC 2015 
                                                  
                                                  
                                                  DoProcess does not seem to work correctly in CC 2018 if the script is run when there is no open document
                                                  in CC 2018. A new document will be opened and layers will be added. However, no progress bar will be displayed. 
                                                  DoForcedProcess Does display a progress bar. I no longer have cc 2015, cc 2015.5 or CC 2017 installed to test 
                                                  with they have many bugs perhaps Adobe will fix CC 2018. 
                                                   */
                                                  var d;
                                                  //if (CheckVersion(16)) doForcedProgress("Testing", "Testing()");
                                                  if (CheckVersion(16)) doProgress("Testing", "Testing()"); // this waits 3 or so seconds before showing
                                                  //////////////////////////////////////////////////////////////////////////////////////////////////////////////
                                                  function Testing() {
                                                      try {
                                                          if (documents.length == 0)
                                                              d = documents.add();
                                                          else
                                                              d = activeDocument;
                                                          var keepGoing = true;
                                                          for (var i = 0; i < 100 && keepGoing; i++) {
                                                              keepGoing = doProgressSubTask(i, 100, "DoIt()");
                                                           }
                                                          if (!keepGoing)
                                                              alert("User canceled keepGoing=" + keepGoing);
                                                      } catch(e) {
                                                          alert("Testing: " + e);
                                                      }
                                                  }
                                                  function DoIt() {
                                                      try {
                                                          d.artLayers.add();
                                                      }
                                                      catch(e) {
                                                          alert("DoIt: " + e);
                                                      }
                                                  }
                                                  // CheckVersion
                                                  function CheckVersion(PSV) {
                                                  var numberArray = version.split(".");
                                                  if ( numberArray[0] < PSV ) {
                                                  alert( "You must use Photoshop " + PSV + " or later to run this script!" );
                                                  return false;
                                                  }
                                                  else return true;
                                                  }
                                                  
                                                  • 22. Re: Modifying Levels Adjustment Layer?
                                                    Kukurykus Adobe Community Professional

                                                    Thx for reply & script but I asked of stringIDToTypeID('legacyContentData') and don't see anything with progressBar in here.

                                                    • 23. Re: Modifying Levels Adjustment Layer?
                                                      r-bin Level 4

                                                      Kukurykus 

                                                       

                                                      It's something I couldn't figure out long time with Adjustement Layer what I find now https://forums.adobe.com/people/Michael+L+Hale did with no problem. I wonder what he used in his research to find stringIDToTypeID('legacyContentData') in that time? Who may give me answer?

                                                       

                                                       

                                                      Will help?

                                                       

                                                      ////////////////////////////////////////////////////////////////////////////////////////////
                                                      function edit_levels(l0,gl,l1,l2,l3, r0,gr,r1,r2,r3, g0,gg,g1,g2,g3, b0,gb,b1,b2,b3, k0,gk,k1,k2,k3, dlg)
                                                          {
                                                          try { 
                                                              var desc1 = new ActionDescriptor();
                                                              var ref = new ActionReference();
                                                          
                                                              ref.putEnumerated( charIDToTypeID( "AdjL" ), charIDToTypeID( "Ordn" ), charIDToTypeID( "Trgt" ) );
                                                          
                                                              desc1.putReference( charIDToTypeID( "null" ), ref );
                                                          
                                                              var desc2 = new ActionDescriptor();
                                                          
                                                              var list1 = new ActionList();
                                                      
                                                              function set_chnl(name, x0,gm,x1, y0,y1)
                                                                  {       
                                                                  var desc = new ActionDescriptor();
                                                      
                                                                  var ref = new ActionReference();
                                                                  ref.putEnumerated( charIDToTypeID( "Chnl" ), charIDToTypeID( "Chnl" ), charIDToTypeID( name ) );
                                                      
                                                                  desc.putReference( charIDToTypeID( "Chnl" ), ref );
                                                      
                                                                  var list2 = new ActionList();
                                                                  list2.putInteger( x0 );
                                                                  list2.putInteger( x1 );
                                                                  desc.putList( charIDToTypeID( "Inpt" ), list2 );
                                                                  desc.putDouble( charIDToTypeID( "Gmm " ), gm );
                                                      
                                                                  var list3 = new ActionList();
                                                                  list3.putInteger( y0 );
                                                                  list3.putInteger( y1 );
                                                                  desc.putList( charIDToTypeID( "Otpt" ), list3 );
                                                      
                                                                  list1.putObject( charIDToTypeID( "LvlA" ), desc );
                                                      
                                                                  list2 = null;
                                                                  list3 = null;
                                                                  ref   = null;
                                                                  desc  = null;
                                                                  }
                                                      
                                                              set_chnl("Cmps", l0,gl,l1,l2,l3);
                                                      
                                                              if (app.activeDocument.mode == DocumentMode.RGB)
                                                                  {
                                                                  if (r0 != undefined) set_chnl("Rd  ", r0,gr,r1,r2,r3);
                                                                  if (g0 != undefined) set_chnl("Grn ", g0,gg,g1,g2,g3);
                                                                  if (b0 != undefined) set_chnl("Bl  ", b0,gb,b1,b2,b3);
                                                                  }
                                                              else if (app.activeDocument.mode == DocumentMode.CMYK)
                                                                  {
                                                                  if (r0 != undefined) set_chnl("Cyn ", r0,gr,r1,r2,r3);
                                                                  if (g0 != undefined) set_chnl("Mgnt", g0,gg,g1,g2,g3);
                                                                  if (b0 != undefined) set_chnl("Yllw", b0,gb,b1,b2,b3);
                                                                  if (k0 != undefined) set_chnl("Blck", k0,gk,k1,k2,k3);
                                                                  }
                                                      
                                                              desc2.putList( charIDToTypeID( "Adjs" ), list1 );
                                                      
                                                              desc1.putObject( charIDToTypeID( "T   " ), charIDToTypeID("Lvls"), desc2 );
                                                          
                                                              if (executeAction( charIDToTypeID( "setd" ), desc1, dlg==false?DialogModes.NO:DialogModes.ALL )) return true;
                                                      
                                                              else return false;
                                                              }
                                                          catch (e) { _alert(e); throw(e); } 
                                                          }
                                                      
                                                      ////////////////////////////////////////////////////////////////////////////////////////////
                                                      function get_short(s, len)
                                                          {
                                                          try { 
                                                              if (len == undefined) len = 1;
                                                      
                                                              var ret = [];
                                                      
                                                              for (var i = 0; i < 2*len; i += 2)
                                                                  {
                                                                  var c0 = s.charCodeAt(0+i);
                                                                  var c1 = s.charCodeAt(1+i);
                                                      
                                                                  var val = c1 + 256*c0;
                                                                  
                                                                  if (c0 & 0x80) val = -(0xFFFF - val + 1);
                                                                  
                                                                  ret.push(val);
                                                                  }
                                                      
                                                              if (len == 1) return ret[0];
                                                      
                                                              return ret;
                                                              }
                                                          catch (e) { _alert(e);  } 
                                                          }
                                                      
                                                      ////////////////////////////////////////////////////////////////////////////////////////////
                                                      function get_adjustment_rawdata(id)
                                                          {
                                                          return get_prop_value("layer", id, "adjustment", 0, "legacyContentData");
                                                          }
                                                      
                                                      ////////////////////////////////////////////////////////////////////////////////////////////
                                                      function get_levels(id)
                                                          {
                                                          try { 
                                                              var x = get_adjustment_rawdata(id);
                                                      
                                                              var ret = 
                                                                  [
                                                                  get_short(x.substr(2)), 
                                                                  get_short(x.substr(10))/100,
                                                                  get_short(x.substr(4)),
                                                                  get_short(x.substr(6)),
                                                                  get_short(x.substr(8)),
                                                                  ];
                                                      
                                                              return ret;
                                                              }
                                                          catch (e) {_alert(e); return null; } 
                                                          }
                                                      

                                                       

                                                      UPD.

                                                       

                                                      function get_prop_value(class_key, id, prop_key)
                                                          {
                                                          try
                                                              {
                                                              if (typeof(class_key) == "string") class_key = stringIDToTypeID(class_key);
                                                              if (typeof(prop_key)  == "string") prop_key  = stringIDToTypeID(prop_key);
                                                      
                                                              var r = new ActionReference();    
                                                      
                                                              if (prop_key != undefined) r.putProperty(charIDToTypeID("Prpr"), prop_key);    
                                                      
                                                              if (id == undefined || id == null) r.putEnumerated(class_key, charIDToTypeID("Ordn"), charIDToTypeID("Trgt"));
                                                              else if (typeof(id) == "string")   r.putName(class_key, id);
                                                              else                               r.putIdentifier(class_key, id);
                                                      
                                                              var desc;
                                                      
                                                              if (prop_key == undefined)
                                                                  {
                                                                  try { return executeActionGet(r); } catch (e) { return undefined; }
                                                                  }
                                                      
                                                              try { desc = executeActionGet(r); } catch (e) { return undefined; }     
                                                      
                                                              if (!desc.hasKey(prop_key)) return undefined;
                                                      
                                                              var ret = get_value(desc, prop_key);
                                                      
                                                              for (var i = 3; i < arguments.length; i++) 
                                                                  if (arguments[i] != undefined) ret = get_value(ret, arguments[i]);  
                                                      
                                                              return ret;
                                                      
                                                              function get_type(obj, key)
                                                                  {
                                                                  try 
                                                                      {
                                                                      if (obj == undefined) return undefined;            
                                                      
                                                                      if (typeof(key) == "string") key = stringIDToTypeID(key);
                                                              
                                                                      switch (obj.typename)
                                                                          {
                                                                          case "ActionDescriptor":  
                                                                          case "ActionList"      : return obj.getType(key);
                                                              
                                                                          case "ActionReference" : return obj.getForm();
                                                                          }
                                                                      }
                                                                  catch (e) { throw(e); }
                                                                  }
                                                              
                                                              function get_value(obj, key)
                                                                  {
                                                                  try 
                                                                      {
                                                                      if (obj == undefined) return undefined;            
                                                      
                                                                      if (typeof(key) == "string") key = stringIDToTypeID(key);
                                                              
                                                                      switch (obj.typename)
                                                                          {
                                                                          case "ActionDescriptor":  
                                                                          case "ActionList"      : return get_desc_value(obj, key);
                                                              
                                                                          case "ActionReference" : return get_ref_value(obj);
                                                                          }
                                                                      }
                                                                  catch (e) { throw(e); }
                                                                  }
                                                              
                                                              function get_desc_value(d, key)
                                                                  {
                                                                  try 
                                                                      {
                                                                      if (d == undefined) return undefined;            
                                                      
                                                                      if (typeof(key) == "string") key = stringIDToTypeID(key);
                                                              
                                                                      var val; 
                                                      
                                                                      if (d instanceof ActionDescriptor && !d.hasKey(key)) return undefined;
                                                      
                                                                      else if (d instanceof ActionList && key >= d.count) return undefined;
                                                      
                                                                      var type = d.getType(key);
                                                              
                                                                      switch (type) 
                                                                          {
                                                                          case DescValueType.ALIASTYPE:        val = d.getPath(key);             break;
                                                                          case DescValueType.BOOLEANTYPE:      val = d.getBoolean(key);          break;
                                                                          case DescValueType.CLASSTYPE:        val = d.getClass(key);            break;
                                                                          case DescValueType.DOUBLETYPE:       val = d.getDouble(key);           break;  
                                                                          case DescValueType.INTEGERTYPE:      val = d.getInteger(key);          break;
                                                                          case DescValueType.LISTTYPE:         val = d.getList(key);             break;
                                                                          case DescValueType.RAWTYPE:          val = d.getData(key);             break;
                                                                          case DescValueType.STRINGTYPE:       val = d.getString(key);           break;
                                                                          case DescValueType.LARGEINTEGERTYPE: val = d.getLargeInteger(key);     break;
                                                                          case DescValueType.REFERENCETYPE:    val = d.getReference(key);        break;
                                                                          case DescValueType.OBJECTTYPE:       val = d.getObjectValue(key);      break;
                                                                          case DescValueType.UNITDOUBLE:       val = d.getUnitDoubleValue(key);  break;
                                                                          case DescValueType.ENUMERATEDTYPE:   val = d.getEnumerationValue(key); break;
                                                                          }
                                                              
                                                                      return val;
                                                                      }
                                                                  catch (e) { throw(e); }
                                                                  }
                                                              
                                                              function get_ref_value(r)
                                                                  {
                                                                  try 
                                                                      {
                                                                      var val; 
                                                              
                                                                      switch (r.getForm())
                                                                          {
                                                                          case ReferenceFormType.CLASSTYPE:  val = r.getDesiredClass();    break;
                                                                          case ReferenceFormType.IDENTIFIER: val = r.getIdentifier();      break;
                                                                          case ReferenceFormType.INDEX:      val = r.getIndex();           break;
                                                                          case ReferenceFormType.NAME:       val = r.getName();            break;
                                                                          case ReferenceFormType.OFFSET:     val = r.getOffset();          break;
                                                                          case ReferenceFormType.ENUMERATED: val = r.getEnumeratedValue(); break;
                                                                          case ReferenceFormType.PROPERTY:   val = r.getProperty();        break;  
                                                                          }
                                                              
                                                                      return val;
                                                                      }
                                                                  catch (e) { throw(e); }
                                                                  }
                                                              }   
                                                          catch(e) { _alert(e); }  
                                                          }
                                                      
                                                      • 24. Re: Modifying Levels Adjustment Layer?
                                                        Kukurykus Adobe Community Professional

                                                        Thank you for script. That will be useful for sure, but I asks how to get to know that: stringIDToTypeID('legacyContentData') exists. I mean what code I have to write to get to know there's something like it in Action Manager? I see your UPDATE!

                                                        • 25. Re: Modifying Levels Adjustment Layer?
                                                          JJMack Most Valuable Participant

                                                          I was comment on what you wrote:

                                                           

                                                          " I wonder what he used in his research to find"

                                                           

                                                          Unfortunately he is no longer with us so we will never know what resources he used.  I fine Photoshop scripting resource are to come by and what there is not always correct. I do not know JavaScript but I do know the implementation Adobe uses is very old and is in their plug-in  “ScriptingSupport.8li” which varies from release to release some better than others.

                                                          • 26. Re: Modifying Levels Adjustment Layer?
                                                            r-bin Level 4

                                                            I do not understand. The get_adjustment_rawdata (id) function is not what you want?

                                                            • 27. Re: Modifying Levels Adjustment Layer?
                                                              Kukurykus Adobe Community Professional

                                                              I read some topics last hour on PS-SCRIPTS.COM - Independent Photoshop® Scripting Community and I found some more info how stringIDToTypeID('legacyContentData') can be used, but not how he got to know about its existence.

                                                              • 28. Re: Modifying Levels Adjustment Layer?
                                                                Kukurykus Adobe Community Professional

                                                                I think you already answered I was simply faster and answered before your update. Then I added "I see your UPDATE!" to my post. So it seems your second script is that what I looked for. Let me check it. THX!

                                                                • 29. Re: Modifying Levels Adjustment Layer?
                                                                  r-bin Level 4

                                                                  It exists in any adjustment layer. The get_adjustment_rawdata (id) function will return undefined if it does not exist. You can also use desc.hasKey ()

                                                                  • 30. Re: Modifying Levels Adjustment Layer?
                                                                    JJMack Most Valuable Participant

                                                                    Yes I know where you are coming from. I fine with my lack of JavaScript knowledge. That the Adobe Photoshop JavaScript reference is all to brief when it come to Action manage coding particularly  about what can be gotten at  using executeActionGet.   Being I can not type and do not know JavaScript it had for me to play around with executeActionGet to find out what can be gotten.  I need the help a good will users like r-bin superM and other I'm sure you will be one soon.

                                                                    • 31. Re: Modifying Levels Adjustment Layer?
                                                                      r-bin Level 4

                                                                      They do not have detailed documentation for action manager examples, because they do all their actions in Photoshop thru one place which starting with the letter "A" and ending with two letters "s" )

                                                                       

                                                                      IMHO

                                                                      • 32. Re: Modifying Levels Adjustment Layer?
                                                                        Kukurykus Adobe Community Professional

                                                                        I would like you to be their main staff Photoshop Scripting Director with full right to decide what should be fixed in their sad Ps code. I believe in just ONE year your directives would made Adobe scripting free of bugs. If additionally there were team to rewrite documentation I'd like to remove that all lame & slow DOM and replace it with many understable AM examples!