Scripting issues

Here everybody can post his problems with PhotoLine
Benutzeravatar
russellcottrell
Mitglied
Beiträge: 255
Registriert: Sa 26 Jul 2014 10:13
Wohnort: California

Re: Scripting issues

Beitrag von russellcottrell »

Hello; sorry to be stubborn, but . . . I just am. I can't help but think that there must be a future for jxa even if it doesn't work perfectly at the moment. So here are some observations in case anyone else has some insights. I found that in the Script Editor, File - Open Dictionary - PhotoLine.app opens a window that shows all the properties and methods. Notably, activeDocument is missing; this may explain why a lot of things don't work:

Code: Alles auswählen

var pl = Application.currentApplication();
pl.includeStandardAdditions = true;
pl.displayAlert("Hello, world!");

var doc = pl.activeDocument;
pl.displayAlert(doc.name); // empty string
pl.displayAlert(doc.activeLayer.name); // error
pl.displayAlert(doc.resolution.toString()); // error
doc.activeLayer = doc.root.lastChild; // error
Maybe someday . . . .
Martin Huber
Entwickler
Entwickler
Beiträge: 4298
Registriert: Di 19 Nov 2002 15:49

Re: Scripting issues

Beitrag von Martin Huber »

You can get the active document with code like:

Code: Alles auswählen

if (pl.documents().length > 0)
	doc = pl.documents.first
Then you can get the active layer with

Code: Alles auswählen

actLayer = doc.activeLayer()
You can check the layer type with something like

Code: Alles auswählen

if ((actLayer != null) && (actLayer.type() === 'LTImage'))
{
   (...)
}
Enumerations in PhotoLine's scripting dictionary seem to be strings in JXA.

But I haven't been able to create new layers at a specific location using JXA. And I haven't been able to set adjustments.

Martin
pixel8tor
Mitglied
Beiträge: 72
Registriert: Di 24 Jul 2018 17:15

Re: Scripting issues

Beitrag von pixel8tor »

Hi All,

I'm working on a script that needs to manipulate the data from the curves dialog. But I can't figure out how to get the actual curves data (points of the curve and its type). In other words, if I display the curves dialog and the user makes adjustments (maybe add a point at (.5, .5) and moves it to (.5, .6) in the red channel), how do I retrieve that data, the point pairs, inside a script? And how would I get those values from a curves adjustment layer? Also, how do you get, and set, the curve type value? Any examples using VBScript would be very helpful.

Thanks
Benutzeravatar
Gerhard Huber
Entwickler
Entwickler
Beiträge: 4276
Registriert: Mo 18 Nov 2002 15:30
Wohnort: Bad Gögging

Re: Scripting issues

Beitrag von Gerhard Huber »

VBScript is deprecated by Microsoft, so you should use PowerShell instead. PowerShell also has the advantage that it has an integrated debugger and you can inspect variables while debugging your script.

Regarding your question: In theory, you can query the parameters of the curves adjustment and modify. Unfortunately, that doesn't work properly in the current version of PhotoLine, because the curve adjustment doesn't return the curves. We will fix that. After the fix, it will work like this (in PowerShell):

Code: Alles auswählen

# Variables have to be set before being used.
Set-StrictMode -Version 2
$pl = New-Object -ComObject PhotoLine.Application -Strict
# $pl.Visible = $True
$doc = $pl.ActiveDocument
                            # Is there a document?
if ($null -ne $doc)
{
    $activeLayer = $doc.ActiveLayer
    # Is there an active layer and has the active layer at least one adjustment.
    if (($null -ne $activeLayer) -and ($activeLayer.AdjustmentsCount -gt 0))
    {
        # Fetch the data of the first adjustment.
        $adjustmentPara = $activeLayer.Adjustment(0)
        # Modify the main curve
        # - fetch it
        $curveMain = $adjustmentPara["CurveMain"]
        if ($null -ne $curveMain)
        {
           # - Fetch the existing points of the curve. It is a float array.
           $points = $curveMain.Points
           # - Are there enough points to edit?
           if ($points.Count -ge 4)
           {
              $points[2] = 0.5
              $points[3] = 0.6
           }
           # - Set the modified points as new curve points in the adjustment.
           $adjustmentPara["CurveMain"] = $points
           $activeLayer.Adjustment(0) = $adjustmentPara;
        }
    }
}
If you want the red curve, you use "Curve1" instead of "CurveMain", "Curve2" for green and "Curve3" for blue.

In the current version, you can just set new points for one of these curves. The following snippet does that:

