Exit
  • Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
  • 한국 커뮤니티
2

How to batch rotate text layers in place?

Community Beginner ,
Sep 25, 2023 Sep 25, 2023

Question: There are thousands of text layers in my PS document, and now I need to rotate all the text 180 degrees in place. Please tell me how to operate? I don’t want to rotate them one by one. Thank you so much.

TOPICS
Windows
2.6K
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 1 Correct answer

Community Expert , Sep 26, 2023 Sep 26, 2023

Please try this version: 

// rotate all type layers;
// 2023, use it at your own risk;
if (app.documents.length > 0) {
var theLayers = collectTypeLayers();
for (var m = 0; m < theLayers.length; m++) {
if (theLayers[m][2] == false) {
showHideLayer (theLayers[m][1], "show");
};
selectLayerByID(theLayers[m][1], false);
scaleRotateLayer (100, 180, 0, 0);
if (theLayers[m][2] == false) {
showHideLayer (theLayers[m][1], "hide")
};
}
};
////////////////////////////////////
function collectTypeLayers () 
...
Translate
Adobe
Community Expert ,
Sep 25, 2023 Sep 25, 2023

We need to know whether text layers are one above another or scattered in the Layers panel. If you have text layers one above another in the Layers panel simple action can do the trick. You will need to select text layer then record step to rotate it. Record step to select next layer above. Duplicate those two steps as many times as you want then play action. If you have thousands layers then duplicate two steps hundred times and play action several times for example. It can be little tricky to not play action twice to the same layer so watch what is going on in the Layers panel.

 

There are some tricks you can use to avoid playing rotate on the same layer twice but that will require Conditional actions which are more advanced.

 

Here is example that provides a straightforward approach to automating tasks in Photoshop using a two-step action that can be duplicated as needed. For more complex actions, the use of Conditional actions or scripts may be necessary. I recommend reaching out to experienced scripters who can offer further assistance @Stephen Marsh @c.pfaffenbichler 

rotate text layer action.png

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Sep 26, 2023 Sep 26, 2023

@Bojan Živković Thank you very much for your patient help. My problem @c.pfaffenbichler  has been solved for me. Thank you again. I wish you a happy life and happiness every day!

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Sep 26, 2023 Sep 26, 2023

Please try this (updated): 

