ich habe zwei Fragen, von denen ich vermute, dass sie zusammenpassen könnten:
1) Wie kann ich alle Farben, über die ID verfügt, auslesen? Ich benötige dies, da ich dem Scriptanwender eine bestimmte gefilterte Auswahl anzeigen will. Mit app.colors.length erhalte ich bei mir 14 (obwohl in der Farbpalette nur 10 angelegt sind). Beim Anlegen eines neuen Farbfeldes habe ich unterhalb der drei Farbmodi RGB, LAB und CMYK viele weitere Bibliotheken, die ich aber nicht über ColorSpace ansteuern kann. Wie komme ich da dran?
2) Gegeben ist ein Rectangle mit einem (durchaus aufwändigerem) Farbverlauf (Abmessungen 10 cm Breite). Aus diesem möchte ich nun in regelmäßigen Abständen die exakt an dieser Stelle bestehende Farbmischung abfragen. Ziel ist die Bestimmung von passenden Farben, die dann weiterhin im Layout benutzt werden können. Muss ich dort über fillColor.gradientStops gehen und diese dann umrechnen oder gibt es eine einfachere Lösung, die ich derzeit nicht sehe?
über die Separationsvorschau die Werte (mittels Hilfslinien für die Cursorpositionierung) zu ermitteln ist zu mühsam, weil es zu viele Stützpunkte sind trotz nur 10cm Strecke?
es soll automatisiert als Script geschehen. Am ehesten lässt es sich noch mit Kuler vergleichen: Man klickt das Rechteck mit dem Verlauf an, bestimmt die Anzahl der Farben und das Script "stanzt" diese dann automatisch an den gleichmäßig verteilten Stellen heraus.
Steht z. B. bei 3 cm ein Stop mit dem Wert C0M100, bei 6 cm ein Stop mit dem Wert C100M0, so würde die Farbe bei 4 cm dann C33M66 haben. (Ob das schön aussieht, mögen andere beurteilen).
Der Weg über die Hilfslinien sowie Separationsvorschau würde zu lange dauern.
die Namen der zehn Farben, welche Du im Bedienfeld "Farbfelder" zählst, bekommst Du mit swatches angezeigt:
Aber "None", "Registration", "Paper" und "Black" müssen übersetzt werden, bevor sie dem Anwender zur Auswahl angeboten werden. Und nachher, vor dem Zuweisen eines der Grundfarbfelder, muss dessen Name wieder ins Englische zurückverwandelt werden.
Die vierzehn Namen – hingegen – welche laut Dialog vorhanden sein sollen, kommen mit colors zum Vorschein:
Das Pipe-Zeichen (= | ) am Schluss stellt sicher, dass alles sichtbar wird. So gut wie möglich. Denn zuletzt befinden sich zwei "Farben" ohne Namen.
Sowohl "Cyan" als auch "Magenta" und "Yellow" (und "Gelb" und "Jaune" und "Giallo" usw.) sind fixe Farbnamen, welche beim Anlegen eines neuen Farbfeldes nicht akzeptiert werden.
Aber ein Scripter kann einem Objekt z.B. "Magenta" zuweisen, auch wenn dieses Farbfeld nicht existiert.
So, ich bin immer noch an dem Thema Farben und komme trotz aller Hilfe nicht recht weiter bzw. renne vor neue Hürden. Ansatz ist, dass ich Farben zum Kopieren zwischen Dokumenten in JSON als Datei auf der Platte abspeichern und später wieder aufrufen will.
Mache ich dies, verheddert sich JSON.stringify in irgendwelchen Tiefen. Ich habe ein Logfile auf die Festplatte schreiben lassen und das JSON wird 25 KB groß. Ich vermute, dass man nicht alle Properties auf die folgende Art und Weise auslesen kann:
Nun gut, brauche eh nicht alle und beschränke mich daher auf eine Auswahl:
Beim Alert stehen nach model und space leere Bereiche, wobei dort auch eine Zeilenschaltung enthalten sein muss, da der Text in zwei Teile unterteilt ist.
Danach möchte ich den String wieder in ein Objekt zurückwandeln und lege dazu eine neue Farbe an, parse den String und loope danach durch die Properties. Dabei steigt das Script aus mit der Meldung: "Ungültiger Wert für Einrichtung der Eigenschaft "model". ColorModel enumerator erwartet, aber () erhalten."
Dank eines Gemeinschaftsbeitrags in diesem Forum aus dem Januar dieses Jahres bin ich nun auch auf die Lösung gekommen (http://www.hilfdirselbst.ch/foren/Enumeration_%96_Value_als_String_P521887.html).
Man muss am besten die enumerators als Values ausgeben, was dann verkürzt so aussieht:
Diese Werte schaffen es dann auch durch JSON.stringify und parse.
Statt des Umwegs über parseInt() geht auch direkter Aufruf von .valueOf() - das hatte ich am Ende des zitierten Threads auch erwähnt. parseInt() macht auch nichts anderes, wenn es ein Objekt übergeben bekommt. Der Wert wird nur zusätzlich in einen String umgewandelt und dann wieder zurück.
JSON ist oft unnötig, wenn man keinen "Consumer" hat der auf striktes JSON Wert legt. Ansonsten reicht toSource() - eine von ExtendScript gelieferte Funktion - sowie das Gegenstück eval(). Eval ist zwar im Web verpönt, aber das ist m.E. zu sehr verallgemeinert. Wenn man die Daten selber produziert, ist es einfach nur praktisch.
Aktennotiz: Nicht gleich beim Finden des ersten Codeschnippsels gackernd über den Programmierhof rennen sondern Beitrag bis zum Ende lesen :-)
Habe da mal einen Test laufen lassen: Das o. g. Objekt 10.000 mal mit toSource/eval laufen lassen, dass andere mal mit JSON.stringify/JSON.parse. Kommt ein Unterschied von 491 ms zu 5.821 ms raus. Die JSONs machen da wohl noch einiges zusätzlich, wer aber die übergebenen Werte in der Hand hat, sollte auf die erste Lösung setzen, wenn auch die Laufzeitunterschiede im tagtäglichen Geschäft eher marginal sind, da bei einmaligen Durchlauf der Unterschied nur eine halbe Millisekunde beträgt.
Kannst Du mir hier noch ein paar Zusatzinfos geben? Soweit ich das blicke, geht es laut Funktionsname darum, aus einem String (oder JSON) ein Objekt zu machen. Mein Problem bestand aber darin, dass bei der Umwandlung in einen String der Value nicht gelesen wurde.
Gruß
Peter
(Dieser Beitrag wurde von peterhenrich am 23. Feb 2014, 19:46 geändert)
manchmal vergesse ich, dass nicht jeder in Vollzeit Code liest und schreibt.
Das Script ist eine sehr vereinfachte Funktion, die aus einem InDesign Objekt (e.g. Color) ein reines JavaScript Objekt macht. Also etwas, was mit JSON oder toSource() in einen String mit der {} Notation überführt werden kann.
Das Beispiel ruft dann unten auch toSource() auf dem Ergebnis auf, um den String auf der Konsole auszugeben.
Ich sage auch vereinfacht, weil die Funktion noch nicht für verschachtelte Objekte funktioniert. Wenn das Color Objekt also theoretisch ColorWhateverOptions enthalten würde, müsste man die Funktion aufbohren. Ebenso für ein theoretisches Gradient Objekt, welches evtl. 5 Colors referenzieren würde.
Wenn man den String mit eval wieder zurück umwandelt, hat man wieder so ein reines JavaScript Objekt. Um dieses ins neue Dokument zu bringen, unterstützen die meisten add() Funktionen ein "withProperties" als letztes Argument ihrer Argument-Liste. withProperties erwartet genau unser JavaScript Objekt, und übernimmt die enthaltenen Eigenschaften in das neue InDesign Objekt.
Das folgende Beispiel liest die Eigenschaften einer der Applikations-Farben aus, wandelt sie in einen String und dann wieder in ein Objekt zurück. Der Name des Objekts wird noch geändert (einfach nur so), und das Objekt zum Aufbau einer neuen Farbe in einem neuen Dokument genutzt.
var str = objectify(app.colors.item(8)).toSource(); var obj = eval(str); obj.name = "Test";
var doc = app.documents.add(); doc.colors.add(obj);
Das Script ist eine sehr vereinfachte Funktion, die aus einem InDesign Objekt (e.g. Color) ein reines JavaScript Objekt macht. Also etwas, was mit JSON oder toSource() in einen String mit der {} Notation überführt werden kann.
Hallo Dirk,
vielen Dank für die erklärenden Worte.
Ich sage auch vereinfacht, weil die Funktion noch nicht für verschachtelte Objekte funktioniert. Wenn das Color Objekt also theoretisch ColorWhateverOptions enthalten würde, müsste man die Funktion aufbohren. Ebenso für ein theoretisches Gradient Objekt, welches evtl. 5 Colors referenzieren würde.
Das ist auch das Problem von JSON.stringify. Es kommt vom Hölzchen aufs Stöckchen und schreibt das halbe ID in das Objekt. Ich hatte das Script mal so abgeändert, dass es bei jedem Aufruf das gerade Erledigte in eine Datei auf der Platte speichert. Ich hatte es zunächst mit Gradients versucht, was eigentlich mein Hauptverwendungszweck werden soll. Ich denke, dass ich nicht um eine spezielle Funktion hierfür herumkomme.
So ist es ja auch wenig sinnvoll, von einem Objekt die id abzufragen, da diese in einem neuen Dokument ja eh wieder eine andere wird.
Siehst Du denn eine andere Möglichkeit, Gradients von einem Dokument in ein anderes zu kopieren, ohne die Zwischenablage zu benutzen? Ich möchte meine Scripte server-ready haben. Bei einer Ein-Kern-Lösung vielleicht noch kein Problem, sobald man aber mehrere Kerne anspricht, kann es zu allenfalls "lustigen", eher aber falschen Ergebnissen kommen. Oder hat jeder Prozess auf einem Kern seine eigene Zwischenablage?
Hallo, Peter! Ich verfolge diesen Thread mit Interesse, obwohl ich über keine InDesign-Server-Anwendung verfüge.
Ohne Zwischenablage Gradients von einem InDesign-Dokument ins andere zu transportieren?
Ich sehe da drei Möglichkeiten mal ohne JSON zu bemühen:
1. IDMS-Datei von Objekt exportieren und platzieren
2. Bibliothek-Datei mit dem Objekt erzeugen und aus der Bibliothek heraus platzieren
(Die Vorschläge 1 und 2 sind nicht ganz so praktisch)
3. Objekt von einem zum anderen InDesign-Dokument duplizieren
Kleines Experiment: Zwei geöffnete Dokumente, 1 Rechteck im Dolument mit Index 0, leeres Dokument mit Index 1.
var myObject = app.documents[0].pages[0].rectangles[0]; myObject.duplicate(app.documents[1].pages[0]);
So ist es ja auch wenig sinnvoll, von einem Objekt die id abzufragen, da diese in einem neuen Dokument ja eh wieder eine andere wird.
Dafür ließe sich per insertLabel(keyString,valueString) eine Spur legen, die man zurückverfolgen und auswerten kann: extractLabel(keyString). Zur Not geht in den valueString wahrscheinlich auch ein ganzes Objekt als String rein (hab's aber noch nicht ausprobiert):
ich möchte jetzt eine MixedInk anlegen, was aber nicht so recht gelingen will. Voraussetzung ist, dass in dem Dokument eine Farbe names "HKS 5 K" angelegt ist.
Nun möchte ich eine neue Version dieser Farbe anlegen, die 20 % "Process Black" enthält.
Dieses Script ...
var doc = app.activeDocument; var myInkList = [doc.inks.itemByName("Process Black"), doc.inks.itemByName("Process Magenta"), doc.inks.itemByName("HKS 5 K")]; var myInkPercentages = [20, 0, 100];