Code: Alles auswählen

        # Fetch the data of the first adjustment.
        $adjustmentPara = $activeLayer.Adjustment(0)
        # Set the points of the main curve
        $adjustmentPara["CurveMain"] = @(0.0, 0.0, 0.5, 0.6, 1.0, 1.0)
        $activeLayer.Adjustment(0) = $adjustmentPara;
pixel8tor
Mitglied
Beiträge: 72
Registriert: Di 24 Jul 2018 17:15

Re: Scripting issues

Beitrag von pixel8tor »

Thanks for your detailed answer. It explains why, after hours of trying, I couldn't retrieve the curves data. As for MS deprecating VBScript, that's very disappointing. I always found a way to get things done with its scripting engine, not to mention *all* the corporate scripts that manipulate data, daily, using VBScript and VBA. Do PS1 scripts run unedited on a Mac with Powershell installed?

Also you didn't mention Curve Type. Will that also be fixed so it's part of the dictionary? And I noticed in "Stings.str" that "Bezier 2" and "Spile 2" aren't listed. Do they have separate Type numbers? The documentation, "VBScripting.pdf", doesn't list them anywhere. I need the Type data because if the user changes it to something other than spline the script won't operate as expected. So I hope that it is added to the dictionary. Thanks for looking into this.
CurveType.jpg
You show an example of how to set curve points, but no example of setting the curve type. Is that currently possible? If so, how? After all the description of an IPLCurve is an array of point pairs AND the CurveType! I'm not sure how to append a Single to an Array.

Will these changes be in the next beta, or will it take longer to make them?

I appreciate all the hard work you guys put into Photoline. Thanks

P.S. This reminds me, since getting the curves data won't work with versions of Photoline earlier than the version you insert those interfaces in, could you add a "Version" property to the "IApplication" object, that would return the version of the currently running PL. That would make it easier for the script to fail gracefully if the running version doesn't support retrieving the curves data. Does that make sense?
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.
pixel8tor
Mitglied
Beiträge: 72
Registriert: Di 24 Jul 2018 17:15

Re: Scripting issues

Beitrag von pixel8tor »

I was wondering if there is another key missing from adjustments dictionaries. This is copied from the very end of VBScriping.PDF:

Adjustments
Adjustments are a subset of the available operations, that can be applied to images. The parameters of the adjustments are stored in IPLDictionaries. All adjustment dictionaries contain the key “Type” whose value is the name of the operation as string. The other keys and values are the parameters of the operation.

I don't see a "Type" key in any of the available adjustments dictionaries. Am I misunderstanding or have they been accidentally omitted? If they should be there, can you fix that? Thanks
Martin Huber
Entwickler
Entwickler
Beiträge: 4298
Registriert: Di 19 Nov 2002 15:49

Re: Scripting issues

Beitrag von Martin Huber »

pixel8tor hat geschrieben: Di 09 Jun 2026 22:12Do PS1 scripts run unedited on a Mac with Powershell installed?
No, for two reasons:
- PowerShell on macOS doesn't support scripting applications.
- Even if it would, scripting works differently on macOS than it does on Windows.
pixel8tor hat geschrieben: Di 09 Jun 2026 22:12Also you didn't mention Curve Type. Will that also be fixed so it's part of the dictionary?
$curveMain from my sample script is an IPLCurve, so $curveMain.Type returns the curve type.
pixel8tor hat geschrieben: Di 09 Jun 2026 22:12And I noticed in "Stings.str" that "Bezier 2" and "Spile 2" aren't listed. Do they have separate Type numbers?
Scripting has nothing to do with Strings.str.
pixel8tor hat geschrieben: Di 09 Jun 2026 22:12The documentation, "VBScripting.pdf", doesn't list them anywhere. I need the Type data because if the user changes it to something other than spline the script won't operate as expected. So I hope that it is added to the dictionary. Thanks for looking into this.
Two things:
- Spline 2 and Bezier 2 are slope-limited versions of Spline and Bezier. Both are only available in the beta versions of PhotoLine, not in the release versions.
- IPLCurve's Type returns the type CurveType, that's documented in VBScripting.pdf. But you are right that some modes are missing. I will change that. It will return one of these values: CTBezier = 0, CTSpline = 1, CTLagrange = 2, CTLine = 3, CTByte256 = 4, CTBezierLim = 5, CTSplineLim = 6
pixel8tor hat geschrieben: Di 09 Jun 2026 22:12You show an example of how to set curve points, but no example of setting the curve type. Is that currently possible? If so, how? After all the description of an IPLCurve is an array of point pairs AND the CurveType!
Setting the curve type is quite straightforward: "$curveMain.Type = 1" will set the curve type to Spline.
pixel8tor hat geschrieben: Di 09 Jun 2026 22:12I'm not sure how to append a Single to an Array.
Well, that's more a PowerShell question than a PhotoLine question. In PowerShell regular arrays are not resizable. You'll have to split an array and recombine the parts with the points you want to insert.
I asked an AI for that and it wrote a little helper function.
A modified script that
- adds a new point to the main curve
- sets main curve's type to Spline
looks like that:

