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

Convert all notes/annotations to text layers in Photoshop scripting

Participant ,
Nov 17, 2022 Nov 17, 2022

Hey! 

Does anyone have an existing script for converting all notes/annotations to text layers?
It can be all notes to a single text layer or multiple.
I currently have a script to select all text layers, send them to a group, search their contents for keywords, and create a txt file if they contain the keywords. I am looking to add a snippet of code to the top of this script in order to cover the off chance a note/annotation was used instead of a text layer.

Looking through the Adobe Javascript Ref 2020 document, I did not see anything in the native DOM for adobe, so I am assuming this will be an AM event. 

If it helps, here is the code for creating a note I copied from ScriptListener/Clean SL. 

select3(true, true);
function select3(dontRecord, forceNotify) {
	var c2t = function (s) {
		return app.charIDToTypeID(s);
	};

	var s2t = function (s) {
		return app.stringIDToTypeID(s);
	};

	var descriptor = new ActionDescriptor();
	var reference = new ActionReference();

	reference.putClass( s2t( "textAnnotTool" ));
	descriptor.putReference( c2t( "null" ), reference );
	descriptor.putBoolean( s2t( "dontRecord" ), dontRecord );
	descriptor.putBoolean( s2t( "forceNotify" ), forceNotify );
	executeAction( s2t( "select" ), descriptor, DialogModes.NO );
}

// =======================================================
historyStateChanged2(645, "New Note", true, 2);
function historyStateChanged2(ID, name2, hasEnglish, itemIndex) {
	var s2t = function (s) {
		return app.stringIDToTypeID(s);
	};

	var descriptor = new ActionDescriptor();

	descriptor.putInteger( s2t( "documentID" ), 621 );
	descriptor.putInteger( s2t( "ID" ), ID );
	descriptor.putString( s2t( "name" ), name2 );
	descriptor.putBoolean( s2t( "hasEnglish" ), hasEnglish );
	descriptor.putInteger( s2t( "itemIndex" ), itemIndex );
	executeAction( s2t( "historyStateChanged" ), descriptor, DialogModes.NO );
}

// =======================================================
make(521, 659, 240, 140);
function make(horizontal, vertical, horizontal2, vertical2) {
	var c2t = function (s) {
		return app.charIDToTypeID(s);
	};

	var s2t = function (s) {
		return app.stringIDToTypeID(s);
	};

	var descriptor = new ActionDescriptor();
	var descriptor2 = new ActionDescriptor();
	var descriptor3 = new ActionDescriptor();
	var descriptor4 = new ActionDescriptor();
	var reference = new ActionReference();

	reference.putClass( s2t( "annotation" ));
	descriptor.putReference( c2t( "null" ), reference );
	descriptor3.putUnitDouble( s2t( "horizontal" ), s2t( "pixelsUnit" ), horizontal );
	descriptor3.putUnitDouble( s2t( "vertical" ), s2t( "pixelsUnit" ), vertical );
	descriptor2.putObject( s2t( "location" ), c2t( "Pnt " ), descriptor3 );
	descriptor4.putUnitDouble( s2t( "horizontal" ), s2t( "pixelsUnit" ), horizontal2 );
	descriptor4.putUnitDouble( s2t( "vertical" ), s2t( "pixelsUnit" ), vertical2 );
	descriptor2.putObject( s2t( "size" ), s2t( "offset" ), descriptor4 );
	descriptor2.putEnumerated( s2t( "annotType" ), s2t( "annotType" ), s2t( "annotText" ));
	descriptor.putObject( s2t( "using" ), s2t( "annotation" ), descriptor2 );
	executeAction( s2t( "make" ), descriptor, DialogModes.NO );
}

// =======================================================
historyStateChanged3(646, "Edit Note", true, 3);
function historyStateChanged3(ID, name2, hasEnglish, itemIndex) {
	var s2t = function (s) {
		return app.stringIDToTypeID(s);
	};

	var descriptor = new ActionDescriptor();

	descriptor.putInteger( s2t( "documentID" ), 621 );
	descriptor.putInteger( s2t( "ID" ), ID );
	descriptor.putString( s2t( "name" ), name2 );
	descriptor.putBoolean( s2t( "hasEnglish" ), hasEnglish );
	descriptor.putInteger( s2t( "itemIndex" ), itemIndex );
	executeAction( s2t( "historyStateChanged" ), descriptor, DialogModes.NO );
}

// =======================================================
set("TEXT\r");
function set(text) {
	var c2t = function (s) {
		return app.charIDToTypeID(s);
	};

	var s2t = function (s) {
		return app.stringIDToTypeID(s);
	};

	var descriptor = new ActionDescriptor();
	var descriptor2 = new ActionDescriptor();
	var reference = new ActionReference();

	reference.putIndex( s2t( "annotation" ), 0 );
	descriptor.putReference( c2t( "null" ), reference );
	descriptor2.putData( s2t( "textData" ), String.fromCharCode( 255, 254, 84, 0, 69, 0, 88, 0, 84, 0, 13, 0 ) );
	descriptor2.putString( s2t( "text" ), text );
	descriptor.putObject( s2t( "to" ), s2t( "annotation" ), descriptor2 );
	executeAction( s2t( "set" ), descriptor, DialogModes.NO );
}
TOPICS
Actions and scripting
919
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

Mentor , Dec 01, 2022 Dec 01, 2022

