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
  • 15060 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).

JJMack
Community Expert
Community Expert
February 22, 2018

Ok. You can experiment by replacing "transform" with "nonAffineTransform".
And also explore the "size" and "warp" objects in the smartObjectMore object.

I do not have time for this now )


r-bin  wrote

And also explore the "size" and "warp" objects in the smartObjectMore object.

I do not have time for this now )

I you get some time could you code  functions that one could use to explore a smart objects size and warp.  Like you did for  smart object layers object corners.  As I wrote I can hack some but  I lack the knowledge to use  action manager code to retrieve Photoshop layer related data.  I needed you to tell me to change to "nonAffineTransform" to get the corners I wanted.  You knowledge of what Photoshop has and how to get at it is knowledge I do not expect to acquire in my lifetime I'm 77 and slowing down.  Your four corners function help me do some smart object layer exploring. Thank you

// Explore Smart Object Layer's 4 corner-points (x,y)

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

if (app.activeDocument.activeLayer.kind!=LayerKind.SMARTOBJECT) alert("ActiveLayer not Smart Object Layer");

else {

var orig_ruler_units = app.preferences.rulerUnits;

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

clearGuides();                              // Clear Canvas Guides

var points = get_smart_object_corners();    // Get Smart Object layers corners

app.activeDocument.selection.select(points);// Set new selection  using layers corners

    // Mark their (x,y)

MarkX( points[0][0]);

MarkY( points[0][1]);

MarkX( points[1][0]);

MarkY( points[1][1]);

MarkX( points[2][0]);

MarkY( points[2][1]);

MarkX( points[3][0]);

MarkY( points[3][1]);

// get the slope and length of the layers sides 0 is horizontal 90 is vertical

var w = points[0][0] - points[1][0];

var h = points[0][1] - points[1][1];

var l0 = Math.sqrt(Math.pow(w,2)+Math.pow(h,2));

var angle0 = Math.atan(h/w) * 180.0 / Math.PI;

var w = points[1][0] - points[2][0] ;

var h = points[1][1] - points[2][1] ;

var l1 = Math.sqrt(Math.pow(w,2)+Math.pow(h,2));

var angle1 = Math.atan(h/w) * 180.0 / Math.PI;

var w = points[2][0] - points[3][0] ;

var h = points[2][1] - points[3][1] ;

var l2 = Math.sqrt(Math.pow(w,2)+Math.pow(h,2));

var angle2 = Math.atan(h/w) * 180.0 / Math.PI;

var w = points[3][0] - points[0][0] ;

var h = points[3][1] - points[0][1] ;

var l3 = Math.sqrt(Math.pow(w,2)+Math.pow(h,2));

var angle3 = Math.atan(h/w) * 180.0 / Math.PI;

//prerimmeter length

var l4 = l0+l1+l2+l3;

    //show the user this information

alert( Math.round(points[0][0]) + ", " +  Math.round(points[0][1]) + " "

+ angle0.](0) + "° " + l0.toFixed(2) +"\n\n"

+ Math.round(points[1][0]) + ", " +  Math.round(points[1][1]) + " "

  + angle1.toFixed(1) + "° " + l1.toFixed(2) +"\n\n"

+ Math.round(points[2][0]) + ", " +  Math.round(points[2][1]) + " "

+ angle2.toFixed(1) + "° " + l2.toFixed(2) +"\n\n"

+ Math.round(points[3][0]) + ", " +  Math.round(points[3][1]) + " "

+ angle3.toFixed(1) + "° " + l3.toFixed(2) +"\n\n"

+ l4.toFixed(2));

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

}

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

// function get_smart_object_corners() returns array from 4 corner-points (x,y)

// of smart object in pixels (value with floating point) https://forums.adobe.com/people/r-bin

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

function get_smart_object_corners() {

    try

        {

        var r = new ActionReference();

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

        var d;

        try { d = executeActionGet(r); } catch (e) { alert(e); return; }

        try { d = d.getObjectValue(stringIDToTypeID("smartObjectMore"));    } catch (e) { alert(e); return; }

        try { d = d.getList(stringIDToTypeID("nonAffineTransform"));                 } catch (e) { alert(e); return; }

        var ret = [[d.getDouble(0),d.getDouble(1)],

                   [d.getDouble(2),d.getDouble(3)],

                   [d.getDouble(4),d.getDouble(5)],

                   [d.getDouble(6),d.getDouble(7)]];

        return ret;

        }

    catch (e) { alert(e); }

}

function clearGuides() {

   var id556 = charIDToTypeID( "Dlt " );

       var desc102 = new ActionDescriptor();

       var id557 = charIDToTypeID( "null" );

           var ref70 = new ActionReference();

           var id558 = charIDToTypeID( "Gd  " );

           var id559 = charIDToTypeID( "Ordn" );

           var id560 = charIDToTypeID( "Al  " );

           ref70.putEnumerated( id558, id559, id560 );

       desc102.putReference( id557, ref70 );

   executeAction( id556, desc102, DialogModes.NO );

};

function MarkX(x) {

// =======================================================

var idMk = charIDToTypeID( "Mk  " );

    var desc61 = new ActionDescriptor();

    var idNw = charIDToTypeID( "Nw  " );

        var desc62 = new ActionDescriptor();

        var idPstn = charIDToTypeID( "Pstn" );

        var idPxl = charIDToTypeID( "#Pxl" );

        desc62.putUnitDouble( idPstn, idPxl, x);

        var idOrnt = charIDToTypeID( "Ornt" );

        var idOrnt = charIDToTypeID( "Ornt" );

        var idVrtc = charIDToTypeID( "Vrtc" );

        desc62.putEnumerated( idOrnt, idOrnt, idVrtc );

    var idGd = charIDToTypeID( "Gd  " );

    desc61.putObject( idNw, idGd, desc62 );

executeAction( idMk, desc61, DialogModes.NO );

}

function MarkY(y) {

// =======================================================

var idMk = charIDToTypeID( "Mk  " );

    var desc63 = new ActionDescriptor();

    var idNw = charIDToTypeID( "Nw  " );

        var desc64 = new ActionDescriptor();

        var idPstn = charIDToTypeID( "Pstn" );

        var idPxl = charIDToTypeID( "#Pxl" );

        desc64.putUnitDouble( idPstn, idPxl, y );

        var idOrnt = charIDToTypeID( "Ornt" );

        var idOrnt = charIDToTypeID( "Ornt" );

        var idHrzn = charIDToTypeID( "Hrzn" );

        desc64.putEnumerated( idOrnt, idOrnt, idHrzn );

    var idGd = charIDToTypeID( "Gd  " );

    desc63.putObject( idNw, idGd, desc64 );

executeAction( idMk, desc63, DialogModes.NO );

}

JJMack