18 Replies Latest reply on Sep 30, 2013 11:22 PM by c.pfaffenbichler

    Find a color and add an anchor point script

    goaldst

      I'm super close to having this right but I get very inconsistent anchor points to show up.

       

      The problem is that sometimes I get two per pixel and sometimes it will miss some of the colors that match the hexvalue I am looking for.

       

      I'd like for this to be consistent in adding an anchor point to the top left hand corner of the pixel that mathes the hexvalue.

       

      Any help would be much appreciated! Code below ...

       

      CODE: SELECT ALL

      function main(){

      var startRulerUnits = app.preferences.rulerUnits;

      app.preferences.rulerUnits = Units.PIXELS;

       

      var myHeight = app.activeDocument.height;

      var myWidth = app.activeDocument.width;

       

      // Find pixel Color

      for(var x=0; x<myWidth; x++) {

        for(var y=0; y<myHeight; y++) {

         activeDocument.colorSamplers.removeAll();

         var sampler = activeDocument.colorSamplers.add([new UnitValue (x, 'px'), new UnitValue (y, 'px')]);

         if (sampler.color.rgb.hexValue === "502905") {

       

            var pname = 'Path ' + Math.floor(Math.random()*10000000000000000);

       

            var startPoint = new PathPointInfo();

            startPoint.anchor = [x,y];

            startPoint.leftDirection = [x,y];

            startPoint.rightDirection = [x,y];

            startPoint.kind = PointKind.CORNERPOINT;

       

            var stopPoint = new PathPointInfo();

            stopPoint.anchor = [x,y];

            stopPoint.leftDirection = [x,y];

            stopPoint.rightDirection = [x,y];

            stopPoint.kind = PointKind.CORNERPOINT;

       

            var spi = new SubPathInfo();

            spi.closed = false;

            spi.operation = ShapeOperation.SHAPEADD;

            spi.entireSubPath = [startPoint];

            var line = activeDocument.pathItems.add(pname, [spi]);

       

         }

       

        }

      }

      }

      main();

        • 1. Re: Find a color and add an anchor point script
          c.pfaffenbichler Level 9

          You are not resetting the rulerUnits.

           

          Is the Color Sampler Tool set to »Point Sample«?

          Have you tried offsetting it half a pixel in both directions?

           

          Iterating a Color Sampler through an image can take a lot of time depending on the image; what are you trying to achieve? Maybe there are other ways of accomplishing that task …

          • 2. Re: Find a color and add an anchor point script
            goaldst Level 1

            What I want to accomplish is to target a specific hexvalue in an image and then drop a anchor point on every pixel that holds that hexvalue.

             

            I do realize that this is going to take alot of time to do it this way.

             

            I will try the suggestions you mentioned above, but if there is a different way to accomplish what I mentioned above I'm all ears!

             

            Thank you for the reply!

            • 3. Re: Find a color and add an anchor point script
              c.pfaffenbichler Level 9

              What do you want to do with the pathPoints afterwards?

              • 4. Re: Find a color and add an anchor point script
                goaldst Level 1

                Nothing. They don't need to connect or anything.

                 

                I want to be able to target a specific color drop some points and then rinse and repeat on a different color.

                • 5. Re: Find a color and add an anchor point script
                  goaldst Level 1

                  So setting my variables to 0.5 instead of 0 worked PERFECT! It's now dumping a point right in the center of the specified pixel and it added on every pixel of that hexvalue.

                   

                  This thing is working perfect man, really appreciate the help!

                   

                  If you have another way off accomplishing this I would be interested in your feedback.

                  • 6. Re: Find a color and add an anchor point script
                    c.pfaffenbichler Level 9

                    Paul provided a Script to get the Lab values via a RAW.

                    http://forums.adobe.com/message/4095741#4095741

                    Maybe this could be adapted in some way and run faster than iterating the Color Picker through the image … not sure, though.

                    • 7. Re: Find a color and add an anchor point script
                      goaldst Level 1

                      Thanks for the lead on the other script. Might take a look at doing this differently.


                      I do have another issue with this script that is throwing a Photoshop error. Here is the error:

                       

                      Error 8800: General Photoshop error occurred. This functionality may not be available in this version of Photoshop.

                       

                      - The command “Rename” is not currently available.

                      Line: 41

                      ->        var line = activeDocument.pathItems.add(pname, [spi]);

                       

                      I'm not sure what the command "Rename" issue is coming from but its definitely the issue.

                       

                      The script is giving a name to each point it creates. Which PS may be processing as a rename.

                       

                      Is there a way for PS to just name the file for me? Or, maybe there is a something different I should do avoid this error?

                      • 8. Re: Find a color and add an anchor point script
                        goaldst Level 1

                        To add to this ...

                         

                        I think what the script does is it makes a Work Path and then it renames it ... I could be wrong.

                         

                        Any way around the rename process?

                        • 9. Re: Find a color and add an anchor point script
                          c.pfaffenbichler Level 9

                          Any way around the rename process?

                          Not as far as I know.

                           

                          If you are willing to work with Lab values instead of Hex values this might work.

                          The name of the path is just a random number here, though.

                          // in large part based on code by paul riggitt;
                          // 2013, use it at your own risk;
                          #target photoshop
                          File.prototype.readByte = function() {
                            return this.read(1).charCodeAt(0); 
                          };
                          function convertByteToSignedByte(num){
                               var dec = (num | (num % 256))-128
                               return dec;
                          };
                          function convertByteToLum( num){
                               var dec = Math.round((num/256)*100);
                               return dec;
                          };
                          function main(){
                          if(!documents.length) return;
                          // create an array for path;
                          var myDocument = app.activeDocument;
                          var theArray = new Array;
                          var originalRulerUnits = app.preferences.rulerUnits;
                          app.preferences.rulerUnits = Units.POINTS;
                          var originalResolution = myDocument.resolution;
                          myDocument.resizeImage(undefined, undefined, 72, ResampleMethod.NONE);
                          //
                          if(activeDocument.mode != DocumentMode.LAB) {
                              alert("Please convert this document to Lab mode\r Then re-run this script");
                              return;
                              }
                          var Name = decodeURI(app.activeDocument.name).replace(/\.[^\.]+$/, '');
                          try{
                          var Path = activeDocument.path;
                          }catch(e){var Path = '~/Desktop';}
                          var rawFile = new File(Path +"/"+Name +".raw");
                          saveAsRaw(rawFile);
                          var len = 0;
                          var W = activeDocument.width.as('px');
                          CountW=0;
                          CountH=0;
                          rawFile.encoding = 'BINARY';
                          rawFile.open('r');
                          while(!rawFile.eof){
                          var theX = CountW;
                          var theY = CountH;
                          var theL = convertByteToLum(rawFile.readByte());
                          var theA = convertByteToSignedByte(rawFile.readByte());
                          var theB = convertByteToSignedByte(rawFile.readByte());
                          // check the values; 
                          if (theL == 86 && theA == -96 && theB == -24) {
                          var aPoint = [new UnitValue(theX, "pt"), new UnitValue (theY, "pt")];
                          theArray.push( [[aPoint, aPoint, aPoint, false], false, 1097098272] )
                          };
                          //           
                               len++;
                               if(len % W == 0){
                                   CountH++;
                                   CountW=0;
                                   }else{
                               CountW++;
                               }
                          }
                          rawFile.close();
                          //csvFile.close();
                          rawFile.remove();
                          // create path;
                          createPath2012(theArray, Math.random());
                          app.preferences.rulerUnits = originalRulerUnits;
                          myDocument.resizeImage(undefined, undefined, originalResolution, ResampleMethod.NONE);
                          //
                          };
                          main();
                          function saveAsRaw(file) {
                          var desc1 = new ActionDescriptor();
                          var desc2 = new ActionDescriptor();
                          desc2.putString( charIDToTypeID('FlCr'), "8BIM" );
                          desc2.putBoolean( charIDToTypeID('ChnI'), true );
                          desc1.putObject( charIDToTypeID('As  '), charIDToTypeID('Rw  '), desc2 );
                          desc1.putPath( charIDToTypeID('In  '), new File( file ) );
                          desc1.putBoolean( charIDToTypeID('Cpy '), true );
                          executeAction( charIDToTypeID('save'), desc1, DialogModes.NO );
                          };
                          ////// create a path from collectPathInfoFromDesc2012-array //////
                          function createPath2012(theArray, thePathsName) {
                          var originalRulerUnits = app.preferences.rulerUnits;
                          app.preferences.rulerUnits = Units.POINTS;
                          // thanks to xbytor;
                          cTID = function(s) { return app.charIDToTypeID(s); };
                          sTID = function(s) { return app.stringIDToTypeID(s); };
                          
                          
                              var desc1 = new ActionDescriptor();
                              var ref1 = new ActionReference();
                              ref1.putProperty(cTID('Path'), cTID('WrPt'));
                              desc1.putReference(sTID('null'), ref1);
                              var list1 = new ActionList();
                          
                          for (var m = 0; m < theArray.length; m++) {
                                    var thisSubPath = theArray[m];
                          
                              var desc2 = new ActionDescriptor();
                              desc2.putEnumerated(sTID('shapeOperation'), sTID('shapeOperation'), thisSubPath[thisSubPath.length - 1]);
                              var list2 = new ActionList();
                              var desc3 = new ActionDescriptor();
                              desc3.putBoolean(cTID('Clsp'), thisSubPath[thisSubPath.length - 2]);
                              var list3 = new ActionList();
                          
                          for (var n = 0; n < thisSubPath.length - 2; n++) {
                                    var thisPoint = thisSubPath[n];
                          
                              var desc4 = new ActionDescriptor();
                              var desc5 = new ActionDescriptor();
                              desc5.putUnitDouble(cTID('Hrzn'), cTID('#Rlt'), thisPoint[0][0]);
                              desc5.putUnitDouble(cTID('Vrtc'), cTID('#Rlt'), thisPoint[0][1]);
                              desc4.putObject(cTID('Anch'), cTID('Pnt '), desc5);
                              var desc6 = new ActionDescriptor();
                              desc6.putUnitDouble(cTID('Hrzn'), cTID('#Rlt'), thisPoint[1][0]);
                              desc6.putUnitDouble(cTID('Vrtc'), cTID('#Rlt'), thisPoint[1][1]);
                              desc4.putObject(cTID('Fwd '), cTID('Pnt '), desc6);
                              var desc7 = new ActionDescriptor();
                              desc7.putUnitDouble(cTID('Hrzn'), cTID('#Rlt'), thisPoint[2][0]);
                              desc7.putUnitDouble(cTID('Vrtc'), cTID('#Rlt'), thisPoint[2][1]);
                              desc4.putObject(cTID('Bwd '), cTID('Pnt '), desc7);
                              desc4.putBoolean(cTID('Smoo'), thisPoint[3]);
                              list3.putObject(cTID('Pthp'), desc4);
                          
                                    };
                          
                              desc3.putList(cTID('Pts '), list3);
                              list2.putObject(cTID('Sbpl'), desc3);
                              desc2.putList(cTID('SbpL'), list2);
                              list1.putObject(cTID('PaCm'), desc2);
                                    };
                          
                              desc1.putList(cTID('T   '), list1);
                              executeAction(cTID('setd'), desc1, DialogModes.NO);
                          
                          
                          if (hasVectorMask() == false) {
                          if (thePathsName != undefined) {app.activeDocument.pathItems[app.activeDocument.pathItems.length - 1].name = thePathsName};
                          var myPathItem = app.activeDocument.pathItems[app.activeDocument.pathItems.length - 1];
                          }
                          else {
                          if (thePathsName != undefined) {app.activeDocument.pathItems[app.activeDocument.pathItems.length - 2].name = thePathsName};
                          var myPathItem = app.activeDocument.pathItems[app.activeDocument.pathItems.length - 2];
                          };
                          app.preferences.rulerUnits = originalRulerUnits;
                          return myPathItem
                          };
                          // from »Flatten All Masks.jsx« by jeffrey tranberry;
                          ///////////////////////////////////////////////////////////////////////////////
                          // Function: hasVectorMask
                          // Usage: see if there is a vector layer mask
                          // Input: <none> Must have an open document
                          // Return: true if there is a vector mask
                          ///////////////////////////////////////////////////////////////////////////////
                          function hasVectorMask() {
                                    var hasVectorMask = false;
                                    try {
                                              var ref = new ActionReference();
                                              var keyVectorMaskEnabled = app.stringIDToTypeID( 'vectorMask' );
                                              var keyKind = app.charIDToTypeID( 'Knd ' );
                                              ref.putEnumerated( app.charIDToTypeID( 'Path' ), app.charIDToTypeID( 'Ordn' ), keyVectorMaskEnabled );
                                              var desc = executeActionGet( ref );
                                              if ( desc.hasKey( keyKind ) ) {
                                                        var kindValue = desc.getEnumerationValue( keyKind );
                                                        if (kindValue == keyVectorMaskEnabled) {
                                                                  hasVectorMask = true;
                                                        }
                                              }
                                    }catch(e) {
                                              hasVectorMask = false;
                                    }
                                    return hasVectorMask;
                          };
                          
                          • 10. Re: Find a color and add an anchor point script
                            goaldst Level 1

                            Is there a way to take the find a lab color feature and replace it with the colorsampler bit in mine?

                             

                            I will past my script below.

                             

                            function main(){

                            var startRulerUnits = app.preferences.rulerUnits;

                            app.preferences.rulerUnits = Units.PIXELS;

                            var myHeight = app.activeDocument.height;

                            var myWidth = app.activeDocument.width;

                             

                             

                            for(var x=0.5; x<myWidth; x++) {

                              for(var y=0.5; y<myHeight; y++) {

                               activeDocument.colorSamplers.removeAll();

                               var sampler = activeDocument.colorSamplers.add([new UnitValue (x, 'px'), new UnitValue (y, 'px')]);

                               if (sampler.color.rgb.hexValue === "A17F44") {

                             

                             

                                  var pname = 'Path ' + [x,y];

                             

                                  var startPoint = new PathPointInfo();

                                  startPoint.anchor = [x,y];

                                  startPoint.leftDirection = [x,y];

                                  startPoint.rightDirection = [x,y];

                                  startPoint.kind = PointKind.CORNERPOINT;

                             

                             

                                  var stopPoint = new PathPointInfo();

                                  stopPoint.anchor = [x+0.5,y+0.5];

                                  stopPoint.leftDirection = [x,y];

                                  stopPoint.rightDirection = [x,y];

                                  stopPoint.kind = PointKind.CORNERPOINT;

                             

                             

                                  var spi = new SubPathInfo();

                                  spi.closed = false;

                                  spi.operation = ShapeOperation.SHAPEADD;

                                  spi.entireSubPath = [startPoint, stopPoint];

                                  var line = activeDocument.pathItems.add(pname, [spi]);

                               }

                              }

                            }

                            }

                            main();

                            • 11. Re: Find a color and add an anchor point script
                              goaldst Level 1

                              So I changed the image I was working with and got this write an anchor point for every pixel of the same color. The only thing that's weird is it writes all of them in a single line instead of matching up with the corresponding pixel it matches.

                               

                              You have to zoom way out to 1% to see all of the achor points in a giant line.

                               

                              I can move a line of them in place and it matches up perfectly. So, is there a way for the script to write the points down the document instead of across the document?

                              • 12. Re: Find a color and add an anchor point script
                                c.pfaffenbichler Level 9

                                In my test the Script I posted works fine.

                                Here’s a screenshot of the result.

                                makePathPointsScr.jpg

                                And here’s a jpg with the path.

                                makePathPoints.jpg

                                That the Path in the Paths Panel looks empty is irrelevant, the subPathItems are just one point each.

                                 

                                You can edit the Script however you want (to produce 0.5px rectangles or whatever), of course those will only really be usefull sense if you subsequently upsample the image.

                                 

                                I still can’t discern what the ultimate goal is.

                                 

                                Using the Eyedropper for such a task is, in my opinion, a huge waste.

                                Have you compared the running times for the two methods yet?

                                • 13. Re: Find a color and add an anchor point script
                                  goaldst Level 1

                                  Ok! So this does work.

                                   

                                  I had to create a new document with Lab as it's color mode and paste a selection from my original image into the Lab Mode Document.

                                   

                                  Converting my original image to Lab and then running the script did the weird straight line of anchor points. Pasting it in a new Doc made it work perfect.

                                   

                                  On my original script I had it creating a 0.5px line from the center of the cooresponding pixel.

                                   

                                  By changing ...

                                  CountW=0;CountH=0; to CountW=0.5; CountH=0.5;

                                   

                                  I was able to get the anchor points to center the pixel. I'm not sure with this script how to make it draw a 0.5px line instead of just an anchor point.

                                  • 14. Re: Find a color and add an anchor point script
                                    c.pfaffenbichler Level 9

                                    If you change the lines

                                     

                                    var aPoint = [new UnitValue(theX, "pt"), new UnitValue (theY, "pt")]; theArray.push( [[aPoint, aPoint, aPoint, false], false, 1097098272] )

                                    to

                                    var aPoint = [new UnitValue(theX, "pt"), new UnitValue (theY, "pt")];

                                    var bPoint = [new UnitValue(theX+0.5, "pt"), new UnitValue (theY+0.5, "pt")];

                                    theArray.push( [[aPoint, aPoint, aPoint, false], [bPoint, bPoint, bPoint, false], false, 1097098272])

                                    you should be getting two-point-subPathItems.

                                     


                                    • 15. Re: Find a color and add an anchor point script
                                      goaldst Level 1

                                      This thing is working perfect now. The only other thing that I would need it to do if it's even possible ...

                                       

                                      Is to connect the points when two paths are next to each other and for it to keep connecting them through each line.

                                       

                                      I will attach a image below. I basically want all the line segments that are created to be connected to one another. Sometimes the line segment doesn't touch any other ones so I wouldn't want it to connect then. Just when there are or more line segments I guess?

                                       

                                      Here is an image. You can see the single segments that need to stay intact but for example the two segments that touch in the top left I want them to connect to each other.

                                       

                                      Screen Shot 2013-09-29 at 11.30.06 AM.png

                                      • 16. Re: Find a color and add an anchor point script
                                        c.pfaffenbichler Level 9

                                        It is possible to do this.

                                        But it may be a bit much yet.

                                         

                                        In the Script I posted the Path is created from an Array that contains Arrays (for the subPathItems) that contain Arrays (for the pathPoints) that contain Arrays (for the anchor and leftDirection and rightDirection and boolean kind), also the closed-staus and operation for each subPathItem.

                                        You could create a function to compare all the subPathItems’ points and if they match with the points of another subPathItem combine them …

                                        But like I indicated that may seem difficult.

                                        • 17. Re: Find a color and add an anchor point script
                                          goaldst Level 1

                                          Yeah for sure. It really seems like it would be a hassle to program it and I actually figured out a way to get this to work.

                                           

                                          I exported the line segments to Illustrator and was able to get them all to combine together.

                                           

                                          Big shouts outs to a ya!! This script is doing exactly what I need it to do. It's awesome this community exists and is willing to help out anyone with a question.

                                           

                                          Thanks again for the time you put into helping me out. Means alot!!

                                          • 18. Re: Find a color and add an anchor point script
                                            c.pfaffenbichler Level 9

                                            You’re welcome.

                                            As the regulars here have provided significant help and advice to me I try to pass some of that on.

                                             

                                            Actually the approach I outlined before may be more convoluted than necessary.

                                            One could just collect the coordinates first and add the path-relevant information later on.

                                            That way one could set up an additional check for the previous point in the if-clause and replace the end-point if it is identical to the new starting-point instead.

                                            But if the operation works for you now fine-tuning the Script is no priority.