Copy link to clipboard
Copied
-- Access the Lightroom SDK namespaces.
local LrDialogs = import 'LrDialogs'
local LrFunctionContext = import 'LrFunctionContext'
local LrBinding = import 'LrBinding'
local LrView = import 'LrView'
local LrApplication = import 'LrApplication'
local LrExportSession = import 'LrExportSession'
local LrTasks = import 'LrTasks'
-- Process pictures and save them as JPEG
local function processPhotos(photos, outputFolder)
LrFunctionContext.callWithContext("export", function(exportContext)
local progressScope = LrDialogs.showModalProgressDialog({
title = "Auto applying presets",
caption = "",
cannotCancel = false,
functionContext = exportContext
})
local exportSession = LrExportSession({
photosToExport = photos,
exportSettings = {
LR_collisionHandling = "rename",
LR_export_bitDepth = "8",
LR_export_colorSpace = "sRGB",
LR_export_destinationPathPrefix = outputFolder,
LR_export_destinationType = "specificFolder",
LR_export_useSubfolder = false,
LR_format = "JPEG",
LR_jpeg_quality = 1,
LR_minimizeEmbeddedMetadata = true,
LR_outputSharpeningOn = false,
LR_reimportExportedPhoto = false,
LR_renamingTokensOn = true,
-- LR_size_doConstrain = true,
LR_size_doNotEnlarge = true,
-- LR_size_maxHeight = 2000,
-- LR_size_maxWidth = 2000,
-- LR_size_resolution = 72,
LR_size_units = "pixels",
LR_tokens = "{{image_name}}",
LR_useWatermark = true,
LR_watermarking_id = "{{simpleCopyrightWatermark}}",
}
})
local numPhotos = exportSession:countRenditions()
local renditionParams = {
progressScope = progressScope,
renderProgressPortion = 1,
stopIfCanceled = true,
}
for i, rendition in exportSession:renditions(renditionParams) do
-- Stop processing if the cancel button has been pressed
if progressScope:isCanceled() then
break
end
-- Common caption for progress bar
local progressCaption = rendition.photo:getFormattedMetadata("fileName") .. " (" .. i .. "/" .. numPhotos .. ")"
progressScope:setPortionComplete(i - 1, numPhotos)
progressScope:setCaption("Processing " .. progressCaption)
rendition:waitForRender()
end
end)
end
-- Import pictures from folder where the rating is not 2 stars
local function importFolder(LrCatalog, folder, outputFolder)
local presetFolders = LrApplication.developPresetFolders()
local presetFolder = presetFolders[1]
local presets = presetFolder:getDevelopPresets()
LrTasks.startAsyncTask(function()
local photos = folder:getPhotos()
local export = {}
for _, photo in pairs(photos) do
if (photo:getRawMetadata("rating") ~= 2 ) then
LrCatalog:withWriteAccessDo("Apply Preset", function(context)
for _, preset in pairs(presets) do
photo:applyDevelopPreset(preset)
end
photo:setRawMetadata("rating", 2)
table.insert(export, photo)
end)
end
end
if #export > 0 then
processPhotos(export, outputFolder)
end
end)
end
-- GUI specification
local function customPicker()
LrFunctionContext.callWithContext("showCustomDialogWithObserver", function(context)
local props = LrBinding.makePropertyTable(context)
local f = LrView.osFactory()
local outputFolderField = f:edit_field {
immediate = true,
value = "D:\\Pictures"
}
local staticTextValue = f:static_text {
title = "Not started",
}
local function myCalledFunction()
staticTextValue.title = props.myObservedString
end
LrTasks.startAsyncTask(function()
local LrCatalog = LrApplication.activeCatalog()
local catalogFolders = LrCatalog:getFolders()
local folderCombo = {}
local folderIndex = {}
for i, folder in pairs(catalogFolders) do
folderCombo[i] = folder:getName()
folderIndex[folder:getName()] = i
end
local folderField = f:combo_box {
items = folderCombo
}
local watcherRunning = false
-- Watcher, executes function and then sleeps 60 seconds using PowerShell
local function watch()
LrTasks.startAsyncTask(function()
while watcherRunning do
LrDialogs.showBezel("Processing images.")
importFolder(LrCatalog, catalogFolders[folderIndex[folderField.value]], outputFolderField.value)
if LrTasks.canYield() then
LrTasks.yield()
end
LrTasks.execute("powershell Start-Sleep -Seconds 3")
end
end)
end
props:addObserver("myObservedString", myCalledFunction)
local c = f:column {
spacing = f:dialog_spacing(),
f:row {
fill_horizontal = 1,
f:static_text {
alignment = "right",
width = LrView.share "label_width",
title = "Watcher running: "
},
staticTextValue,
},
f:row {
f:static_text {
alignment = "right",
width = LrView.share "label_width",
title = "Select folder: "
},
folderField
},
f:row {
f:static_text {
alignment = "right",
width = LrView.share "label_width",
title = "Output folder: "
},
outputFolderField
},
f:row {
f:push_button {
title = "Process once",
action = function()
if folderField.value ~= "" then
props.myObservedString = "Processed once"
importFolder(LrCatalog, catalogFolders[folderIndex[folderField.value]], outputFolderField.value)
else
LrDialogs.message("Please select an input folder")
end
end
},
f:push_button {
title = "Watch every 3s",
action = function()
watcherRunning = true
if folderField.value ~= "" then
props.myObservedString = "Running"
watch()
else
LrDialogs.message("Please select an input folder")
end
end
},
f:push_button {
title = "Pause watcher",
action = function()
watcherRunning = false
props.myObservedString = "Stopped after running"
end
}
},
}
LrDialogs.presentModalDialog {
title = "Auto Export fullsize Watcher",
contents = c,
-- Preferrably cancel should stop the script
-- OK can be changed to run in background
-- actionBinding = {
-- enabled = {
-- bind_to_object = props,
-- key = 'actionDisabled'
-- },
-- }
}
end)
end)
end
customPicker()
i want to add watermark to this script, but always fail, maybe whats wrong with my code??
Copy link to clipboard
Copied
There were lots of problems with the script when I tried to run it.
Most importantly, trying to develop plugins without a debugger is futile. When an error occurs in any task except the main task, LR usually silently terminates that task without displaying anything to the user. That's why the script was silently failing.
Consider the Zerobrane IDE or my Debugging Toolkit. My toolkit is lighter weight with far fewer features, but it understands LR's unique task architecture better and it has a better pretty printer for structured values. Both options require you to instrument your code.
I've attached a working version of the script (at least Process Once works -- didn't try the other buttons). It's instrumented for use with the Debugging Toolkit. An incomplete list of the things I fixed and simplified:
1. The code wasn't properly accessing the values of controls using LrView.bind. See the section Binding UI Values To Data Values in Chapter 5 of the Lightroom Classic Programmers Guide.
2. Used paths (strings) rather than LrFolders for the input and output folders. This simplified the handling of the corresponding combo boxes considerably.
3. Introduced a global variable "catalog" rather than use a misleadingly named local variable "LrCatalog".
4. Added a timeout to catalog:withWriteAccessDo().
5. Used LrTasks.sleep(3) rather than run Powershell.
6. The built-in Simple Copyright Watermark preset doesn't work in my Mac LR, independent of this script -- not sure what's going wrong there. So I changed LrExportSession() to use the unique id of my own watermark preset that doesn't the same thing. (Get the unique id by opening the .lrtemplate for the watermark in a text editor.)
Copy link to clipboard
Copied
"The built-in Simple Copyright Watermark preset doesn't work in my Mac LR, independent of this script -- not sure what's going wrong there."
I was hallucinating -- the test file I was exporting didn't have a value for the IPTC Copyright field.