Skip to main content
Participant
May 12, 2019
Answered

Action or Script to eyedropper at the current mouse position

  • May 12, 2019
  • 5 replies
  • 3914 views

I want to record an action that does something like this:

1. Eyedropper the color at the current mouse position

2. Lock transparent pixels at current layer

3. Fill the layer with that color

4. Unlock transparent pixels at current layer

3. Move up to the next layer

I tried recording an action like this, but I've encountered 2 problems: first, when I record an Eyedropper click, it just records "Set Foreground Color" as an static color, and not picking wherever my mouse is currently hovering at when I start the action. Another problem is that whenever I do record fill, when I play the script, it brings that annoying Popup. I just want a simple fill (same as Alt + Del, without popup).

Is there any way around this?

This topic has been closed for replies.
Correct answer Chuck Uebele

Have you tried using

desc23.putBoolean(stringIDToTypeID("preserveTransparency"), true);


Yea, that worked. I recorded the AM code using the menu item for fill rather than the KBSC, so I was able to turn on preserve transparency. No need to lock the layer.

#target photoshop

var doc = activeDocument;

var curLayer = doc.activeLayer;//layer to fill

if(curLayer.name !='sample'){

var samp = doc.layers.getByName('sample'); //color sampler layer must be named "sample"

var base = doc.layers.getByName('base'); //layer from which to sample the color"

var sampLocation = new Array((samp.bounds[2].value+samp.bounds[0].value)/2,(samp.bounds[3].value+samp.bounds[1].value)/2)// get location of dot layer for color sampler

    doc.activeLayer = base; //select base to sample and just turn on it's visibility

    turnOff ();

    sampleColor ();

    turnOff ();

    doc.activeLayer = curLayer;

    fillLayer ();

    }

else{alert('Do not use the "sample" layer as a starting point')}

   

function fillLayer(){

   

var idFl = charIDToTypeID( "Fl  " );

    var desc5 = new ActionDescriptor();

    var idUsng = charIDToTypeID( "Usng" );

    var idFlCn = charIDToTypeID( "FlCn" );

    var idFrgC = charIDToTypeID( "FrgC" );

    desc5.putEnumerated( idUsng, idFlCn, idFrgC );

    var idOpct = charIDToTypeID( "Opct" );

    var idPrc = charIDToTypeID( "#Prc" );

    desc5.putUnitDouble( idOpct, idPrc, 100.000000 );

    var idMd = charIDToTypeID( "Md  " );

    var idBlnM = charIDToTypeID( "BlnM" );

    var idNrml = charIDToTypeID( "Nrml" );

    desc5.putEnumerated( idMd, idBlnM, idNrml );

    var idPrsT = charIDToTypeID( "PrsT" );

    desc5.putBoolean( idPrsT, true );

executeAction( idFl, desc5, DialogModes.NO );

    }

function turnOff(){

     var idShw = charIDToTypeID( "Shw " );

        var desc3 = new ActionDescriptor();

        var idnull = charIDToTypeID( "null" );

            var list2 = new ActionList();

                var ref2 = new ActionReference();

                var idLyr = charIDToTypeID( "Lyr " );

                var idOrdn = charIDToTypeID( "Ordn" );

                var idTrgt = charIDToTypeID( "Trgt" );

                ref2.putEnumerated( idLyr, idOrdn, idTrgt );

            list2.putReference( ref2 );

        desc3.putList( idnull, list2 );

        var idTglO = charIDToTypeID( "TglO" );

        desc3.putBoolean( idTglO, true );

    executeAction( idShw, desc3, DialogModes.NO );  

    }

function sampleColor(){

    doc.colorSamplers.removeAll();

    colorS1 = doc.colorSamplers.add (sampLocation);

    var c1R = colorS1.color.rgb.red

    var c1G = colorS1.color.rgb.green

    var c1B = colorS1.color.rgb.blue   

    var idsetd = charIDToTypeID( "setd" );

        var desc17 = new ActionDescriptor();

        var idnull = charIDToTypeID( "null" );

            var ref4 = new ActionReference();

            var idClr = charIDToTypeID( "Clr " );

            var idFrgC = charIDToTypeID( "FrgC" );

            ref4.putProperty( idClr, idFrgC );

        desc17.putReference( idnull, ref4 );

        var idT = charIDToTypeID( "T   " );

            var desc18 = new ActionDescriptor();

            var idRd = charIDToTypeID( "Rd  " );

            desc18.putDouble( idRd, c1R );

            var idGrn = charIDToTypeID( "Grn " );

            desc18.putDouble( idGrn, c1G );

            var idBl = charIDToTypeID( "Bl  " );

            desc18.putDouble( idBl, c1B );

        var idRGBC = charIDToTypeID( "RGBC" );

        desc17.putObject( idT, idRGBC, desc18 );

        var idSrce = charIDToTypeID( "Srce" );

        desc17.putString( idSrce, """photoshopPicker""" );

    executeAction( idsetd, desc17, DialogModes.NO );

   

    }

