Skip to main content
X-Raym
Participating Frequently
February 21, 2018
Answered

Get Layer Transform X Y Top Left Coordinate Position

  • February 21, 2018
  • 3 replies
  • 15075 views

Hi !

I try to look for this but in fact it seems more complicated than expected, and I didn't find a working up to date solution.

So we have layer bound property, which can return top left value of a layer.

But if the layer is smart layer (or a text) this may not work as I would have expect: indeed, it will return the value of the position of the first pixel, and not the actual smart layer position (determined by it's original boundaries).

Here is a screen capture to show the difference between the layer top left coordinate and the transform X Y position (which match the original file placement):

How do you get these X Y positions from a Photoshop script ?

Thanks !

This topic has been closed for replies.
Correct answer r-bin

Try this function

function get_layer_bounds(layer)

    {

    try

        {

        if (layer.kind == LayerKind.SMARTOBJECT)

            {

            var layer0 = activeDocument.activeLayer;

            activeDocument.activeLayer = layer;

            var r = new ActionReference();

            r.putEnumerated( charIDToTypeID( "Lyr " ), charIDToTypeID( "Ordn" ), charIDToTypeID( "Trgt" ) );

            var d = executeActionGet(r).getObjectValue(stringIDToTypeID("smartObjectMore")).getList(stringIDToTypeID("transform"));

            var x = [d.getDouble(0), d.getDouble(2), d.getDouble(4), d.getDouble(6)];

            var y = [d.getDouble(1), d.getDouble(3), d.getDouble(5), d.getDouble(7)];

          

            var l = [Math.min(x[0], Math.min(x[1], Math.min(x[2], x[3]))) ];

            var r = [Math.max(x[0], Math.max(x[1], Math.max(x[2], x[3]))) ];

            var t = [Math.min(y[0], Math.min(y[1], Math.min(y[2], y[3]))) ];

            var b = [Math.max(y[0], Math.max(y[1], Math.max(y[2], y[3]))) ];

            activeDocument.activeLayer = layer0;

            return [ UnitValue(l,"px"), UnitValue(t,"px"), UnitValue(r,"px"), UnitValue(b,"px") ];

            }

        else

            return layer.boundsNoEffects;

        }

    catch (e) { alert(e); }

    }

3 replies

X-Raym
X-RaymAuthor
Participating Frequently
March 17, 2018

r-bin​, the question is for anyone who want to answer 🙂
Thank you again for your time and expertise !!

 

I'll see how this function can be integrated in my current script.

 

Cheers !

X-Raym
X-RaymAuthor
Participating Frequently
March 15, 2018

I just got a very particular cases,

How would you get X and Y position relative to the Artboard position ? Seems to be a quite complex API case.

I had a layer on a artboard which was offset by 961px, and all Y were offset by 961px. Idealy, I would prefer to have it not offset.

Thanks for your help

Legend
March 16, 2018

If the question is to me, then I have never worked with ArtBoards (in CS6 there are none).

But if I understand correctly what you need, then here is a new function which, depending on the parameter "in_artboard" returns the absolute or relative coordinates of the layer (or smart object).

 

To work, you also need the function get_prop_value().

Its code can be found in this thread: Modifying Levels Adjustment Layer?

 

alert(get_layer_bounds(activeDocument.activeLayer, false))

alert(get_layer_bounds(activeDocument.activeLayer, true))

 

function get_layer_bounds(layer, in_artboard) 

    { 

    try 

        { 

        var ret;

 

        var layer0 = activeDocument.activeLayer; 

        activeDocument.activeLayer = layer; 

 

        var id = get_prop_value("layer", null, "layerID");

 

        if (layer.kind == LayerKind.SMARTOBJECT) 

            { 

            var d = get_prop_value("layer", null, "smartObjectMore", "transform");

 

            var x = [d.getDouble(0), d.getDouble(2), d.getDouble(4), d.getDouble(6)]; 

            var y = [d.getDouble(1), d.getDouble(3), d.getDouble(5), d.getDouble(7)]; 

            

            var l = [Math.min(x[0], Math.min(x[1], Math.min(x[2], x[3]))) ]; 

            var r = [Math.max(x[0], Math.max(x[1], Math.max(x[2], x[3]))) ]; 

 

            var t = [Math.min(y[0], Math.min(y[1], Math.min(y[2], y[3]))) ]; 

            var b = [Math.max(y[0], Math.max(y[1], Math.max(y[2], y[3]))) ]; 

 

            ret = [ UnitValue(l,"px"), UnitValue(t,"px"), UnitValue(r,"px"), UnitValue(b,"px") ]; 

            } 

        else 

            {

            var old_units = app.preferences.rulerUnits;

            app.preferences.rulerUnits = Units.PIXELS;

 

            ret = layer.boundsNoEffects; 

            app.preferences.rulerUnits = old_units;

            }

 

        if (in_artboard)

            {

            var art_rect = get_layer_atrboard_rect(id)

   

            ret[0] -= art_rect.left;

            ret[2] -= art_rect.left;

 

            ret[1] -= art_rect.top;

            ret[3] -= art_rect.top;

            }

 

        activeDocument.activeLayer = layer0; 

 

        return ret;

        } 

    catch (e) { alert(e); } 

    }  

 

function get_layer_atrboard_rect(id)

    {

    try {

        var not_artboard_rect = {top:0, left:0, bottom:0, right:0};

 

        eval("var json = " + get_prop_value("layer", null, "json"));

 

        if (json == undefined) return not_artboard_rect;

 

        function test_id(layer, id, n)

            {

            if (layer.id == id) return n;

 

            if (layer.layers)

                {

                for (var i = 0; i < layer.layers.length; i++)

                    {

                    var ret = test_id(layer.layers, id, n+1);

                    if (ret != null) return ret;

                    }               

                return null;

                }

            else

                {

                return null;

                }           

            }

 

        for (var i = 0; i < json.layers.length; i++)

            {

            var ret = test_id(json.layers, id, 0);

 

            if (ret)

                {

                if (json.layers.artboard) return json.layers.artboard.artboardRect;

                else return not_artboard_rect;

                break;       

                }

            }

       

        return not_artboard_rect;       

        }

    catch (e) { alert(e); }

    }

Legend
February 21, 2018
X-Raym
X-RaymAuthor
Participating Frequently
February 21, 2018

r-bin

Hi, thanks for your very quick assistance (and your initial code snippet) !

This get_smart_object_corners() function doesn't take any parameter, how come ?

How to pass a Layer as parameter to it ?

My ultimate goal is to merge this code snippet to

Adobe-Export-Scripts/Export Layer Coordinates Photoshop.jsx at master · bronzehedwick/Adobe-Export-Scripts · GitHub

As you can see L44, the function need to take a Layer as parameter.

Many thanks again!

(let me know if you prefer me to answer in the original thread).

Legend
August 13, 2018

Hi. Your code to get all properties is great! Can you advice how to set any of these options back to Smart Object? For example if I want to modify warp in code, or any other property.


change_one_warp_mesh_point_for_smart_object(2, 100,150);

function change_one_warp_mesh_point_for_smart_object(point_index, hor,ver)

    {

    try {

        var r = new ActionReference();   

        r.putProperty(charIDToTypeID("Prpr"), stringIDToTypeID("smartObjectMore"));

        r.putEnumerated(charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt"));   

        var obj = executeActionGet(r).getObjectValue(stringIDToTypeID("smartObjectMore")) ;

        var warp = obj.getObjectValue(stringIDToTypeID("warp")); 

        // if there is no warp, we will not create a new one,

        // since we need to specify 4x4 points for this, and we want to change only one

        if (!warp.hasKey(stringIDToTypeID("customEnvelopeWarp"))) return false;

        /////////////// changing one point in the current warp mesh ////////////////////

        var meshPoints = warp.getObjectValue(stringIDToTypeID("customEnvelopeWarp")).getList(stringIDToTypeID("meshPoints")); 

        var new_meshPoints = new ActionList();

       

        for (var i = 0; i < meshPoints.count; i++)

            {

            if (i != point_index)

                {

                new_meshPoints.putObject(stringIDToTypeID("rationalPoint"), meshPoints.getObjectValue(i));

                }

            else

                {

                var d = new ActionDescriptor();

                d.putUnitDouble(stringIDToTypeID("horizontal"), stringIDToTypeID("pixelsUnit"), hor);

                d.putUnitDouble(stringIDToTypeID("vertical"),   stringIDToTypeID("pixelsUnit"), ver);

                new_meshPoints.putObject(stringIDToTypeID("rationalPoint"), d);

                }

            }

        var customEnvelopeWarp = new ActionDescriptor();

        customEnvelopeWarp.putList(stringIDToTypeID("meshPoints"), new_meshPoints);

        warp.putObject(stringIDToTypeID("customEnvelopeWarp"), stringIDToTypeID("customEnvelopeWarp"), customEnvelopeWarp);

        ///////////////////////////////////////////////////////////////////////////////

        // execute transform command

        var d = new ActionDescriptor();

        d.putEnumerated(stringIDToTypeID("freeTransformCenterState"), stringIDToTypeID("quadCenterState"), stringIDToTypeID("QCSAverage"));

        d.putObject(stringIDToTypeID("warp"), stringIDToTypeID("warp"), warp);

        executeAction(stringIDToTypeID("transform"), d, DialogModes.NO);

        }

    catch (e) { alert(e); }

    }