// rotate all type layers;
// 2023, use it at your own risk;
if (app.documents.length > 0) {
var theLayers = collectTypeLayers();
for (var m = 0; m < theLayers.length; m++) {
selectLayerByID(theLayers[m][1], false);
scaleRotateLayer (100, 180, 0, 0)
}
};
////////////////////////////////////
function collectTypeLayers () {
// the file;
var myDocument = app.activeDocument;
// get number of layers;
var ref = new ActionReference();
ref.putEnumerated( charIDToTypeID("Dcmn"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") ); 
var applicationDesc = executeActionGet(ref);
var theNumber = applicationDesc.getInteger(stringIDToTypeID("numberOfLayers"));
// process the layers;
var theLayers = new Array;
for (var m = 0; m <= theNumber; m++) {
try {
var ref = new ActionReference();
ref.putIndex( charIDToTypeID( "Lyr " ), m);
var layerDesc = executeActionGet(ref);
var layerSet = typeIDToStringID(layerDesc.getEnumerationValue(stringIDToTypeID("layerSection")));
var isBackground = layerDesc.getBoolean(stringIDToTypeID("background"));
// if not layer group collect values;
if (layerSet != "layerSectionEnd" && layerSet != "layerSectionStart" && isBackground != true && layerDesc.hasKey(stringIDToTypeID("textKey")) == true) {
var theName = layerDesc.getString(stringIDToTypeID('name'));
var theID = layerDesc.getInteger(stringIDToTypeID('layerID'));
theLayers.push([theName, theID])
};
}
catch (e) {};
};
return theLayers
};
// based on code by mike hale, via paul riggott;
function selectLayerByID(id,add){ 
add = undefined ? add = false:add 
var ref = new ActionReference();
    ref.putIdentifier(charIDToTypeID("Lyr "), id);
    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); 
}
};
////// scale active layer to canvas dimensions //////
function scaleRotateLayer (theScale, theAngle, offsetX, offsetY) {
try {
// scale layer:
var originalRulerUnits = app.preferences.rulerUnits;
app.preferences.rulerUnits = Units.PIXELS;
// transform;
var desc23 = new ActionDescriptor();
var ref2 = new ActionReference();
ref2.putEnumerated( charIDToTypeID( "Lyr " ), charIDToTypeID( "Ordn" ), charIDToTypeID( "Trgt" ) );
desc23.putReference( charIDToTypeID( "null" ), ref2 );
var idOfst = charIDToTypeID( "Ofst" );
var desc24 = new ActionDescriptor();
var idPxl = charIDToTypeID( "#Pxl" );
desc24.putUnitDouble( charIDToTypeID( "Hrzn" ), idPxl, offsetX );
desc24.putUnitDouble( charIDToTypeID( "Vrtc" ), idPxl, offsetY );
desc23.putObject( idOfst, idOfst, desc24 );
var idPrc = charIDToTypeID( "#Prc" );
desc23.putUnitDouble( charIDToTypeID( "Wdth" ), idPrc, theScale );
desc23.putUnitDouble( charIDToTypeID( "Hght" ), idPrc, theScale );
desc23.putUnitDouble( charIDToTypeID( "Angl" ), charIDToTypeID( "#Ang" ), theAngle );
desc23.putEnumerated( charIDToTypeID( "Intr" ), charIDToTypeID( "Intp" ), stringIDToTypeID( "bicubicAutomatic" ) );
desc23.putEnumerated( stringIDToTypeID( "freeTransformCenterState" ), stringIDToTypeID( "quadCenterState" ), stringIDToTypeID( "QCSAverage" ) );
//            desc23.putBoolean( charIDToTypeID( "Cpy " ), true );
executeAction( charIDToTypeID( "Trnf" ), desc23, DialogModes.NO );
app.preferences.rulerUnits = originalRulerUnits;
} catch (e) {}
};

 

 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Sep 26, 2023 Sep 26, 2023

@c.pfaffenbichler 

 

Nice one, you beat me to it! As I have already started my coding, I may as well post it anyway once I've completed it...

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Sep 26, 2023 Sep 26, 2023

This script only rotates text layers 180° if they are a top-level layer (i.e. not in a layer set or nested set in set).

 

/*
Rotate All Top Level Text Layers 180 degrees.jsx
https://community.adobe.com/t5/photoshop-ecosystem-discussions/how-to-batch-rotate-text-layers-in-place/td-p/14112213
v1.0, 26th September 2023, Stephen Marsh
*/

#target photoshop

function main() {
    // Hack to ensure that a layer is selected
    activeDocument.artLayers.add();
    activeDocument.activeLayer.remove();
    var counter = 0;
    // Start Timer
    var timeDiff = {
        setStartTime: function () {
            d = new Date();
            time = d.getTime();
        },
        getDiff: function () {
            d = new Date();
            t = d.getTime() - time;
            time = d.getTime();
            return t;
        }
    };
    timeDiff.setStartTime();
    // Loop over the text layers and rotate them
    for (var i = 0; i < activeDocument.layers.length; i++) {
        try {
            activeDocument.activeLayer = activeDocument.layers[i];
            if (app.activeDocument.activeLayer.kind == LayerKind.TEXT) {
                transformRotate(180);
                counter++;
            }
        } catch (e) {}
    }
    alert(counter + " text layers rotated!" + "\r" + "Run Time: " + timeDiff.getDiff() / 1000 + " seconds");
}
activeDocument.suspendHistory("Rotate All Top Level Text Layers 180 degrees...", "main()");


function transformRotate(angle) {
    function s2t(s) {
        return app.stringIDToTypeID(s);
    }
    var descriptor = new ActionDescriptor();
    descriptor.putUnitDouble(s2t("angle"), s2t("angleUnit"), angle);
    executeAction(s2t("rotateEventEnum"), descriptor, DialogModes.NO);
}

 

I'll post updated code to work with groups/sets later.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Sep 26, 2023 Sep 26, 2023