5 replies

Chuck Uebele
Community Expert
Community Expert
May 13, 2019

I played around with trying to script filling layer with the transparency lock, and there seems to be a bug with doing that, so a workaround would be: rather than locking the transparency, record the layer's transparency with a ctrl/cmd-click on the layer's icon to create a selection. Then use fill. For the below script to work, you have to have a layer named: "base" that is used as the color reference. And you need to create a layer with a dot (vector or pixel), and name it: "sample." You then need to select the layer you want filled, and run the script.

#target photoshop

var doc = activeDocument;

var curLayer = doc.activeLayer;//layer to fill

if(curLayer.name !='sample'){

var samp = doc.layers.getByName('sample'); //color sampler layer must be named "sample"

var base = doc.layers.getByName('base'); //layer from which to sample the color"

var sampLocation = new Array((samp.bounds[2].value+samp.bounds[0].value)/2,(samp.bounds[3].value+samp.bounds[1].value)/2)// get location of dot layer for color sampler

    doc.activeLayer = base; //select base to sample and just turn on it's visibility

    turnOff ();

    sampleColor ();

    turnOff ();

    doc.activeLayer = curLayer;

    makeSelection ();

    fillLayer ();

    doc.selection.deselect();

    }

else{alert('Do not use the "sample" layer as a starting point')}

   

function makeSelection(){

        var idsetd = charIDToTypeID( "setd" );

        var desc6 = new ActionDescriptor();

        var idnull = charIDToTypeID( "null" );

            var ref2 = new ActionReference();

            var idChnl = charIDToTypeID( "Chnl" );

            var idfsel = charIDToTypeID( "fsel" );

            ref2.putProperty( idChnl, idfsel );

        desc6.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 );

        desc6.putReference( idT, ref3 );

    executeAction( idsetd, desc6, DialogModes.NO );

}

function fillLayer(){

    var idFl = charIDToTypeID( "Fl  " );

        var desc23 = new ActionDescriptor();

        var idUsng = charIDToTypeID( "Usng" );

        var idFlCn = charIDToTypeID( "FlCn" );

        var idFrgC = charIDToTypeID( "FrgC" );

        desc23.putEnumerated( idUsng, idFlCn, idFrgC );

    executeAction( idFl, desc23, DialogModes.NO ); 

    }

function turnOff(){

     var idShw = charIDToTypeID( "Shw " );

        var desc3 = new ActionDescriptor();

        var idnull = charIDToTypeID( "null" );

            var list2 = new ActionList();

                var ref2 = new ActionReference();

                var idLyr = charIDToTypeID( "Lyr " );

                var idOrdn = charIDToTypeID( "Ordn" );

                var idTrgt = charIDToTypeID( "Trgt" );

                ref2.putEnumerated( idLyr, idOrdn, idTrgt );

            list2.putReference( ref2 );

        desc3.putList( idnull, list2 );

        var idTglO = charIDToTypeID( "TglO" );

        desc3.putBoolean( idTglO, true );

    executeAction( idShw, desc3, DialogModes.NO );  

    }

function sampleColor(){

    doc.colorSamplers.removeAll();

    colorS1 = doc.colorSamplers.add (sampLocation);

    var c1R = colorS1.color.rgb.red

    var c1G = colorS1.color.rgb.green

    var c1B = colorS1.color.rgb.blue   

    var idsetd = charIDToTypeID( "setd" );

        var desc17 = new ActionDescriptor();

        var idnull = charIDToTypeID( "null" );

            var ref4 = new ActionReference();

            var idClr = charIDToTypeID( "Clr " );

            var idFrgC = charIDToTypeID( "FrgC" );

            ref4.putProperty( idClr, idFrgC );

        desc17.putReference( idnull, ref4 );

        var idT = charIDToTypeID( "T   " );

            var desc18 = new ActionDescriptor();

            var idRd = charIDToTypeID( "Rd  " );

            desc18.putDouble( idRd, c1R );

            var idGrn = charIDToTypeID( "Grn " );

            desc18.putDouble( idGrn, c1G );

            var idBl = charIDToTypeID( "Bl  " );

            desc18.putDouble( idBl, c1B );

        var idRGBC = charIDToTypeID( "RGBC" );

        desc17.putObject( idT, idRGBC, desc18 );

        var idSrce = charIDToTypeID( "Srce" );

        desc17.putString( idSrce, """photoshopPicker""" );

    executeAction( idsetd, desc17, DialogModes.NO );

   

    }

