Copy link to clipboard
Copied
First fit the selected layer according to the layer below then rotate the selected layer according to the position the layer below is rotated.
// Set ruler units to pixels
var oldPref = app.preferences.rulerUnits;
app.preferences.rulerUnits = Units.PIXELS;
// Get active document and layers
var doc = activeDocument;
var iLayer = doc.activeLayer;
// Function to select the layer below
function layerDown() {
var idslct = charIDToTypeID("slct");
var desc2 = new ActionDescriptor();
var idnull = charIDToTypeID("null");
var ref1 = new ActionReference();
var idLyr = charIDToTypeID("Lyr ");
var idOrdn = charIDToTypeID("Ordn");
var idBckw = charIDToTypeID("Bckw");
ref1.putEnumerated(idLyr, idOrdn, idBckw);
desc2.putReference(idnull, ref1);
executeAction(idslct, desc2, DialogModes.NO);
}
// Call the function to select the layer below
layerDown();
// Get the bounds of the layer below
var mLayerB = doc.activeLayer.bounds;
// Fit the selected layer according to the layer below
var scale = Math.max((mLayerB[2] - mLayerB[0]) / (iLayer.bounds[2] - iLayer.bounds[0]), (mLayerB[3] - mLayerB[1]) / (iLayer.bounds[3] - iLayer.bounds[1]));
iLayer.resize(scale * 100, scale * 100);
iLayer.translate((mLayerB[0] + mLayerB[2]) / 2 - (iLayer.bounds[0] + iLayer.bounds[2]) / 2, (mLayerB[1] + mLayerB[3]) / 2 - (iLayer.bounds[1] + iLayer.bounds[3]) / 2);
// Function to get the rotation angle of a layer
function getLayerRotation(layer) {
var idslct = charIDToTypeID("slct");
var desc = new ActionDescriptor();
var ref = new ActionReference();
ref.putEnumerated(charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt"));
desc.putReference(charIDToTypeID("null"), ref);
var result = executeAction(charIDToTypeID("getd"), desc, DialogModes.NO);
var rotation = 0;
if (result.hasKey(stringIDToTypeID("transform"))) {
var transform = result.getObjectValue(stringIDToTypeID("transform"));
if (transform.hasKey(stringIDToTypeID("rotation"))) {
rotation = transform.getDouble(stringIDToTypeID("rotation"));
}
}
return rotation;
}
// Get the rotation of the layer below
var mLayerRotation = getLayerRotation(doc.activeLayer);
// Function to rotate the layer
function rotateLayer(layer, angle) {
var idtrns = charIDToTypeID("Trnf");
var desc = new ActionDescriptor();
var idnull = charIDToTypeID("null");
var ref = new ActionReference();
ref.putEnumerated(charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt"));
desc.putReference(idnull, ref);
var idtarg = charIDToTypeID("TlrP");
var desc2 = new ActionDescriptor();
desc2.putUnitDouble(charIDToTypeID("Angl"), charIDToTypeID("#Ang"), angle);
desc.putObject(idtarg, idtrns, desc2);
executeAction(idtrns, desc, DialogModes.NO);
}
// Rotate the selected layer to match the layer below
rotateLayer(iLayer, mLayerRotation);
// Restore the original ruler units
app.preferences.rulerUnits = oldPref;
Copy link to clipboard
Copied
Could you please post screenshots with the pertinent Panels (Toolbar, Layers, Options Bar, …) visible?
Is the lower Layer a Smart Object? If it is not, but rather a plain pixel Layer, the concept of »rotation« would not apply because the Bounds define a rectangle with vertical and horicontal sides.
Copy link to clipboard
Copied
Copy link to clipboard
Copied
This code can be used to determine the rotation of a selected Smart Object.
// get keys for smart objects;
// based on code by michael l hale;
// 2024, use it at your own risk;
if (app.documents.length > 0) {
var ref = new ActionReference();
ref.putEnumerated( charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );
var layerDesc = executeActionGet(ref);
var soDesc = layerDesc.getObjectValue(stringIDToTypeID('smartObject'));
var soMoreDesc = layerDesc.getObjectValue(stringIDToTypeID('smartObjectMore'));
var placedDesc = soDesc.getEnumerationValue(stringIDToTypeID('placed'));
var theFileRef = soDesc.getString(stringIDToTypeID('fileReference'));
var theDocID = soDesc.getString(stringIDToTypeID('documentID'));
var size = soMoreDesc.getObjectValue(stringIDToTypeID('size'));
//checkDesc2 (soMoreDesc);
var transform = soMoreDesc.getList(stringIDToTypeID("transform"));
var xx = new Array;
for (var m = 0; m < transform.count; m++) {
xx.push(transform.getDouble(m))
};
//alert ("transform\n"+xx.join("\n\n")+"\n\nangle "+getAngle([xx[0], xx[1]], [xx[2], xx[3]]));
var nonAffineTransform = soMoreDesc.getList(stringIDToTypeID("nonAffineTransform"));
var yy = new Array;
for (var n = 0; n < nonAffineTransform.count; n++) {
yy.push(nonAffineTransform.getDouble(n))
};
alert ("nonaffinetransform\n"+yy.join("\n\n")+"\n\nangle "+getAngle([yy[6], yy[7]], [yy[4], yy[5]]));
};
//////
////// radians //////
function radiansOf (theAngle) {
return theAngle * Math.PI / 180
};
////// get an angle, 3:00 being 0˚, 6:00 90˚, etc. //////
function getAngle (pointOne, pointTwo) {
// calculate the triangle sides;
var width = pointTwo[0] - pointOne[0];
var height = pointTwo[1] - pointOne[1];
var sideC = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2));
// calculate the angles;
if (width+width > width) {theAngle = Math.asin(height / sideC) * 360 / 2 / Math.PI}
else {theAngle = 180 - (Math.asin(height / sideC) * 360 / 2 / Math.PI)};
if (theAngle < 0) {theAngle = (360 + theAngle)};
// if (theAngle > 180) {theAngle = (360 - theAngle) * (-1)};
return theAngle
};
Copy link to clipboard
Copied
thanks sr you replied
The sr layer is not rotated. The script only shows the alert angle
sr I don't understand what should I do. I feel like I am doing something wrong
Copy link to clipboard
Copied
You should use the number/s to rotate the Layer you want to rotate.
I did not create a Script for you, I gave you code to demonstrate how to determine a Smart Object’s angle.
Copy link to clipboard
Copied
https://drive.google.com/file/d/1K8_nQyY7WxL1hM-4Xsymhq3v_OjGYuLk/view?usp=sharing
Hi sir I want to show you a video. Download and watch this video. In this video, if you look in the Photoshop layer panel, you will understand that even though the smart object is not a layer, the layer is rotated.
Copy link to clipboard
Copied
I don’t understand what you mean.
Does the »Show transform controls«-setting of the Move Tool confuse the issue?
Copy link to clipboard
Copied
I don't know much about photoshop java scripting. Sir you are wiser than us you understand more than us. I also can't understand, I am also confused. How can the selected layer from the script be rotated according to the following layer. Is this possible?
Copy link to clipboard
Copied
https://drive.google.com/file/d/1VjpEQQAnxF2trC58dnCikijvckZcTPaX/view?usp=sharing.
Sir this is an example so you can understand what I want to explain to you
Copy link to clipboard
Copied
// rotate, scale and move layer according to smart object immediately below;
// 2024, use it at your own risk;
if (app.documents.length > 0) {
var originalRulerUnits = app.preferences.rulerUnits;
app.preferences.rulerUnits = Units.PIXELS;
// check for background layer;
var ref = new ActionReference();
ref.putEnumerated( charIDToTypeID("Dcmn"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );
var desc = executeActionGet(ref);
if (desc.getBoolean(stringIDToTypeID("hasBackgroundLayer")) == true) {var theAdd = -1}
else {var theAdd = 0};
// get the index;
var ref = new ActionReference();
ref.putEnumerated( charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );
var layerDesc = executeActionGet(ref);
var theIndex = layerDesc.getInteger(stringIDToTypeID('itemIndex'));
var theID = layerDesc.getInteger(stringIDToTypeID('layerID'));
// the angles;
var currentAngle = getAngleOfLayer ();
selectLayerByIndex(theIndex + theAdd - 1, false);
var theAngle = getAngleOfLayer ();
selectLayerByIndex(theIndex + theAdd, false);
if (currentAngle != undefined && theAngle != undefined) {
// rotate;
layerDuplicateScaleRotate (theID, false, theAngle[1] - currentAngle[1], theAngle[2] - currentAngle[2], theAngle[3]/currentAngle[3]*100, theAngle[3]/currentAngle[3]*100, theAngle[0] - currentAngle[0]);
};
// reset;
app.preferences.rulerUnits = originalRulerUnits;
};
////////////////////////////////////
////// get angle //////
function getAngleOfLayer () {
try {
var ref = new ActionReference();
ref.putEnumerated( charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );
var layerDesc = executeActionGet(ref);
var theName = layerDesc.getString(stringIDToTypeID('name'));
var soDesc = layerDesc.getObjectValue(stringIDToTypeID('smartObject'));
var soMoreDesc = layerDesc.getObjectValue(stringIDToTypeID('smartObjectMore'));
var placedDesc = soDesc.getEnumerationValue(stringIDToTypeID('placed'));
var theFileRef = soDesc.getString(stringIDToTypeID('fileReference'));
var theDocID = soDesc.getString(stringIDToTypeID('documentID'));
var size = soMoreDesc.getObjectValue(stringIDToTypeID('size'));
var transform = soMoreDesc.getList(stringIDToTypeID("transform"));
var xx = new Array;
for (var m = 0; m < transform.count; m++) {
xx.push(transform.getDouble(m))
};
var nonAffineTransform = soMoreDesc.getList(stringIDToTypeID("nonAffineTransform"));
var yy = new Array;
for (var n = 0; n < nonAffineTransform.count; n++) {
yy.push(nonAffineTransform.getDouble(n))
};
var theX = yy[0] + (yy[4] - yy[0])/2;
var theY = yy[1] + (yy[5] - yy[1])/2;
var aWidth = yy[2] - yy[0];
var aHeight = yy[3] - yy[1];
var theWidth = Math.sqrt(aWidth*aWidth + aHeight*aHeight);
return [getAngle([yy[6], yy[7]], [yy[4], yy[5]]), theX, theY, theWidth]
} catch (e) {return undefined}
};
////// radians //////
function radiansOf (theAngle) {
return theAngle * Math.PI / 180
};
////// get an angle, 3:00 being 0˚, 6:00 90˚, etc. //////
function getAngle (pointOne, pointTwo) {
// calculate the triangle sides;
var width = pointTwo[0] - pointOne[0];
var height = pointTwo[1] - pointOne[1];
var sideC = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2));
// calculate the angles;
if (width+width > width) {theAngle = Math.asin(height / sideC) * 360 / 2 / Math.PI}
else {theAngle = 180 - (Math.asin(height / sideC) * 360 / 2 / Math.PI)};
if (theAngle < 0) {theAngle = (360 + theAngle)};
// if (theAngle > 180) {theAngle = (360 - theAngle) * (-1)};
return theAngle
};
// by mike hale, via paul riggott;
function selectLayerByIndex(index,add){
try{
add = undefined ? add = false:add
var ref = new ActionReference();
ref.putIndex(charIDToTypeID("Lyr "), index);
var desc = new ActionDescriptor();
desc.putReference(charIDToTypeID("null"), ref );
if(add) desc.putEnumerated( stringIDToTypeID( "selectionModifier" ), stringIDToTypeID( "selectionModifierType" ), stringIDToTypeID( "addToSelection" ) );
desc.putBoolean( charIDToTypeID( "MkVs" ), false );
//try{
executeAction(charIDToTypeID("slct"), desc, DialogModes.NO );
}catch(e){
alert(e.message);
}
};
////// duplicate layer (id, xOffset, yOffset, theXScale, theYScale, theAngle) //////
function layerDuplicateScaleRotate (theID, theDuplicate, xOffset, yOffset, theXScale, theYScale, theAngle) {
// based on code by mike hale, via paul riggott;
var ref = new ActionReference();
ref.putIdentifier(charIDToTypeID("Lyr "), theID);
var desc = new ActionDescriptor();
desc.putReference(charIDToTypeID("null"), ref );
desc.putBoolean( charIDToTypeID( "MkVs" ), false );
try{
executeAction(charIDToTypeID("slct"), desc, DialogModes.NO );
}catch(e){
alert(e.message);
};
// =======================================================
var desc23 = new ActionDescriptor();
var idnull = charIDToTypeID( "null" );
var ref2 = new ActionReference();
ref2.putIdentifier ( charIDToTypeID( "Lyr " ), theID );
// ref2.putEnumerated( charIDToTypeID( "Lyr " ), charIDToTypeID( "Ordn" ), charIDToTypeID( "Trgt" ) );
desc23.putReference( idnull, ref2 );
desc23.putEnumerated( charIDToTypeID( "FTcs" ), charIDToTypeID( "QCSt" ), charIDToTypeID( "Qcsa" ) );
var idOfst = charIDToTypeID( "Ofst" );
var desc24 = new ActionDescriptor();
var idPxl = charIDToTypeID( "#Pxl" );
desc24.putUnitDouble( charIDToTypeID( "Hrzn" ), idPxl, xOffset );
desc24.putUnitDouble( charIDToTypeID( "Vrtc" ), idPxl, yOffset );
var idOfst = charIDToTypeID( "Ofst" );
desc23.putObject( idOfst, idOfst, desc24 );
var idPrc = charIDToTypeID( "#Prc" );
desc23.putUnitDouble( charIDToTypeID( "Wdth" ), idPrc, theXScale );
desc23.putUnitDouble( charIDToTypeID( "Hght" ), idPrc, theYScale );
desc23.putUnitDouble( charIDToTypeID( "Angl" ), charIDToTypeID( "#Ang" ), theAngle );
desc23.putEnumerated( charIDToTypeID( "Intr" ), charIDToTypeID( "Intp" ), stringIDToTypeID( "bicubicAutomatic" ) );
desc23.putBoolean( charIDToTypeID( "Cpy " ), theDuplicate );
executeAction( charIDToTypeID( "Trnf" ), desc23, DialogModes.NO );
};
////// get a distance between two points //////
function getDistance (pointOne, pointTwo) {
// calculate the triangle sides;
var width = pointTwo[0] - pointOne[0];
var height = pointTwo[1] - pointOne[1];
var sideC = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2));
return sideC
};
Copy link to clipboard
Copied
I don't know much about photoshop java scripting. Sir you are wiser than us you understand more than us. I also can't understand, I am also confused. How can the selected layer from the script be rotated according to the following layer. Is this possible?
By @MM258920690p77
The following code would rotate a Layer to the angle of the Smart Object immediately below it (see screenshots).
If you need to additionally scale and move the Layer then feel free to amend the Script accordingly.
The relevant infomation is already being assessed in the function »getAngleOfLayer« as far as I can tell.
// rotate layer to angle of smart object immediately below;
// 2024, use it at your own risk;
if (app.documents.length > 0) {
var originalRulerUnits = app.preferences.rulerUnits;
app.preferences.rulerUnits = Units.PIXELS;
// check for background layer;
var ref = new ActionReference();
ref.putEnumerated( charIDToTypeID("Dcmn"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );
var desc = executeActionGet(ref);
if (desc.getBoolean(stringIDToTypeID("hasBackgroundLayer")) == true) {var theAdd = -1}
else {var theAdd = 0};
// get the index;
var ref = new ActionReference();
ref.putEnumerated( charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );
var layerDesc = executeActionGet(ref);
var theIndex = layerDesc.getInteger(stringIDToTypeID('itemIndex'));
var theID = layerDesc.getInteger(stringIDToTypeID('layerID'));
// the angles;
var currentAngle = getAngleOfLayer ();
selectLayerByIndex(theIndex + theAdd - 1, false);
var theAngle = getAngleOfLayer ();
selectLayerByIndex(theIndex + theAdd, false);
if (currentAngle != undefined && theAngle != undefined) {
// rotate;
layerDuplicateScaleRotate (theID, false, 0, 0, 100, 100, theAngle - currentAngle);
};
// reset;
app.preferences.rulerUnits = originalRulerUnits;
};
////// get angle //////
function getAngleOfLayer () {
try {
var ref = new ActionReference();
ref.putEnumerated( charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );
var layerDesc = executeActionGet(ref);
var theName = layerDesc.getString(stringIDToTypeID('name'));
var soDesc = layerDesc.getObjectValue(stringIDToTypeID('smartObject'));
var soMoreDesc = layerDesc.getObjectValue(stringIDToTypeID('smartObjectMore'));
var placedDesc = soDesc.getEnumerationValue(stringIDToTypeID('placed'));
var theFileRef = soDesc.getString(stringIDToTypeID('fileReference'));
var theDocID = soDesc.getString(stringIDToTypeID('documentID'));
var size = soMoreDesc.getObjectValue(stringIDToTypeID('size'));
var transform = soMoreDesc.getList(stringIDToTypeID("transform"));
var xx = new Array;
for (var m = 0; m < transform.count; m++) {
xx.push(transform.getDouble(m))
};
var nonAffineTransform = soMoreDesc.getList(stringIDToTypeID("nonAffineTransform"));
var yy = new Array;
for (var n = 0; n < nonAffineTransform.count; n++) {
yy.push(nonAffineTransform.getDouble(n))
};
return getAngle([yy[6], yy[7]], [yy[4], yy[5]])
} catch (e) {return undefined}
};
//////
////// radians //////
function radiansOf (theAngle) {
return theAngle * Math.PI / 180
};
////// get an angle, 3:00 being 0˚, 6:00 90˚, etc. //////
function getAngle (pointOne, pointTwo) {
// calculate the triangle sides;
var width = pointTwo[0] - pointOne[0];
var height = pointTwo[1] - pointOne[1];
var sideC = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2));
// calculate the angles;
if (width+width > width) {theAngle = Math.asin(height / sideC) * 360 / 2 / Math.PI}
else {theAngle = 180 - (Math.asin(height / sideC) * 360 / 2 / Math.PI)};
if (theAngle < 0) {theAngle = (360 + theAngle)};
// if (theAngle > 180) {theAngle = (360 - theAngle) * (-1)};
return theAngle
};
// by mike hale, via paul riggott;
function selectLayerByIndex(index,add){
try{
add = undefined ? add = false:add
var ref = new ActionReference();
ref.putIndex(charIDToTypeID("Lyr "), index);
var desc = new ActionDescriptor();
desc.putReference(charIDToTypeID("null"), ref );
if(add) desc.putEnumerated( stringIDToTypeID( "selectionModifier" ), stringIDToTypeID( "selectionModifierType" ), stringIDToTypeID( "addToSelection" ) );
desc.putBoolean( charIDToTypeID( "MkVs" ), false );
//try{
executeAction(charIDToTypeID("slct"), desc, DialogModes.NO );
}catch(e){
alert(e.message);
}
};
////// duplicate layer (id, xOffset, yOffset, theXScale, theYScale, theAngle) //////
function layerDuplicateScaleRotate (theID, theDuplicate, xOffset, yOffset, theXScale, theYScale, theAngle) {
// based on code by mike hale, via paul riggott;
var ref = new ActionReference();
ref.putIdentifier(charIDToTypeID("Lyr "), theID);
var desc = new ActionDescriptor();
desc.putReference(charIDToTypeID("null"), ref );
desc.putBoolean( charIDToTypeID( "MkVs" ), false );
try{
executeAction(charIDToTypeID("slct"), desc, DialogModes.NO );
}catch(e){
alert(e.message);
};
// =======================================================
var desc23 = new ActionDescriptor();
var idnull = charIDToTypeID( "null" );
var ref2 = new ActionReference();
ref2.putIdentifier ( charIDToTypeID( "Lyr " ), theID );
// ref2.putEnumerated( charIDToTypeID( "Lyr " ), charIDToTypeID( "Ordn" ), charIDToTypeID( "Trgt" ) );
desc23.putReference( idnull, ref2 );
desc23.putEnumerated( charIDToTypeID( "FTcs" ), charIDToTypeID( "QCSt" ), charIDToTypeID( "Qcsa" ) );
var idOfst = charIDToTypeID( "Ofst" );
var desc24 = new ActionDescriptor();
var idPxl = charIDToTypeID( "#Pxl" );
desc24.putUnitDouble( charIDToTypeID( "Hrzn" ), idPxl, xOffset );
desc24.putUnitDouble( charIDToTypeID( "Vrtc" ), idPxl, yOffset );
var idOfst = charIDToTypeID( "Ofst" );
desc23.putObject( idOfst, idOfst, desc24 );
var idPrc = charIDToTypeID( "#Prc" );
desc23.putUnitDouble( charIDToTypeID( "Wdth" ), idPrc, theXScale );
desc23.putUnitDouble( charIDToTypeID( "Hght" ), idPrc, theYScale );
desc23.putUnitDouble( charIDToTypeID( "Angl" ), charIDToTypeID( "#Ang" ), theAngle );
desc23.putEnumerated( charIDToTypeID( "Intr" ), charIDToTypeID( "Intp" ), stringIDToTypeID( "bicubicAutomatic" ) );
desc23.putBoolean( charIDToTypeID( "Cpy " ), theDuplicate );
executeAction( charIDToTypeID( "Trnf" ), desc23, DialogModes.NO );
};