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

LrTasks.execute() problem on Windows

Explorer ,
Feb 09, 2019 Feb 09, 2019

Copy link to clipboard

Copied

I am attempting to get a Red-Blue channel swap LR plugin to work on Windows.

See:-

Infrared Plugin for Lightroom

and

Dropbox - lr_infrared.zip

The plugin uses Imagemagick:-

convert img.jpg -set colorspace RGB -separate -swap 0,2 -combine img.jpg

or

magick img.jpg -set colorspace RGB -separate -swap 0,2 -combine img.jpg

This works fine if I execute the command from a command window.

However it doesn't work when executed from the plugin using LrTasks.execute().

The resulting jpg file does not have the channels swapped.

I'm new to the lua scripting language.

Here is the code:-

--

-- Quick Export Script to Swap Red and Blue Channels in Gimp

--   by Stu Fisher http://q3f.org

--

-- modified to use ImageMagick

--   by Chris McClanahan http://mcclanahoochie.com

--   http://mcclanahoochie.com/blog/2013/01/lightroom-plugins-infrared-and-pyrdetail

--

local LrTasks = import 'LrTasks'

local LrApplication = import 'LrApplication'

local LrLogger = import 'LrLogger'

local myLogger = LrLogger('RBSwap')

myLogger:enable("print")

exportServiceProvider = {}

exportServiceProvider.canExportVideo = false

function exportServiceProvider.processRenderedPhotos(functionContext, exportContext)

  

   local exportSession = exportContext.exportSession

   local exportSettings = exportContext.propertyTable

   local nPhotos = exportSession:countRenditions()

   local progressScope = exportContext:configureProgress {

      title =

         nPhotos > 1 and LOC("$$$/RBSwap/Publish/Progress=Exporting ^1 photos to RB swap", nPhotos)

         or              LOC "$$$/RBSwap/Publish/Progress/One=Exporting one photo to RB swap",

   }

  

   for i, rendition in exportContext:renditions { stopIfCanceled = true } do       

      progressScope:setPortionComplete((i - 1) / nPhotos)

      if not rendition.wasSkipped then

         local success, pathOrMessage = rendition:waitForRender()

         progressScope:setPortionComplete((i - 0.5) / nPhotos)

         if progressScope:isCanceled() then break end

         if success then

            local filePath = assert(pathOrMessage)

            -- choose app, configure bin paths --

            --result = LrTasks.execute("/Applications/Gimp-2.8.app/Contents/Resources/bin/gimp-2.8 -i -b '(red_blue_swap \"" .. filePath .. "\")' -b '(gimp-quit 0)'")

            if WIN_ENV then

               -- windows support thanks to Frank Firsching

               cmd = "cmd.exe /c convert.exe"

            else

               cmd = "/opt/local/bin/convert"

            end

            local cmd = cmd .. " " .. filePath .. " -set colorspace RGB -separate -swap 0,2 -combine " .. filePath

           

            result = LrTasks.execute(cmd)

            -- no need to trigger import. Done automatically by Lightroom as

            -- specified in presets/RBSwap.lrtemplate

         end

      end

   end

   progressScope:done()

end

return exportServiceProvider

I've tried adding a debug line to see if LrTasks.execute() is working:-

result = LrTasks.execute("echo 'test' > ~\\Desktop\\log.txt")

I get no log.txt file, so either I'm doing something wrong or LrTasks.execute() is not working at all.

I've tried all sorts of combinations of quoting and escape characters in the string.

Nothing seems to work.

I know the execute() function is being called because if I add 'error(cmd)' just before

LrTasks.execute(cmd) I get an error window showing the command string.

I've run out of ideas to try.

TOPICS
SDK

Views

964

Translate

Translate

Report

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
LEGEND ,
Feb 09, 2019 Feb 09, 2019

Copy link to clipboard

Copied

Skimming your code, some thoughts come to mind:

- You're not quoting the filePath argument, which is a problem if the path contains spaces.

- On Windows, you need to wrap the entire command line with an additional set of double quotes. (Who knows why, it's just magic that's needed.)

- To see what's going on, you need to check the exit code from execute() and also standard out and standard error (in case there are error messages).

- I posted the source for my Util.safeExecute() function which takes care of the Windows need for additional quotes and makes it easy to capture standard out and standard error: Re: LrTasks.execute return code 65280?

- I don't think your test line will work on either Windows or Mac:

LrTasks.execute("echo 'test' > ~\\Desktop\\log.txt")

On Windows, "~" doesn't expand to the user's home directory.  On Mac, you need "/", not "\", as the path separator.

- Because the LR execution environment is so minimal, you really need to use a debugger when developing plugins.  See here for more details: Re: Sample code for a publish service? . It will take you a couple hours to get one hooked up and get up to speed with it, but it will pay off immediately.

Votes

Translate

Translate

Report

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
Explorer ,
Feb 10, 2019 Feb 10, 2019

Copy link to clipboard

Copied

I eventually managed to get this to work after a lot of frustration and various combinations of escaping and quoting in strings.

First you need to escape backslashes in the Windows path names by converting '\' to '\\' in the file path string something like this:-

local filePath = string.gsub(assert(pathOrMessage),"\\","\\\\")

Then you need to surround the path name strings with double quotes to cope with spaces in the file names like this:-

('"' below is actually a double quote surrounded by single quotes)

filePath = '"' .. filePath .. '"'

Finally we can issue the command like this:-

if WIN_ENV then

               cmd = "magick"

            else

               cmd = "/opt/local/bin/convert"

            end

local cmd = cmd .. " " .. filePath .. " -set colorspace RGB -separate -swap 0,2 -combine " .. filePath

result = LrTasks.execute(cmd)

It is not necessary to launch a command window using cmd = "cmd.exe -c convert" as was done in the original script.

It is not necessary to wrap the entire command line with additional double quotes.

The debug test line I tried that didn't work actually came from your own previous suggestion! See:-

Problem with LrTasks.execute() method

This doesn't work because '~' does not expand to the user's home directory as you mention above.

To get it to work, I created a directory C:\Temp (with no spaces in the path name) and changed the debug line to:-

result = LrTasks.execute("echo 'test' > C:\\Temp\\log.txt")

As a retired software engineer with many years of experience on both Linux & Windows, I think the way lua handles quotes and escape characters is the most arcane (and poorly documented) features in any scripting language I have ever come across.

This link I found helps explain some of the quirks and bizarre behaviour:-

Escaping File Paths in Scripts

With so many far better scripting languages to choose from I do wonder why Adobe chose lua for lightroom plugins?

Votes

Translate

Translate

Report

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
Explorer ,
Feb 10, 2019 Feb 10, 2019

Copy link to clipboard

Copied

BTW: While debugging this plugin, I found the image icon displayed in Windows Explorer is not automatically refreshed following the RB swap.

Explorer continues to display the cached icon that was saved before to the channel swap. You have to manually refresh the window to see the updated image.

Votes

Translate

Translate

Report

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
Explorer ,
Feb 10, 2019 Feb 10, 2019

Copy link to clipboard

Copied

I should have added that 'magick.exe' and 'convert.exe' do the the same thing.

I seem to remember that 'convert' clashes with a built in command of the same name in Windows, so 'magick' is preferred to avoid confusion.

The code assumes that the path to magick.exe is in the users 'Path' environment variable.

You can check using $Env:Path in a PowerShell window.

It's easy enough to add the full path to magick.exe or convert.exe if required, but the same rules about escaping '\' and adding double quotes to allow spaces apply. I think it's probably better to rely on the 'Path' environment variable to locate the exe file, otherwise the plugin script would need to be changed if imagemagick is updated to a different version.

Votes

Translate

Translate

Report

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
LEGEND ,
Feb 10, 2019 Feb 10, 2019

Copy link to clipboard

Copied

The debug test line I tried that didn't work actually came from your own previous suggestion! See:-

Problem with LrTasks.execute() method

That example was for Mac OS, which the original poster in that thread was using:

LrTasks.execute ("echo A > ~/Desktop/log.txt")

Votes

Translate

Translate

Report

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
LEGEND ,
Feb 10, 2019 Feb 10, 2019

Copy link to clipboard

Copied

you need to escape backslashes in the Windows path names by converting '\' to '\\' in the file path string something like this:-

local filePath = string.gsub(assert(pathOrMessage),"\\","\\\\")

That isn't necessary.  You just need to double-quote file paths in case they contain spaces or other special characters.  This example works correctly:

LrTasks.execute ([[echo A > "c:\users\john\my log.txt"]])

Votes

Translate

Translate

Report

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
Explorer ,
Feb 11, 2019 Feb 11, 2019

Copy link to clipboard

Copied

LATEST

Thanks John. You are right.

When I was initially trying to get this to work I ended up changing things step by step and checking the resulting command string by writing to a log file.

Initially there were no surrounding double quotes, so escaping the backslashes in the file path was necessary.

Subsequently I added the quotes to fix the spaces in filenames issue.

I didn't realise that the additional quotes meant there was now no need to escape the backslashes.

I don't think the original script could have been tested with spaces in filenames under Windows.

I've now also changed things so that I export a RB channel swapped TIF file rather than JPG.

Imagemagick threw up some warnings about TIF tags, but it looks like they can be ignored.

'magick -quiet' removes the warnings.

Votes

Translate

Translate

Report

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
LEGEND ,
Feb 10, 2019 Feb 10, 2019

Copy link to clipboard

Copied

It is not necessary to wrap the entire command line with additional double quotes.

That's only necessary if the program path contains spaces and is quoted.  That doesn't appear to be the case in your example, so double-quoting the entire command line isn't needed.  (This is a Windows issue, not a Lua issue.)

Votes

Translate

Translate

Report

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
New Here ,
Feb 11, 2019 Feb 11, 2019

Copy link to clipboard

Copied

Just another idea, I followed this tutorial and can convert infrared pictures in Lr.

Votes

Translate

Translate

Report

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