@c.pfaffenbichler, that's right - we can't access notes content by DOM or AM, but we know that they are stored in an image file (i rarely work with binary data and admit that not all things in the code are perfect, but it seems to work)

#target photoshop
var s2t = stringIDToTypeID,
    doc = new AM(),
    f = new File(Folder.temp.fsName + "/" + "annotations.psd");
if (doc.checkNotes()) {
    doc.duplicate('annotations', true);
    doc.setImageSize(1);
    activeDocument.xmpMetadata.rawData = '';
...
Translate
Adobe
Community Expert ,
Dec 01, 2022 Dec 01, 2022
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
Mentor ,
Dec 01, 2022 Dec 01, 2022

@c.pfaffenbichler, that's right - we can't access notes content by DOM or AM, but we know that they are stored in an image file (i rarely work with binary data and admit that not all things in the code are perfect, but it seems to work)

#target photoshop
var s2t = stringIDToTypeID,
    doc = new AM(),
    f = new File(Folder.temp.fsName + "/" + "annotations.psd");
if (doc.checkNotes()) {
    doc.duplicate('annotations', true);
    doc.setImageSize(1);
    activeDocument.xmpMetadata.rawData = '';
    doc.saveAs(f);
    doc.closeDocument();
    if (f) {
        f.open("r");
        f.encoding = "BINARY";
        var s = f.read();
        f.close();
        f.remove();
        i = s.indexOf('8BIMAnno')
        if (i) {
            var blockLength = hextoDec(toHex(s, i + 8, 4)),
                annotations = [];
            s = s.substr(i + 12, blockLength);
            do {
                var i = s.indexOf('txtC');
                if (i >= 0) {
                    blockLength = hextoDec(toHex(s, i + 4, 4)) - 2;
                    s = s.substr(i + 10);
                    if (blockLength) {
                        var content = '';
                        do {
                            content += String.fromCharCode(hextoDec(toHex(s, 0, 2)))
                            blockLength -= 2
                            s = s.substr(2)
                        } while (blockLength)
                        annotations.push(content);
                    }
                } else break;
            } while (true)
            for (var i = 0; i < annotations.length; i++) {
                activeDocument.artLayers.add()
                activeDocument.activeLayer.kind = LayerKind.TEXT
                activeDocument.activeLayer.textItem.contents = annotations[i]
            }
        }
    }
}
function toHex(s, from, bits) {
    s = s.substr(from, bits);
    var h = '';
    for (var i = 0; i < bits; i++) h += (('0' + s.charCodeAt(i).toString(16)).slice(-2));
    return h
}
function hextoDec(val) {
    var hex = val.split('').reverse().join(''),
        dec = 0;
    for (var i = 0; i < hex.length; i++) {
        dec += parseInt(hex[i], 16) * Math.pow(16, i);
    }
    return dec;
}
function AM() {
    var s2t = stringIDToTypeID;
    this.checkNotes = function () {
        try {
            (r = new ActionReference()).putEnumerated(s2t('annotation'), s2t('ordinal'), s2t('targetEnum'));
            (d = new ActionDescriptor()).putReference(s2t('null'), r);
            executeAction(s2t('delete'), d, DialogModes.NO);
            (r = new ActionReference()).putEnumerated(s2t('historyState'), s2t('ordinal'), s2t('previous'));
            (d = new ActionDescriptor()).putReference(s2t('null'), r);
            executeAction(s2t('select'), d, DialogModes.NO)
            return true
        } catch (e) {
            return false
        }
    }
    this.duplicate = function (title, merged) {
        (r = new ActionReference()).putEnumerated(s2t("document"), s2t("ordinal"), s2t("targetEnum"));
        (d = new ActionDescriptor()).putReference(s2t("target"), r);
        d.putString(s2t("name"), title);
        if (merged) d.putBoolean(s2t("merged"), merged);
        executeAction(s2t("duplicate"), d, DialogModes.NO);
    }
    this.setImageSize = function (width) {
        (d = new ActionDescriptor()).putUnitDouble(s2t("width"), s2t("pixelsUnit"), width);
        d.putBoolean(s2t("constrainProportions"), true);
        d.putEnumerated(s2t("interpolation"), s2t("interpolationType"), s2t("bilinear"));
        executeAction(s2t("imageSize"), d, DialogModes.NO);
    }
    this.saveAs = function (pth) {
        (d = new ActionDescriptor());
        (d1 = new ActionDescriptor()).putObject(s2t("as"), s2t("photoshop35Format"), d);
        d1.putPath(s2t("in"), pth);
        d1.putBoolean(s2t("embedProfiles"), false);
        executeAction(s2t("save"), d1, DialogModes.NO);
    }
    this.closeDocument = function () {
        (d = new ActionDescriptor()).putEnumerated(s2t('saving'), s2t('yesNo'), s2t('no'));
        executeAction(s2t('close'), d, 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 Expert ,
Dec 01, 2022 Dec 01, 2022

Thanks for the insight! 

Hopefully the original poster will drop by to acknowledge your effort. 

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
Participant ,
Dec 02, 2022 Dec 02, 2022

This is awesome thank you!

 

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 ,
Dec 03, 2022 Dec 03, 2022
LATEST

If it solves your issue remember to mark @jazz-y ’s post as »correct answer«. 

 

Edit: I apologize, I had missed that it is already marked as »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