Photoshop script "repeat last curves" - photoshop

I use some photoshop scripts for my work, and all the time try to found a way to repeat previous curves adjusting, since many times it is necessary to repeat a similar (but not the same, so that I can slightly correct it) correction for the same type of images.
Many peoples do not know about this nuance, but in Photoshop there is a not-so-documented option to open an adjustment dialog ( levels / curves / hue saturation, etc. ) with the same values ​​aswhich they were applied the previous time. It can be done with adding ALT to the hot keys of their call.
e.g.:
CTRL+ALT+L for Levels
CTRL+ALT+M for Curves
CTRL+ALT+U for Hue/Saturation
If you dont know this, for understand what i need, try it in photoshop step by step:
Open the image
Press CTRL+M, edit curves points and press OK.
Now press CTRL+ALT+M (you will see that a new curves dialog has opened with the same points and their positions that you applied in step 2).
Change somehow curves points and click OK
Now press CTRL+ALT+M again and now you will see the curves settings that were applied in step 4
...and so on
I have no problem with opening any saved curves preset with scripting... however, using the presets is too limited, because picking them up for the current type of images, takes longer than changing the settings myself. I need a script where the curves would open exactly with the previous values. Just like it is done in Photoshop with CTRL+ALT+M.
If I record action (with pressing CTRL+ALT+M), the current values of the curves is simply recorded and not a repetition of the previous one.
So it possible to do this with jsx?
Many thanks!
While curves dialog create in script, this piece of code appears:
var idpresetKind = stringIDToTypeID( "presetKind" );
var idpresetKindType = stringIDToTypeID( "presetKindType" );
var idpresetKindCustom = stringIDToTypeID( "presetKindUserDefined" );
Perhaps somewhere in the bowels of the Photoshop libraries there is a "preset" that repeats the previous apply values?

Thanks to #Ghoul Fool and Kukurykus from Adobe community, i found correct answear. And for somebody who will search the same thing, I`ll keep here this:
try{dsc = getCustomOptions('curves')}catch(err){dsc = new ActionDescriptor()}
try{dsc = executeAction(stringIDToTypeID('curves'), dsc, DialogModes.ALL),
putCustomOptions('curves', dsc, false)}catch(err){}
Save it as 'Curves.jsx' to your 'Presets / Scripts' folder of your Ps. (Re)launch app and instead of current Curves item in your action, from expandable contextual menu 'Insert Menu Item' and choose 'File > Scripts > Curves'.
Now any time you play the action and set curves it will remember last used settings to play them back.
src
Thats all!

If I understand you correctly, you can load an existing .acv file and then aplly the curves to it.
var myCurves = "D:\\temp\\myCurvesFile.acv"; // change to your file
curves(myCurves); // invoke function
function curves(afile)
{
// =======================================================
var idCrvs = charIDToTypeID( "Crvs" );
var desc14 = new ActionDescriptor();
var idpresetKind = stringIDToTypeID( "presetKind" );
var idpresetKindType = stringIDToTypeID( "presetKindType" );
var idpresetKindUserDefined = stringIDToTypeID( "presetKindUserDefined" );
desc14.putEnumerated( idpresetKind, idpresetKindType, idpresetKindUserDefined );
var idUsng = charIDToTypeID( "Usng" );
desc14.putPath( idUsng, new File( afile ) );
executeAction( idCrvs, desc14, DialogModes.NO );
}

Related

How can I create the resource string without a big string?