This one will process text layers within layer groups and nested layer groups:

 

/*
Rotate All Text Layers 180 degrees.jsx
https://community.adobe.com/t5/photoshop-ecosystem-discussions/how-to-batch-rotate-text-layers-in-place/td-p/14112213
v1.0, 26th September 2023, Stephen Marsh
*/

#target photoshop

activeDocument.suspendHistory('Rotate All Text Layers 180 degrees.jsx', 'main()');

function main() {
    if (!documents.length) {
        alert('There are no documents open!');
    } else {
        var counter = 0;
        // Start Timer
        var timeDiff = {
            setStartTime: function () {
                d = new Date();
                time = d.getTime();
            },
            getDiff: function () {
                d = new Date();
                t = d.getTime() - time;
                time = d.getTime();
                return t;
            }
        };
        timeDiff.setStartTime();
        processAllLayersAndSets(app.activeDocument);
        alert(counter + " text layers rotated!" + "\r" + "Run Time: " + timeDiff.getDiff() / 1000 + " seconds");
    }

    function processAllLayersAndSets(obj) {
        // Process Layers 
        for (var i = obj.artLayers.length - 1; 0 <= i; i--) {
            app.activeDocument.activeLayer = obj.artLayers[i];
            if (app.activeDocument.activeLayer.kind == LayerKind.TEXT) {
                transformRotate(180);
                counter++;
            }
        }
        // Process Layer Set Layers 
        for (var j = obj.layerSets.length - 1; 0 <= j; j--) {
            processAllLayersAndSets(obj.layerSets[j]);
        }
    }

    function transformRotate(angle) {
        function s2t(s) {
            return app.stringIDToTypeID(s);
        }
        var descriptor = new ActionDescriptor();
        descriptor.putUnitDouble(s2t("angle"), s2t("angleUnit"), angle);
        executeAction(s2t("rotateEventEnum"), descriptor, DialogModes.NO);
    }
}

 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Sep 26, 2023 Sep 26, 2023

@Stephen Marsh 

Thank you very much. I tried it just now, but an error occurred and the rotation was unsuccessful. Figure 2 is my document.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Sep 26, 2023 Sep 26, 2023

@LiuFei刘飞 – What version of Photoshop are you using?

 

You can try replacing the function with slightly different code, but this is based off v2021 as the previous, so may still have issues in your version:

 

 

function transformRotate(angle) {
    var desc1 = new ActionDescriptor();
    desc1.putUnitDouble(cTID('Angl'), cTID('#Ang'), angle);
    executeAction(cTID('Rtte'), desc1, DialogModes.NO);
}

 

 

This function was created in v2022:

 

 

function transformRotate(angle) {
	var s2t = function (s) {
		return app.stringIDToTypeID(s);
	};
	var descriptor = new ActionDescriptor();
	var reference = new ActionReference();
	reference.putEnumerated( s2t( "layer" ), s2t( "ordinal" ), s2t( "targetEnum" ));
	descriptor.putReference( s2t( "null" ), reference );
	descriptor.putUnitDouble( s2t( "angle" ), s2t( "angleUnit" ), angle );
	executeAction( s2t( "rotateEventEnum" ), descriptor, DialogModes.NO );
}

 

 

Or another one from v2022:

 

function transformRotate(angle) {
var idrotateEventEnum = stringIDToTypeID( "rotateEventEnum" );
    var desc278 = new ActionDescriptor();
    var idangle = stringIDToTypeID( "angle" );
    var idangleUnit = stringIDToTypeID( "angleUnit" );
    desc278.putUnitDouble( idangle, idangleUnit, angle );
executeAction( idrotateEventEnum, desc278, DialogModes.NO );
}
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Sep 26, 2023 Sep 26, 2023

@Stephen Marsh 24.7.0

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Sep 26, 2023 Sep 26, 2023

@Stephen Marsh Thank you for your patience and help. I don’t know English and I used a translation software to translate it. The expression may not be very accurate.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Sep 26, 2023 Sep 26, 2023

@LiuFei刘飞 

 

The following function was recorded and tested in the latest v2024:

 

