2 Replies Latest reply on Jun 16, 2016 8:09 AM by Edward C. D. Hopkins

    How do I script the Paint Bucket?

    Edward C. D. Hopkins

      Re: Photoshop CS6, ver 13.0.1 (x32) on Win 7 SP1 (64-bit) 16gB RAM

       

      When scripting the Trim function in Photoshop, some of my photos apparently have non-white pixels on the canvas that don't match white color of the top left corner pixel. Thus some sides are not trimmed due to problem pixels while the other sides are neatly trimmed. An example where the top is not trimmed while the left, right and bottom are trimmed is at http://www.sylloge.net/Upload75/IFN-8480988_02.tif (apologies for defacing due museum's copyright).

       

      This is easily repaired by using the Paint Bucket with white at opacity 100%, tolerance 10 near the top left of  background. How do I script the Paint Bucket at position 10 pixels from left, 10 pixels from top?

       

      Is Paint Bucket the right approach to the problem?

        • 1. Re: How do I script the Paint Bucket?
          JJMack Most Valuable Participant

          If Trim using the top left or bottom right corner do not work adding a white pixel there may not work either.  I do not know how trim works or how much tolerance it may use.  I would suggest trying to simulate a trim with some high tolerance using the magic wand. If its a background layer image. Convert it to a normal layer and  add a white layer under that layer the use the magic wand tool to select contiguous pixels sampling areas on the boarder of the canvas  invert and clear pixels on that layer.  Do this several time sample different point about the canvas border,   Then get the layer's  bounds and crop the canvas to that layers bounds..

           

          I wrote a script something like that to trim layer that have borders there was no cropping done.

          Capture.jpg

          try { if(app.documents.length>0){ app.activeDocument.suspendHistory ('Trim Layers', 'TrimLayers();') } }
          catch(e) { alert( e + ': on line '  + e.line );}
          
          
          function TrimLayers() { 
            var orig_ruler_units = app.preferences.rulerUnits; // save user ruler units  
            var orig_display_dialogs = app.displayDialogs; // Save users Displat Doalogs
            app.preferences.rulerUnits = Units.PIXELS; // set the ruler units to PIXELS
            app.displayDialogs = DialogModes.NO; // Set Dialogs off
            var doc  = app.activeDocument; // get current document 
            var saveactiveLayer = doc.activeLayer; // save activeLayer
            doc.selection.deselect(); // make sure ther is no active selection
            try {processArtLayers(doc);} // Process all Layers
            catch(e) { alert( e + ': on line '  + e.line );} // some unexpected error
            doc.selection.deselect(); // make sure ther is no active selection
            try { doc.activeLayer = saveactiveLayer;} // restore activeLayer
            catch(e) { } // may have been deleted
            app.displayDialogs = orig_display_dialogs; // Reset display dialogs 
            app.preferences.rulerUnits = orig_ruler_units; // reset units to original settings
          }
          ///////////////////////////////////////////////////////////////////////////////
          // Function: processsArtLayers
          // Input: document or layer set
          ///////////////////////////////////////////////////////////////////////////////
          function processArtLayers(obj) {
              for(var i = obj.artLayers.length-1;0<= i; i--) { // for Layers
            try {TrimLayer(obj.artLayers[i]); } // process Art Layer
            catch(e) {} // don't stop on errors
            }
              for(var i=obj.layerSets.length-1;0<=i;i--) { // for Layer sets
            try {processArtLayers(obj.layerSets[i]);} // process Layer Set
            catch(e) {} // don't stop on errors
            }
          }
          
          
          function TrimLayer(layer) { 
            // do nothing if layer is background or locked  
            if(layer.isBackgroundLayer || layer.allLocked || layer.pixelsLocked || layer.positionLocked || layer.transparentPixelsLocked ) return; 
            //if(layer.protectArtboardAutonest ) return;
            if( layer.kind != LayerKind.NORMAL) return; // do nothing if not normal layer   
          
            app.activeDocument.activeLayer = layer; // target layer
            var bounds = layer.bounds; // layer bounds  
            var LWidth = bounds[2]-bounds[0]; // layer width  
            var LHeight = bounds[3]-bounds[1]; // layer height 
            var Lleft =  bounds[0]; // layer left x
            var Lright =  bounds[2]; // layer right x
            var Ltop =  bounds[1]; // layer top y
            var Lbottom =  bounds[3]; // layer bottom y
            var tlrnc = 20; // tolerance
            i=0.6; // fudge factor
          
          
            try {
            MagicWand((Lleft+i), (Ltop+i), tlrnc); // top left
            app.activeDocument.selection.clear(); // clear
            }
            catch(e) {}; // do nothing
            try {
            MagicWand((Lleft+LWidth/2), (Ltop+i), tlrnc); // top middle
            app.activeDocument.selection.clear(); // clear
            }
            catch(e) {};   // do nothing
            try {
            MagicWand((Lright-i), (Ltop+i), tlrnc); // top right
            app.activeDocument.selection.clear(); // clear
            }
            catch(e) {}; // do nothing 
            try {
            MagicWand((Lleft+i), (Ltop+LHeight/2), tlrnc); // middle left
            app.activeDocument.selection.clear(); // clear
            }
            catch(e) {}; // do nothing 
            try {
            MagicWand((Lright-i), (Ltop+LHeight/2), tlrnc); // middle right
            app.activeDocument.selection.clear(); // clear
            }
            catch(e) {}; // do nothing 
            try {
            MagicWand((Lleft+i), (Lbottom-i), tlrnc); // bottom left
            app.activeDocument.selection.clear(); // clear
            }
            catch(e) {};   // do nothing
            try {
            MagicWand((Lleft+LWidth/2), (Lbottom-i), tlrnc); // bottom middle
            app.activeDocument.selection.clear(); // clear
            }
            catch(e) {}; // do nothing 
            try {
            MagicWand((Lright-i), (Lbottom-i), tlrnc); // bottom right
            app.activeDocument.selection.clear(); // clear
            }
            catch(e) {};   // do nothing
          }
          
          
          function MagicWand(x,y,tolerance) {
          var idsetd = charIDToTypeID( "setd" );
              var desc106 = new ActionDescriptor();
              var idnull = charIDToTypeID( "null" );
                  var ref60 = new ActionReference();
                  var idChnl = charIDToTypeID( "Chnl" );
                  var idfsel = charIDToTypeID( "fsel" );
                  ref60.putProperty( idChnl, idfsel );
              desc106.putReference( idnull, ref60 );
              var idT = charIDToTypeID( "T   " );
                  var desc107 = new ActionDescriptor();
                  var idHrzn = charIDToTypeID( "Hrzn" );
                  var idPxl = charIDToTypeID( "#Pxl" );
                  desc107.putUnitDouble( idHrzn, idPxl, x );
                  var idVrtc = charIDToTypeID( "Vrtc" );
                  var idPxl = charIDToTypeID( "#Pxl" );
                  desc107.putUnitDouble( idVrtc, idPxl, y );
              var idPnt = charIDToTypeID( "Pnt " );
              desc106.putObject( idT, idPnt, desc107 );
              var idTlrn = charIDToTypeID( "Tlrn" );
              desc106.putInteger( idTlrn, tolerance );
              var idAntA = charIDToTypeID( "AntA" );
              desc106.putBoolean( idAntA, true );
          executeAction( idsetd, desc106, DialogModes.NO );
          }
          
          
          • 2. Re: How do I script the Paint Bucket?
            Edward C. D. Hopkins Level 1

            I worked this part out on my own using the Script Listener which leaves you with some mysteries. Not sure what it all means, but it works!

             

            You must provide value for the toler variable when calling this function. The bucket dump coordinates are hard-coded to 10x10.

             

            Thanks to JJMack for his many instructive posts on the forums.

             

             

            function UsePaintBucket(){

                var idFl = charIDToTypeID( "Fl  " ); // Fill

                var SetParams = new ActionDescriptor();

                var idFrom = charIDToTypeID( "From" ); // From

                var Coordinates = new ActionDescriptor(); //coordinates for Paint Bucket tool to use

                // set position for paint bucket to dump

                var idHrzn = charIDToTypeID( "Hrzn" ); // Horizontal position

                var idPxl = charIDToTypeID( "#Pxl" );  // in pixels

                Coordinates.putUnitDouble( idHrzn, idPxl, 10.000000 );

                var idVrtc = charIDToTypeID( "Vrtc" ); // Vertical position

                var idPxl = charIDToTypeID( "#Pxl" ); // in pixels

                Coordinates.putUnitDouble( idVrtc, idPxl, 10.000000 );

                var idPnt = charIDToTypeID( "Pnt " ); // Paint

                SetParams.putObject( idFrom, idPnt, Coordinates );

                // Set tolerance to user-specified value

                var idTlrn = charIDToTypeID( "Tlrn" ); // Tolerence

                SetParams.putInteger( idTlrn, toler );  // user's specified tolerance value

                // Set anti-alias True

                var idAntA = charIDToTypeID( "AntA" ); // Anti-alias

                SetParams.putBoolean( idAntA, true ); // set to True

                // What are these?

                var idUsng = charIDToTypeID( "Usng" );

                var idFlCn = charIDToTypeID( "FlCn" );

                var idFrgC = charIDToTypeID( "FrgC" );

                SetParams.putEnumerated( idUsng, idFlCn, idFrgC );

                // Set opacity to 100 per cent

                var idOpct = charIDToTypeID( "Opct" ); // Opacity

                var idPrc = charIDToTypeID( "#Prc" ); // Percentage

                SetParams.putUnitDouble( idOpct, idPrc, 100.000000 );   

                executeAction( idFl, SetParams, DialogModes.NO );

            }