Code: Alles auswählen

# Functions have to be defined before the code using them
# Insert-ArrayValues will insert $NewValues in $Array at position $index and return the result
function Insert-ArrayValues {
    param(
        [object[]] $Array,
        [int]      $Index,
        [object[]] $NewValues
    )

    $left  = if ($Index -gt 0) { $Array[0..($Index - 1)] } else { @() }
    $right = if ($Index -lt $Array.Length) { $Array[$Index..($Array.Length - 1)] } else { @() }

    return $left + $NewValues + $right
}

############## Main Code ##############
# Variables have to be set before being used.
Set-StrictMode -Version 2
$pl = New-Object -ComObject PhotoLine.Application -Strict
# $pl.Visible = $True
$version = $pl.Version
$doc = $pl.ActiveDocument
                            # Is there a document?
if ($null -ne $doc)
{
    $activeLayer = $doc.ActiveLayer
    # Is there an active layer and has the active layer at least one adjustment.
    if (($null -ne $activeLayer) -and ($activeLayer.AdjustmentsCount -gt 0))
    {
        # Fetch the data of the first adjustment.
        $adjustmentPara = $activeLayer.Adjustment(0)
        # Modify the main curve
        # - fetch it
        $curveMain = $adjustmentPara["CurveMain"]
        if ($null -ne $curveMain)
        {
           # - Fetch the existing points of the curve. It is a float array.
           $points = $curveMain.Points
           $pointsCount = $points.Count
           # - Are there enough points to edit?
           if ($pointsCount -ge 4)
           {
              # A new point will be inserted between the first and the second point.
              # The new point is the average of the first and the second point.
              # PowerShell is a bit tricky here. The parantheses around the single
              # array elements are important.
              $newPoint = @((($points[0] + $points[2]) / 2), (($points[1] + $points[3]) / 2))
              $points = Insert-ArrayValues -Array $points -Index 2 -NewValues $newPoint
           }
           # - Set the curve type to Spline
           $curveMain.Type = 1
           # - Set the modified points
           $curveMain.Points = $points
           # - Set the modified points as new curve points in the adjustment.
           $adjustmentPara["CurveMain"] = $curveMain
           $activeLayer.Adjustment(0) = $adjustmentPara;
        }
    }
}
Note: This script will only work with the upcoming PhotoLine 25.60B3.
pixel8tor hat geschrieben: Di 09 Jun 2026 22:12Will these changes be in the next beta, or will it take longer to make them?
It will be in the next beta, but I don't know when it will be included in the official release.
pixel8tor hat geschrieben: Di 09 Jun 2026 22:12P.S. This reminds me, since getting the curves data won't work with versions of Photoline earlier than the version you insert those interfaces in, could you add a "Version" property to the "IApplication" object, that would return the version of the currently running PL. That would make it easier for the script to fail gracefully if the running version doesn't support retrieving the curves data. Does that make sense?
There will be a Version property (see the script above) that returns a version string (for example "25.51").
pixel8tor hat geschrieben: Do 11 Jun 2026 19:20Adjustments are a subset of the available operations, that can be applied to images. The parameters of the adjustments are stored in IPLDictionaries. All adjustment dictionaries contain the key “Type” whose value is the name of the operation as string. The other keys and values are the parameters of the operation.

I don't see a "Type" key in any of the available adjustments dictionaries. Am I misunderstanding or have they been accidentally omitted? If they should be there, can you fix that?
The "Type" property works fine here. "$adjustmentPara["Type"]" shows "Curves".
Please note: Even after running a script in PowerShell ISE, you can access your variables and type commands in the console. Typing "$adjustmentPara["Type"]" in the console should show "Curves".
pixel8tor
Mitglied
Beiträge: 72
Registriert: Di 24 Jul 2018 17:15

Re: Scripting issues

Beitrag von pixel8tor »

Thanks for your detailed reply. I have a few more questions.

You wrote: "PowerShell on macOS doesn't support scripting applications."

Okay, what about JavaScript. I know there's been discussion about the unofficial support for it. And PL does have some samples included. But I guess there must be some limitation that makes it a bad choice. What's the issue with JavaScript?

You wrote: "Scripting has nothing to do with Strings.str."

Well, in a round about way it does. Since it supplies the strings that show up in the PL interface, and scripting automates interacting with the objects that underlie the interface.

You wrote: "$curveMain.Type = 1" will set the curve type to Spline"

I don't understand that. Is it PS1? I'm just barely stumbling by with VBScript. The following is a line of code from "AdjustmentWithGradient.vbs". Where would you insert the CurveMain Type?

adjustmentLayer.InsertAdjustment -1, "Type", "Curves", "Contrast", 60, "CurveMain", Array(0, 0, 0.5, 0.6, 1, 1)

You wrote: "There will be a Version property".

Thanks for that. For now I'll just check if that property exist, since it will sync with changes made to retrieving Curves properties data.

You wrote: "The "Type" property works fine here. "$adjustmentPara["Type"]" shows "Curves".
Please note: Even after running a script in PowerShell ISE, you can access your variables and type commands in the console. Typing "$adjustmentPara["Type"]" in the console should show "Curves"."

Sorry again but the PS1 code is lost on me. Anyway the reason I ask is because if I have this line of code:

Set dialogsettings = doc(0).ShowOperationDialog ("Curves")

I assume "dialogsettings" is a dictionary, but it only contains these items: Intensity, ColorMode, Channels, PictureType, Contrast, Brightness, and Gamma. There is no Type item. Maybe I'm getting different dictionaries confused. How do I get a full list of properties for the Curves object? Also I noticed that methods ShowOperationDialog and DoOperation require an "operationName". But the InsertAdjustment method doesn't. Yet they all accept dictionaries for parameters. If the dictionary contains a Type item, why is the "operationName" necessary at all? Again, I might be confusing different dictionaries. It's easy to get lost in all this object, properties, and methods stuff. Any help clearing up my confusion would be appreciated.

Thanks again for your help.
Martin Huber
Entwickler
Entwickler
Beiträge: 4298
Registriert: Di 19 Nov 2002 15:49

Re: Scripting issues

Beitrag von Martin Huber »

pixel8tor hat geschrieben: Mo 15 Jun 2026 01:42 You wrote: "PowerShell on macOS doesn't support scripting applications."

Okay, what about JavaScript. I know there's been discussion about the unofficial support for it. And PL does have some samples included. But I guess there must be some limitation that makes it a bad choice. What's the issue with JavaScript?
I haven't been able to get some basic things to work in JXA (Apple's version of JavaScript for scripting), and from what I've read online, it has some shortcomings.
pixel8tor hat geschrieben: Mo 15 Jun 2026 01:42 You wrote: "$curveMain.Type = 1" will set the curve type to Spline"

I don't understand that. Is it PS1? I'm just barely stumbling by with VBScript. The following is a line of code from "AdjustmentWithGradient.vbs". Where would you insert the CurveMain Type?

adjustmentLayer.InsertAdjustment -1, "Type", "Curves", "Contrast", 60, "CurveMain", Array(0, 0, 0.5, 0.6, 1, 1)
You can't. The "CurveMain" key is flexible and can accepts various kind of data. In this case it just takes an array of points.
If you want to also set the type, you will have to explicitly create an IPLCurve. Something like this:

Code: Alles auswählen

Set curve = CreateObject("PhotoLine.Curve")
curve.Type = 1
curve.Points = Array(0, 0, 0.5, 0.6, 1, 1)
adjustmentLayer.InsertAdjustment -1, "Type", "Curves", "Contrast", 60, "CurveMain", curve
Attention: I didn't test that and just typed it in the browser.
pixel8tor hat geschrieben: Mo 15 Jun 2026 01:42 Sorry again but the PS1 code is lost on me.
I really recommend switching to PowerShell. It makes life so much easier. You can type commands in the console and see what happens. You get better error messages. You can trace your code and inspect the results you are getting.
pixel8tor hat geschrieben: Mo 15 Jun 2026 01:42 Anyway the reason I ask is because if I have this line of code:

Set dialogsettings = doc(0).ShowOperationDialog ("Curves")

I assume "dialogsettings" is a dictionary,
Yes, ShowOperationDialog is documented to return a dictionary.
pixel8tor hat geschrieben: Mo 15 Jun 2026 01:42 but it only contains these items: Intensity, ColorMode, Channels, PictureType, Contrast, Brightness, and Gamma. There is no Type item. Maybe I'm getting different dictionaries confused. How do I get a full list of properties for the Curves object? Also I noticed that methods ShowOperationDialog and DoOperation require an "operationName". But the InsertAdjustment method doesn't. Yet they all accept dictionaries for parameters. If the dictionary contains a Type item, why is the "operationName" necessary at all?
Because there is a difference between operations and adjustments.
"Operations" are commands that are applied to a document, page or layer. "Adjustments" are properties of a layer. And adjustments have a "Type" key, operations don't.

So to use your operations dictionary as adjustments dictionary in VBS you have to

Code: Alles auswählen

        Set dialogSettings = layer.ShowOperationDialog("Curves")
        dialogSettings.Add "Type", "Curves"
        layer.InsertAdjustment -1, dialogSettings
This should work fine in current versions.

The corresponding PowerShell code doesn't work:

Code: Alles auswählen

        $dialogSettings = $activeLayer.ShowOperationDialog("Curves")
        $dialogSettings.Add("Type", "Curves")
        $activeLayer.InsertAdjustment(-1, $dialogSettings)
For unknown reasons, PowerShell passes $dialogSettings to PhotoLine differently than VBS does. I'll look into it.
pixel8tor
Mitglied
Beiträge: 72
Registriert: Di 24 Jul 2018 17:15

Re: Scripting issues

Beitrag von pixel8tor »

You wrote: -- I haven't been able to get some basic things to work in JXA (Apple's version of JavaScript for scripting), and from what I've read online, it has some shortcomings.

Sounds like there's no COM scripting engine that works consistently across different OSs. Too bad.

You wrote: -- If you want to also set the type, you will have to explicitly create an IPLCurve. Something like this:
Set curve = CreateObject("PhotoLine.Curve")
curve.Type = 1
curve.Points = Array(0, 0, 0.5, 0.6, 1, 1)
adjustmentLayer.InsertAdjustment -1, "Type", "Curves", "Contrast", 60, "CurveMain", curve
Attention: I didn't test that and just typed it in the browser.

This is a good news bad news situation. Creating a Curve object does work to set the curve type, but the bad news is "curve.Points = Array(0, 0, 0.5, 0.6, 1, 1)" throws an error. I asked AI about it and it said VBS has no native way to add the array of points to curve.Points. Something about wrong data type and needing an "adapter" to do that. So I was wondering if you could either add an "Add" method to the "PhotoLine.Curve" object. I have no idea how difficult that is, so it might be too much to ask. Or could you add to the parser that decodes the parameters in "adjustmentLayer.InsertAdjustment -1, "Type", "Curves", "Contrast", 60, "CurveMain", curve" so it would parse "CurveMainType = 1" to set the curve type for each Curve (Main, 1, 2,...). If either of these options is doable without too much effort it would be helpful. Thanks

You wrote: -- I really recommend switching to PowerShell.

Currently I don't have a compelling reason to learn PowerShell scripting. Maybe once I've got this script usable with VBS, I might use an AI translator to produce a PS1 version and learn from that. I might also try that to produce a Mac version, since there seems to be no common scripting engine. Or maybe someone on the forum, than knows both AppleScript and VBS, could do it. But that's off in the future.

You wrote: -- Because there is a difference between operations and adjustments.

Thanks for explaining the difference between the dictionaries. I guess my assumption was wrong about dictionaries being self contained. In other words, always having a "Type" item that referred to what the rest of the dictionary items referred to.

You wrote: -- So to use your operations dictionary as adjustments dictionary in VBS you have to
Set dialogSettings = layer.ShowOperationDialog("Curves")
dialogSettings.Add "Type", "Curves"
layer.InsertAdjustment -1, dialogSettings
This should work fine in current versions.

Actually this doesn't work in the current version because "dialogsettings" doesn't get any Curve items! That's what started off this whole discussion.

You wrote: -- The corresponding PowerShell code doesn't work . . .

Isn't coding fun?!
Martin Huber
Entwickler
Entwickler
Beiträge: 4298
Registriert: Di 19 Nov 2002 15:49

Re: Scripting issues

Beitrag von Martin Huber »

pixel8tor hat geschrieben: Do 18 Jun 2026 18:41 This is a good news bad news situation. Creating a Curve object does work to set the curve type, but the bad news is "curve.Points = Array(0, 0, 0.5, 0.6, 1, 1)" throws an error. I asked AI about it and it said VBS has no native way to add the array of points to curve.Points. Something about wrong data type and needing an "adapter" to do that.
That already worked fine in my internal version and it should work in 25.60b3.

Since our discussion is no longer about the current version, I'm starting a new thread in the beta group where we can continue our discussion.