function transformRotate(angle) {
var idrotateEventEnum = stringIDToTypeID( "rotateEventEnum" );
    var desc226 = new ActionDescriptor();
    var idnull = stringIDToTypeID( "null" );
        var ref1 = new ActionReference();
        var idlayer = stringIDToTypeID( "layer" );
        var idordinal = stringIDToTypeID( "ordinal" );
        var idtargetEnum = stringIDToTypeID( "targetEnum" );
        ref1.putEnumerated( idlayer, idordinal, idtargetEnum );
    desc226.putReference( idnull, ref1 );
    var idangle = stringIDToTypeID( "angle" );
    var idangleUnit = stringIDToTypeID( "angleUnit" );
    desc226.putUnitDouble( idangle, idangleUnit, angle );
executeAction( idrotateEventEnum, desc226, DialogModes.NO );
}

 

 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Sep 26, 2023 Sep 26, 2023

@Stephen Marsh I can’t write scripts and I can’t read scripts. I copied the last piece of code you sent me into notepad and saved it as .jsx, then browsed the file in PS. I noticed nothing happened. Is this just a piece of code? I can't understand the code. You can send me all the code together. Sorry for the trouble, thank you very much.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Sep 26, 2023 Sep 26, 2023

You can also try the one I posted. 

Save the code as a txt-file, change the extension to .jsx and copy it into Photoshop’s Presets/Scripts-Folder; after restarting Photoshop it should be available under File > Scripts and can be assigned a Shortcut or used in an Action. 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Sep 26, 2023 Sep 26, 2023

@c.pfaffenbichler OK, I'll try it, thank you very much

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Sep 26, 2023 Sep 26, 2023

@c.pfaffenbichler Still not working, am I too stupid and using the wrong method? Take a look at the attached screenshot I sent

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Sep 26, 2023 Sep 26, 2023

You had not mentioned that there are hidden Type Layers. 

I updated the code with a try-clause that will not rotate them but at least will not stop because of them. 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Sep 26, 2023 Sep 26, 2023

Please try this version: 