JJMack
Community Expert
Community Expert
May 13, 2019

Don't forget different layer types have different attributes fill is not a valid option for all layer type. You fill function will fail on those layer types

JJMack
Chuck Uebele
Community Expert
Community Expert
May 13, 2019

I recorded some AM code for fill on a locked transparency pixel layer, but it failed when it was played. It did fill a vector layer.

Chuck Uebele
Community Expert
Community Expert
May 12, 2019

As the others said, you can't record the mouse position. What you can do is create a script. Create a layer with a shape dot. This will act as your cursor position. In the script, reference the layer you want to fill and also the dot layer. They you can use the dot location for getting the color sample and applying it to another layer. I've been doing some thing along those lines but morphing shape layer between two paths, then using dot layer to sample a reference layer for color and applying a gradient to each shape layer.

JJMack
Community Expert
Community Expert
May 12, 2019

Nice

JJMack
JJMack
Community Expert
Community Expert
May 12, 2019

You may find the script useful for getting at color samplers position and color.  You would need to loop through the document layer or get the layers by some means to process the different layer you want to fill.  Where you can select layers relatively in an action you need to know what the layer structure is and which layer is active when the action is played. For  Conditional Action steps can only test some condition of a layer like its type if it has at a mask.  Can not process layer name logically and if selected by name the action will fail if the name does not exist of if several layer have the same name which layer will be the one selected. Scripts are more powerful than actions.

var orig_ruler_units = app.preferences.rulerUnits;

app.preferences.rulerUnits = Units.PIXELS; // Set the ruler units to PIXELS

message="Canvas Width=" + app.activeDocument.width.value + " ,Height=" + app.activeDocument.height.value;

for (var s=0,len=app.activeDocument.colorSamplers.length;s<len;s++) {

var colorSamplerRef = app.activeDocument.colorSamplers;

var rgbC = new SolidColor 

    rgbC.rgb.red = colorSamplerRef.color.rgb.red; 

    rgbC.rgb.green = colorSamplerRef.color.rgb.green; 

    rgbC.rgb.blue = colorSamplerRef.color.rgb.blue;  

    //alert(rgbC.rgb.hexValue) 

message = message + "\nColorSampler=" + s + " ,x=" + colorSamplerRef.position[0].value + " ,y=" + colorSamplerRef.position[1].value

+ " Color=" + rgbC.rgb.hexValue;

}

alert(message);

app.preferences.rulerUnits = orig_ruler_units; // Reset units to original settings

Stephen action will be interactive and work if all you want to do is process the currently targeted raster layer.  Then target the next layer up in the stack. If the next layer is also a one you wish the fill you can use the action again. One thing to note is Stephen  Acton will not will not work for all layer types.  The  lock transparent and later merge clip layer will not work if the current targets layer is a layer like a shape layer.  The fill Layer will remain clipped to the shape layer or text layer.

JJMack
Stephen Marsh
Community Expert
Community Expert
May 12, 2019

I would offer the following action steps as a suggestion based on your wishlist:

The first thing is to create an eyedropper tool preset for the action to select in order to make the eyedropper active from the action playback. This is a 2 part action, or just remember to pick the colour first and then run the action deleting the first two steps if you are doing them manually.

JJMack
Community Expert
Community Expert
May 12, 2019

Actions and scripts can not get the position of the mouse/pen cursor so what you want to do is impossible.   However,  if you set a  Color sampler at the pixels color you want to use a script can do what you want to do using the Color Sampler position and layer color.  Photoshop Scripts can use logic to do the process you want to do. With the exception of  " Lock transparent pixels at current layer" The Layer's tramsparency can ve lock and preserved. I do not think Photoshop has such a feature.  And I do not remembet if you get the opacity of the pixel of a sample color becaus the Point can be a single pixels or an area of pixels.

Edit:

You only get the Color To fill with as a solor color.  The Layer you would fill woul be filled with that color.  Of cource you could lick it curreb transparenct befor you fill and also adjust the layer opacity after the fill.

JJMack