In After Effects scripts, if you want your script to be able to be docked in the program's workspace, the only way to do it as far as I know is to use a resource string like this:
var res = "Group{orientation:'column', alignment:['fill', 'fill'], alignChildren:['fill', 'fill'],\
group1: Group{orientation:'column', alignment:['fill', ''], alignChildren:['fill', ''],\
button1: Button{text: 'Button'},\
},\
}";
myPanel.grp = myPanel.add(res);
The above code creates a script UI with one button ("button1") inside a group ("group1").
I would like to know other ways to create the same resource string. Is it possible to make it using a JSON object and then stringifying it??
I know it can be done somehow, because I have inspected the Duik Bassel script that is dockable and, for example, adds elements like this:
var button1 = myPal.add( 'button' );
but I cannot understand how to do it myself.
TL;DR: I want to make a dockable scriptUI without writing a giant string all at once, but bit by bit, like a floating script.
UI container elements have an add() method which allows you to add other UI elements to them, and you can treat them as normal objects.
var grp = myPanel.add("group");
grp.orientation = "column";
grp.alignment = ['fill', 'fill'];
grp.alignChildren = ['fill', 'fill'];
var group1 = grp.add("group");
…
var button1 = group1.add("button");
button1.text = 'Button'
More details and examples here: https://extendscript.docsforadobe.dev/user-interface-tools/types-of-controls.html#containers
Also worth checking out https://scriptui.joonas.me/ which is a visual scriptUI interface builder. You have to do some work on the code it produces to get panels for AE, but it's not hard.
extendscript still uses a 20th century version of javaScript, which doesn't have JSON built-in, but I have successfully used a JSON polyfill with it.
I used json2.js to get structured data in and out of Illustrator, and it worked beautifully, but I can see there's now a json3.js which might be better for whatever reason. This stackoverflow question addresses the differences.
To load another .js file (such as a polyfill) into your script, you need to do something like
var scriptsFolder = (new File($.fileName)).parent; // hacky but effective
$.evalFile(scriptsFolder + "/lib/json2.js"); // load JSON polyfill
These file locations may differ in other Adobe apps. Not sure what it would be in AfterEffects. I seem to remember that InDesign has a different location for scripts. You can also hardcode the path, of course.
Good luck!

Create a square with additional data node data

I am pretty much a javascript noob, and very new to cytoscape (but i code in other languages)...
I am trying to use Cytoscape to graph out the servers available in my network. Creating a node per server and their relationship was straightforward actually.
I would like to add the possibility than when I click a node (let's say server12345) that it would open kind of a table with data associated with that server (servertype etc...).
Do you have any idea / examples / guidance on how I could:
add functionality on that click event of a specific node ?
how to create a 'details' table using cytoscope?
Thank you guys so much in advance!
(Ps: My first post on StackOverflow...)
Nice question.
Firstly, you can capture the click event of cytoscape.js like below
cy.nodes().on('click', function(e){
var clickedNode = e.target;
console.log(clickedNode.id());
});
or you can also use the tap event of cytoscape.js
cy.on('tap', 'node', function(evt){
var node = evt.target;
console.log( 'tapped ' + node.id() );
});
You can read events section of the documentation for more details
After you capture this event, I see to ways.
1-) Just modify an existing HTML element on the UI. For example in here you can see on the left side there are some other elements.
So you can write your code like
cy.on('tap', 'node', function(evt){
var node = evt.target;
document.getElementById('someOtherElementOnUI').innerHTML = JSON.stringfy(node.data());
});
This will simply modify some other UI element (HTML element) and changes its content to the data of the selected node.
2-) You can use some extensions like Cytoscape.js-popper and show data dynamically like a tooltip. You can check my answer https://stackoverflow.com/a/66813720/3209523

How to convert the spectrum type ("Spectrum" -> "Convert Data to")

Is there a manner in which one can convert the spectrum type, for instance to EELS, by DM scripting? This screenshot represents what I'm referring to. I'd like to import a dataset using the GMS 3.4 Python interface, and then turn that into a EELS dataset for further processing (ideally without having to manually interface with the screenshotted menu bar).
Yes there is.
The "type" is simply a meta-data tag
which you can easily set with the TagGroup commands.
There is, however, one complication:
Data "registers" itself with DM when it first appears. Changing the meta-tags manually doesn't change this registration. (The menu command, however, does.)
Thus, you will only see effect of the type change when
either:
You save, close and reopen the data
You clone the data, throw away the original, and display the clone
The second option might cause issues with data-linkage though, as the unique image ID of the data is newly created.
Example using the first method (requires save & load):
image img:=GetFrontImage()
TagGroup tg = img.ImageGetTagGroup()
tg.TagGroupSetTagAsString("Meta Data:Signal","EELS")
imageDocument doc = img.ImageGetOrCreateImageDocument()
doc.ImageDocumentSave(0)
string path = doc.ImageDocumentGetCurrentFile()
doc.ImageDocumentClose(0)
doc = NewImageDocumentFromFile(path)
doc.ImageDocumentShow()
An alternative option is to rely on the menu command. If it is present, then you can simply use the ChoseMenuItem() command to invoke it.
However, the command will only be available with the UI when the data you want to change is front-most (i.e. not a script window!) You will need to ensure by script, that this is the case. A simple ShowWindow() will do.
image img:=GetFrontImage()
img.ShowImage()
if ( !ChooseMenuItem("Spectrum","Convert Data To","None") )
Throw( "Conversion to none failed.")
if ( !ChooseMenuItem("Spectrum","Convert Data To","EDS") )
Throw( "Conversion to none failed.")
Disadvantage of this solution: You will get the user-prompts.

PDFBox: Fill out a PDF with adding repeatively a one-page template containing a form

Following SO question Java pdfBox: Fill out pdf form, append it to pddocument, and repeat I had trouble appending a cloned page to a new PDF.
Code from this page seemed really interesting, but didn't work for me.
Actually, the answer doesn't work because this is the same PDField you always modify and add to the list. So the next time you call 'getField' with initial name, it won't find it and you get an NPE. I tried with the same pdfbox version used (1.8.12) in the nice github project, but can't understand how he gets this working.
I had the same issue today trying to append a form on pages with different values in it. I was wondering if the solution was not to duplicate field, but can't succeed to do it properly. I always end with a PDF containing same values for each form.
(I provided a link to the template document for Mkl, but now I removed it because it doesn't belong to me)
Edit: Following Mkl's advices, I figured it out what I was missing, but performances are really bad with duplicating every pages. File size isn't satisfying. Maybe there's a way to optimize this, reusing similar parts in the PDF.
Finally I got it working without reloading the template each time. So the resulting file is as I wanted: not too big (4Mb for 164 pages).
I think I did 2 mistakes before: one on page creation, and probably one on field duplication.
So here is the working code, if someone happens to be stuck on the same problem.
Form creation:
PDAcroForm finalForm = new PDAcroForm(finalDoc, new COSDictionary());
finalForm.setDefaultResources(originForm.getDefaultResources())
Page creation:
PDPage clonedPage = templateDocument.getPage(0);
COSDictionary clonedDict = new COSDictionary(clonedPage.getCOSObject());
clonedDict.removeItem(COSName.ANNOTS);
clonedPage = new PDPage(clonedDict);
finalDoc.addPage(clonedPage);
Field duplication: (rename field to become unique and set value)
PDTextField field = (PDTextField) originForm.getField(fieldName);
PDPage page = finalDoc.getPages().get(nPage);
PDTextField clonedField = new PDTextField(finalForm);
List<PDAnnotationWidget> widgetList = new ArrayList<>();
for (PDAnnotationWidget paw : field.getWidgets()) {
PDAnnotationWidget newWidget = new PDAnnotationWidget();
newWidget.getCOSObject().setString(COSName.DA, paw.getCOSObject().getString(COSName.DA));
newWidget.setRectangle(paw.getRectangle());
widgetList.add(newWidget);
}
clonedField.setQ(field.getQ()); // To get text centered
clonedField.setWidgets(widgetList);
clonedField.setValue(value);
clonedField.setPartialName(fieldName + cnt++);
fields.add(clonedField);
page.getAnnotations().addAll(clonedField.getWidgets());
And at the end of the process:
finalDoc.getDocumentCatalog().setAcroForm(finalForm);
finalForm.setFields(fields);
finalForm.flatten();

How to convert a panorama item into page/data grid

I am new to Windows phone dev. I am following this excellent article ( http://developer.nokia.com/Community/Wiki/Weather_in_Windows_Phone_7 ) and have learnt something about how to load xml data and show it as a useful info in a paronama view. But now instead of panorama i want it to be shown as a page. I am not sure if its in a page tag or data grid tag that I should work with. Can someone please help me with how to convert this piece of code to some thing which can be displayed in a page
// create PanoramaItem
PanoramaItem panoramaItem = new PanoramaItem();
panoramaItem.Header = queries[query];
// modify header to show only city (not the country)
int index = queries[query].IndexOf(",");
if (index != -1)
panoramaItem.Header = queries[query].Substring(0,queries[query].IndexOf(","));
else panoramaItem.Header = queries[query];
// use ForecastTemplate in Panorama Item
panoramaItem.ContentTemplate=(DataTemplate)Application.Current.Resources["ForecastTemplate"];
panoramaItem.Content = pio; // add Panorama Item to Panorama
Panorama.Items.Add(panoramaItem); // query next city forecast
At first, be sure that Pivot is useless for you. Its like Panorama, but Pivot :) See differences here, here, here(nice one) or here
Tried to paste some code here, but SO is not showing tags. So, take a look at <.Grid.ColumnDefinitions> and <.Grid.RawDefinitions>. Dots at the beginning are just for rendering.