// rotate all type layers;
// 2023, use it at your own risk;
if (app.documents.length > 0) {
var theLayers = collectTypeLayers();
for (var m = 0; m < theLayers.length; m++) {
if (theLayers[m][2] == false) {
showHideLayer (theLayers[m][1], "show");
};
selectLayerByID(theLayers[m][1], false);
scaleRotateLayer (100, 180, 0, 0);
if (theLayers[m][2] == false) {
showHideLayer (theLayers[m][1], "hide")
};
}
};
////////////////////////////////////
function collectTypeLayers () {
// the file;
var myDocument = app.activeDocument;
// get number of layers;
var ref = new ActionReference();
ref.putEnumerated( charIDToTypeID("Dcmn"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") ); 
var applicationDesc = executeActionGet(ref);
var theNumber = applicationDesc.getInteger(stringIDToTypeID("numberOfLayers"));
// process the layers;
var theLayers = new Array;
for (var m = 0; m <= theNumber; m++) {
try {
var ref = new ActionReference();
ref.putIndex( charIDToTypeID( "Lyr " ), m);
var layerDesc = executeActionGet(ref);
var layerSet = typeIDToStringID(layerDesc.getEnumerationValue(stringIDToTypeID("layerSection")));
var isBackground = layerDesc.getBoolean(stringIDToTypeID("background"));
// if not layer group collect values;
if (layerSet != "layerSectionEnd" && layerSet != "layerSectionStart" && isBackground != true && layerDesc.hasKey(stringIDToTypeID("textKey")) == true) {
var visible = layerDesc.getBoolean(stringIDToTypeID("visible"));
var theName = layerDesc.getString(stringIDToTypeID('name'));
var theID = layerDesc.getInteger(stringIDToTypeID('layerID'));
theLayers.push([theName, theID, visible])
};
}
catch (e) {};
};
return theLayers
};
// based on code by mike hale, via paul riggott;
function selectLayerByID(id,add){ 
add = undefined ? add = false:add 
var ref = new ActionReference();
    ref.putIdentifier(charIDToTypeID("Lyr "), id);
    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); 
}
};
////// scale active layer to canvas dimensions //////
function scaleRotateLayer (theScale, theAngle, offsetX, offsetY) {
try {
// scale layer:
var originalRulerUnits = app.preferences.rulerUnits;
app.preferences.rulerUnits = Units.PIXELS;
// transform;
var desc23 = new ActionDescriptor();
var ref2 = new ActionReference();
ref2.putEnumerated( charIDToTypeID( "Lyr " ), charIDToTypeID( "Ordn" ), charIDToTypeID( "Trgt" ) );
desc23.putReference( charIDToTypeID( "null" ), ref2 );
var idOfst = charIDToTypeID( "Ofst" );
var desc24 = new ActionDescriptor();
var idPxl = charIDToTypeID( "#Pxl" );
desc24.putUnitDouble( charIDToTypeID( "Hrzn" ), idPxl, offsetX );
desc24.putUnitDouble( charIDToTypeID( "Vrtc" ), idPxl, offsetY );
desc23.putObject( idOfst, idOfst, desc24 );
var idPrc = charIDToTypeID( "#Prc" );
desc23.putUnitDouble( charIDToTypeID( "Wdth" ), idPrc, theScale );
desc23.putUnitDouble( charIDToTypeID( "Hght" ), idPrc, theScale );
desc23.putUnitDouble( charIDToTypeID( "Angl" ), charIDToTypeID( "#Ang" ), theAngle );
desc23.putEnumerated( charIDToTypeID( "Intr" ), charIDToTypeID( "Intp" ), stringIDToTypeID( "bicubicAutomatic" ) );
desc23.putEnumerated( stringIDToTypeID( "freeTransformCenterState" ), stringIDToTypeID( "quadCenterState" ), stringIDToTypeID( "QCSAverage" ) );
//            desc23.putBoolean( charIDToTypeID( "Cpy " ), true );
executeAction( charIDToTypeID( "Trnf" ), desc23, DialogModes.NO );
app.preferences.rulerUnits = originalRulerUnits;
} catch (e) {}
};
////// show or hide layer //////
function showHideLayer (theId, theOp) {
var idhide = stringIDToTypeID( theOp );
var desc22 = new ActionDescriptor();
var list2 = new ActionList();
var ref8 = new ActionReference();
ref8.putIdentifier( stringIDToTypeID( "layer" ), theId );
list2.putReference( ref8 );
desc22.putList( stringIDToTypeID( "null" ), list2 );
executeAction( idhide, desc22, DialogModes.NO );
};
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Sep 26, 2023 Sep 26, 2023

This version works, you’re awesome. Except for the text in the variable pen shape layer, which is rotated incorrectly, all other text is OK. I just manually change the text in the variable pen shape layer. The text in the normal layer is very good. 90% of the workload has been solved. Thank you very much.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Sep 26, 2023 Sep 26, 2023

I was hoping that you could replace the function block in the original script with the different functions of the same name.

 

 I'll have to do that for you tomorrow.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Sep 26, 2023 Sep 26, 2023

@Stephen Marsh I still didn't get it right, maybe I'm a little stupid and don't know if I'm doing it right.
Thank you very much for your patient guidance. I'm from China, it's night now, I wonder which country are you friends from?

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Sep 26, 2023 Sep 26, 2023

My document is very large, with nearly 10,000 text layers. I need to convert the image 180 degrees from north to south, but the text is upside down. It is too tiring to do it one by one manually, so I want to use a simple method to batch rotate 180 degrees.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Sep 26, 2023 Sep 26, 2023

@Stephen Marsh Thank you very much for your patient help. My problem @c.pfaffenbichler  has been solved for me. Thank you again. I wish you a happy life and happiness every day!

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Sep 26, 2023 Sep 26, 2023
LATEST
quote

@Stephen Marsh Thank you very much for your patient help. My problem @c.pfaffenbichler  has been solved for me. Thank you again. I wish you a happy life and happiness every day!


By @LiuFei刘飞

 

You're welcome, I didn't expect you to have hidden text layers, my code makes them visible.

 

Please mark the answer from @c.pfaffenbichler as the correct answer.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines