10 Replies Latest reply on Dec 10, 2011 1:11 AM by dgolberg

    HSB Average from Selection + HSB Adjustment

    dgolberg Level 1

      Little bit of an unusual one for you here; but here it is anyway... Is there any way to get the average HSB value of a randomly selected area without applying the average filter, using script?  The selection is already created before the script is run, so all the script needs to do is get the selected area's average HSB value.  Additionally, is it possible to then adjust that selected area's HSB values to a predetermined value?  I want it to keep the detail, but say, darken an area if it's brighter than the preset or desaturate it if the color is too strong.  Any ideas on how to do these/if it's possible to do these?  I'm pretty sure the second one's doable, but not so sure about the first, so any help is appreciated.



        • 1. Re: HSB Average from Selection + HSB Adjustment
          c.pfaffenbichler Level 9

          I don’t see a realistic alternative to the filter if the Selection is of any significant size.


          And as for editing with an HSB-average-target: Are you working in HSB or RGB or Lab?

          I suspect doing the correction with a Curves or other Adjustment Layer/s and then re-Average-ing to verify the effect (and trying again if the effect is not as intended) might be possible, but I fear might not be very efficient and possibly fail in some cases.


          Why don’t you tell what this is about in practice?

          • 2. Re: HSB Average from Selection + HSB Adjustment
            dgolberg Level 1

            Thanks for taking a look at it c.pfaffenbichler.  Anyway, basically what I'm doing is taking an object in a scene and overlaying it over various colors.  For example, my current process (which works but usually ends up too dark on some objects) is to take a copy of the object and put it in a new layer.  I then create a new layer below it and fill said layer with the color I'm looking for, then desaturate the copy from the background, set it to soft light, duplicate it (to make the affect stronger and more realistic), then merge the 3 layers together.  This works great if the object is lighter in color; but darker objects, as you guessed it, come out too dark; and on very rare occasions, too saturated (usually when the object is too light rather than dark). 


            I did some further testing with it after creating the original post and found that, taking the HSB brightness value from the averaged result (after running it through the above process; I temp apply the average filter and grab the color with the eyedropper tool) and comparing it with the HSB value of the underlying color layer resulted in different values.  I then took the B value and subtracted the result from the underlay to come up with the difference between the 2.  I then take that difference, multiply it by 2, and using the Brightness/Contrast tool, add that value to brightness.  I then have something VERY close to, if not exactly what I'm looking for.  The only hard part is automating the process; which is why I'm here for 


            Anyway, let me know if that's still a little hard to understand and I'll try to clarify any parts that don't make sense.

            • 3. Re: HSB Average from Selection + HSB Adjustment
              dgolberg Level 1

              The hardest part is getting the HSB value from a random location based on the selected area.  If I can figure that out, I can probably come up with the rest through actions and other scripting.  As far as the averaging, I could probably just create temporary copies to average for getting the HSB, then delete them when I'm done, that's not too big of a deal.

              • 4. Re: HSB Average from Selection + HSB Adjustment
                c.pfaffenbichler Level 9

                First I thought recoloring images of textiles, but as many of those are patterned such an approach would seem difficult, so I guess more likely you are trying to recolor photographs of technical objects.

                Could you post an example of an original image (in lores) and your target value?

                Are you working in RGB?


                The whole approach seems a bit problematic to me, please excuse if you have already given thought to all that, but I want to point out why the merit of a color-metric approach might seem debatable, just to make sure:

                If one wants to achieve the effect of a photographed object apearing as if it had a defined HSB color it would seem necessary to know the original object’s HSB color to be able to judge whether the conditions at taking the photograph already resulted in a changed average HSB-color – which seems quite likely with various lighting conditions and depending on the object’s shape (not to mention the surface reflectivity), as for example large parts may be in shadow and therefore affect overall brightness but also saturation.


                Have you tried Luminance or Linear Light as alternative Blend Modes?

                • 5. Re: HSB Average from Selection + HSB Adjustment
                  dgolberg Level 1

                  Well, I'm in RGB/8 color mode, but I'm using the HSB (via the color picker window) to determine the difference in brightness of the resulting color. 


                  Anyway, below is an example of what I'm trying to do (I couldn't use the actual project due to NDA, but it's the same methodology).  The first image is the original photo with a color palette for various stains in the lower right corner.  On the palette, I took the original stain, selected it and averaged it out to get a base color to work with.  I then cut out the object (in this case the cabinet) to apply the "stain" to. 


                  The method I had been using was to then create a fill layer below the cabinet layer using one of the stain averages, desaturate the cabinet layer and set it to soft light and duplicate it.  After seeing your mention of luminosity and linear light, I tried those, but got even darker results.  Instead, I found 1 soft light layer and 1 luminosity layer over that gave a slightly better result than 2x softlight layers, but they still come out the same brightness.  The 2nd and 3rd picture are examples of my results after merging the color layer and 2 overlay layers together.  The 2nd picture is the top stain, the 3rd is the next one down from that.  Now, they're not TOO far off in this one; but sometimes the original we work with has a darker stain to it, so the result comes out too dark compared to the palette, even though it looks good otherwise. 




                  Obviously, some stains are just too dark to do anything with, but the ones we're having the most trouble with we can still get to look right, albeit through a very lengthy and manual process of curves, saturation, and color balance; and often the manual method comes up with inconsistent results.  Basically, what I'm trying to do is automate the process to not only speed things up; but to get more consistent results than we currently are getting from the manual method (often times others have to do the process, and their proof colors may be off or they simply have trouble adjusting the colors correctly).  So far, this method is getting our colors much more consistent, but the brightness is still a bit off due to the intensity of the original; which is why I keep referring to HSB, as I can see the Brightness of the texture this way.


                  All I need to do now is create a script that can get the color of a random location in the image (basically the layer that was cut out from the background then altered and merged back into a single layer like images 2 and 3 above), and compare the averaged brightness from the stain palette to the averaged brightness from the merged layers.  I know how to get the color of a specific location, but not of a random location that is ever changing (the object(s) we're working with are usually in different places in each photo), which is what I'm stuck on now.  I would assume that, if it even is possible, it would require either a selection of the area or a transparent layer where it can pick the color from the areas that have pixel color and ignore the transparent sections.


                  Does that help any?

                  • 6. Re: HSB Average from Selection + HSB Adjustment
                    dgolberg Level 1

                    Basically, I just need a script that can get the color from a random location and store the values for comparison.  The colors should either be in the HSB format or converted to HSB in order for me to apply the math needed to figure out how much brightness I need to add to get the desired look.

                    • 7. Re: HSB Average from Selection + HSB Adjustment
                      c.pfaffenbichler Level 9

                      I tend to use paths for stuff they may not be ideally fitted to, but in this case I suppose creating a Working Path is a valid option to determine a point in the area of a Layer.

                      This Script probably should include a check to verify the Preferences are set to morw than 6 History States, but most users probably have that anyway.


                      Could you try this?

                      // get hue, saturation and brightness from an averaged layer;
                      // 2011; use it at your own risk;
                      #target photoshop
                      if (app.documents.length > 0) {
                      if (app.activeDocument.activeLayer.kind == LayerKind.NORMAL) {
                      var myDocument = app.activeDocument;
                      // set to pixels;
                      var originalRulerUnits = app.preferences.rulerUnits;
                      app.preferences.rulerUnits = Units.PIXELS;
                      var historyState = myDocument.activeHistoryState;
                      try {
                      // apply average filter;
                      hideOthers ();
                      // load layer transparency;
                      // =======================================================
                      var idsetd = charIDToTypeID( "setd" );
                          var desc4 = new ActionDescriptor();
                          var idnull = charIDToTypeID( "null" );
                              var ref2 = new ActionReference();
                              var idChnl = charIDToTypeID( "Chnl" );
                              var idfsel = charIDToTypeID( "fsel" );
                              ref2.putProperty( idChnl, idfsel );
                          desc4.putReference( idnull, ref2 );
                          var idT = charIDToTypeID( "T   " );
                              var ref3 = new ActionReference();
                              var idChnl = charIDToTypeID( "Chnl" );
                              var idChnl = charIDToTypeID( "Chnl" );
                              var idTrsp = charIDToTypeID( "Trsp" );
                              ref3.putEnumerated( idChnl, idChnl, idTrsp );
                          desc4.putReference( idT, ref3 );
                      executeAction( idsetd, desc4, DialogModes.NO );
                      // contract selection and make path;
                      // get one point;
                      var thePoint = myDocument.pathItems[myDocument.pathItems.length - 1].subPathItems[0].pathPoints[0].anchor;
                      // set colorsampler;
                      var myColorSampler = myDocument.colorSamplers.add(thePoint);
                      // return and set foreground-color;
                      var theH = myColorSampler.color.hsb.hue;
                      var theS = myColorSampler.color.hsb.saturation;
                      var theB = myColorSampler.color.hsb.brightness;
                      // undo path and colorsampler;
                      myDocument.activeHistoryState = historyState;// myDocument.historyStates[myDocument.historyStates.length - 2];
                      alert ("hue "+theH+"\nsaturation "+theS+"\nbrightness "+theB)
                      catch (e) {alert ("failed")};
                      // reset;
                      app.rulerUnits = originalRulerUnits;
                      ////// toggle visibility of others //////
                      function hideOthers () {
                      // =======================================================
                      var idShw = charIDToTypeID( "Shw " );
                          var desc10 = new ActionDescriptor();
                          var idnull = charIDToTypeID( "null" );
                              var list4 = new ActionList();
                                  var ref7 = new ActionReference();
                                  var idLyr = charIDToTypeID( "Lyr " );
                                  var idOrdn = charIDToTypeID( "Ordn" );
                                  var idTrgt = charIDToTypeID( "Trgt" );
                                  ref7.putEnumerated( idLyr, idOrdn, idTrgt );
                              list4.putReference( ref7 );
                          desc10.putList( idnull, list4 );
                          var idTglO = charIDToTypeID( "TglO" );
                          desc10.putBoolean( idTglO, true );
                      executeAction( idShw, desc10, DialogModes.NO );
                      • 8. Re: HSB Average from Selection + HSB Adjustment
                        dgolberg Level 1

                        Awesome! It's working really well! there is one small issue though, and I think I know what it is.  When I just run the script on the layer, the saturation in the HSB is way off and the brightness is a little bit off as well.  However, when I ctrl+click the layer to create a selection of it first, then run the script, it works fine; so I think it's simply a case of the order the average step comes in.  Moving the average layer line to just before the contract selection and make path lines seems to have fixed it.  My guess is the average was being run on the transparent portions too, causing the incorrect saturation and brightness results.


                        Awesome job on the script!  It's going to help me out a TON!  Just a quick question though on the paths.  How exactly do pathItems work and what all can they do?  Knowing more about them might be handy for future scripts.


                        Anyway, thanks again for the help!

                        • 9. Re: HSB Average from Selection + HSB Adjustment
                          c.pfaffenbichler Level 9

                          You’re welcome.

                          Sorry, I seem to have run insufficient tests if it did not work out originally – but good to read you’ve been able to amend it yourself.


                          Photoshop handles PathItems differently from Illustrator for example.

                          So you cannot address SubPathItems or PathPoints directly based on whether you have them selected in Photoshop or simply transform an existing path (the workaround here could be to use the path as a Vector Mask on a Layer and transform that), but you can use existing paths’ information and perform mathematical operations on those (rather their PathPoints’ anchor, leftDirection, rightDirection), add additional points, omit existing ones and use that to create a new PathItem.

                          And one can use makeWorkPath() on a Selection to get PathPoints which may, as I think it is in this case, help one get a relatively quick workaraound to determine points that are located on a Selection’s edge.

                          1 person found this helpful
                          • 10. Re: HSB Average from Selection + HSB Adjustment
                            dgolberg Level 1

                            Ahh, think I understand them more now.  I was thinking they were something more complex than that.  Using the example of the selection edge probably clarrified it best for me. 


                            I've done some tinkering with the script and it's working great for what I needed it for.  I changed up a couple parts to make it easier to call at certain times (such as placing the try section in a function and repositioning the history state line so that all the layers are made visible again after the color values have been stored).  I also added in some script listener code to properly adjust the brightness (adjustBrightnessContrast(value, 0); seems to use the Hue/Saturation window's method for brightness that causes washout).  All I have left is some adjustments to my mathematical equations to get the adjustment amount/direction correct and adding if statements/for loops to run the script on all necessary layers.


                            Thanks again for the help! This will save me a ton of time!