Lightroom SDK: Add something like 'photo:setDevelopSettings' to the API

  • 4
  • Idea
  • Updated 4 years ago
  • (Edited)
Hey Adobe,

for plugin development it would be a huge step to have a method like
photo:setDevelopSettings("$setting", $value)
to be able to change DevelopSettings. I'm currently working on a plugin and this its a huge drawback not be able to write them directly. I'm currently working around with saving metadata, modify them via an external script and read them back but I think that could be much easier.

Kind regards,
Ingmar Rieger
Photo of Ingmar Rieger

Ingmar Rieger

  • 4 Posts
  • 0 Reply Likes

Posted 6 years ago

  • 4
Photo of Rob Cole

Rob Cole

  • 4831 Posts
  • 382 Reply Likes
You can set develop settings like you want now - using (on-the-fly) plugin presets.

It's not quite as slick as photo:setDevelopSettings would be, but it can be done, for example:

--- Adjust specified settings.
--
-- @param photos (array of LrPhoto, reauired) photos to adjust.
-- @param undoTitle (string, reauired) alias: presetName.
-- @param ments (table, required) adjust-ments to make, as a table of name/value pairs.
-- @param tmo (number, default=10) seconds to wait for catalog - ignored if already has write access.
--
-- @usage will wrap with catalog accessor if need be.
-- @usage synchronous - must be called from async task.
--
-- @return status.
-- @return message
--
function DevelopSettings:adjustPhotos( photos, undoTitle, ments, tmo )
return app:call( Call:new{ name=undoTitle, async=false, main=function( call )
local function adjust()
local preset = LrApplication.addDevelopPresetForPlugin( _PLUGIN, undoTitle, ments )
if preset then
app:logVerbose( "Got preset named '^1'", undoTitle )
else
error( "No preset" )
end
for i, photo in ipairs( photos ) do
photo:applyDevelopPreset( preset, _PLUGIN )
end
end
if catalog.hasWriteAccess then
adjust()
else
local s, m = cat:update( tmo or 10, call.name, adjust )
if not s then
error( m )
end
end
end } )
end

from the Elare Plugin Framework.

Consider also some code to clean up. I put this in plugin init module:

local presets = LrApplication.getDevelopPresetsForPlugin( _PLUGIN ) -- hopefully no need to yield.
for _, preset in ipairs( presets ) do
local file = preset:getFile()
if fso:existsAsFile( file ) then
LrFileUtils.delete( file )
end
end

*** WARNING: you can set most but not *all* settings this way, notable exclusions:
* Crop
* Orientation
* ToneCurve Enable/Disable

-------------------------------
My .02: Although a less-cumbersome means to set develop settings would be nice, what would be better, IMHO is if *all* develop setting were supported, so settings could be saved and restored, or synchronized by plugins, without loss.
--------------------------------

Rob
Photo of Rob Cole

Rob Cole

  • 4831 Posts
  • 382 Reply Likes
Some things to be aware of:

Some things require "settling time" before they "take".

Examples:
* Switching process version.
* Custom white balance.
* Enabling profile-based lens corrections.

Thus, you must apply pre-requisites and then return from the catalog:with-do gate, then wait a spell, before you can do dependent things...

Example of assuring auto-tone has settled:

local s, m = devSettings:adjustPhotos( { photo }, "Auto Tone", { AutoTone=true } )
local dev2
if s then
local count = 0
app:log( "Auto-tone'd" )
repeat
app:sleep( .2 ) -- typically takes from .1 to 2 seconds, total, so 1/5 second polling interval seems reasonable.
dev2 = photo:getDevelopSettings()
if dev2.Blacks2012 > -100 then
dbgf( "Settled after ^1 re-checks.", count )
break
else -- Lr dev settings are "busy"
count = count + 1
if count == 100 then -- ten seconds => give up.
call:abort( "Auto-tone not settling." )
return
end
end
until false


Rob
Photo of Ingmar Rieger

Ingmar Rieger

  • 4 Posts
  • 0 Reply Likes
Hey Rob,

thank you for your answer and your code sample. I now finally found time to play with my plugin development again and played with your code snippet but I'm stopped by the call of "Call:new" at the begin of the function which throws the following exception:
2012-11-11 22:52:04.305 Adobe Photoshop Lightroom 4[2266:707] Oops! An untagged string ([string "TestDevSettings.lua"]:39: attempt to index global 'Call' (a nil value)) got thrown far enough that we display it to the user. This shouldn't happen.

Any idea how this happens? Do I have to import something to get this class (Call) to work?

And what is the "settling time" needed for you mention in your second post? I'm working on a plugin which will change the Exposure2012 and the Temperature/Tint values. Do I need to always wait for each photo, at the end of the process or can I ignore it when I'm not doing more on the photo after applying the preset?
Photo of Rob Cole

Rob Cole

  • 4831 Posts
  • 382 Reply Likes
Hi Ingmar,

Sorry - this code is taken from the elare plugin framework, and must be massaged to fit your plugin environment/context, or executed in a plugin that uses the elare plugin framework.

The "Call" object is just a wrapper for the main function call, which has options for error handling, async vs. sync, recursion-guarding, progress-scope, ...

The take-away from this example is the code that creates the preset to embody the develop adjustments, and then applies the preset in a catalog:withWriteAccessDo function.

Settling:
- You *must* assure custom white-balance mode has settled, *before* attempting to change the temperature or tint.
- You *must* assure process version of 6.6(PV2012-beta) or 6.7(PV2012-final) has settled before changing Exposure2012.

Consider downloading Cookmarks for example.

Rob
Photo of Ingmar Rieger

Ingmar Rieger

  • 4 Posts
  • 0 Reply Likes
Ok, thank you. I think now I got the point and will play a bit more with it. But I'm unclear about what you're saying about the settling: Do I have to apply a preset which sets white balance to Custom and then apply another with temperature and tint or can I do it with one preset?

And the cleanup sample you mentioned in your first post. Does deleting the presets in the filesystem also deletes them from the Lightroom database? I'm going to need a lot of presets and I think this would blow the Lightroom database very fast.
Photo of Rob Cole

Rob Cole

  • 4831 Posts
  • 382 Reply Likes
WB settling: Yes. - two presets - one to make pre-requisite adjustments (exit withWriteAccessDo method, then wait a while). the other to make dependent adjustments (new call to withWriteAccessDo method). In this case, the first preset will set white balance to custom, and the other will do the temperature/tint adjustment(s).

PS - I wish all this was handled by Lightroom proper so plugins didn't have to deal with it...

Cleanup deletes files, Lr builds database from files present during startup (before plugins run). So each startup, you are cleaning up from the last "session". I had 3000 presets for one plugin before I added the cleanup. Definitely a good idea...

Cheers,
Rob
Photo of Ingmar Rieger

Ingmar Rieger

  • 4 Posts
  • 0 Reply Likes
Hey Rob,

thank you very much for your help. My plugin base is now mostly working. One (hopefully) last question I have, maybe you can help: How can I read the current value for temperature and tint? This were the only settings I'd need for my plugin which I wasn't able to find in the API so far.
Photo of Rob Cole

Rob Cole

  • 4831 Posts
  • 382 Reply Likes
Sounds good...

local settings = photo:getDevelopSettings()

raw:
settings.Temperature -- or settings['Temperature'] - similarly for the others...
settings.Tint

rgb:
settings.IncrementalTemperature
settings.IncrementalTint

Note: consider using John Ellis debugging toolkit and call:
Debug.init( true )
Debug.lognpp( settings )

Note: the temperature and tint settings for raw won't be there until white balance is set to custom. Although Lightroom shows the white balance values corresponding to "as shot", they aren't develop settings yet in the strictest sense until after custom adjustment.

PS - the Lightroom SDK forum is a good place for this type of discussion too.

Rob
Photo of matt

matt

  • 2 Posts
  • 0 Reply Likes
Hi,
im wondering if plugin-on the fly preset can be applied on settings in Develop module that user can actually see effects in lightroom module itself?
Photo of Rob Cole

Rob Cole

  • 4831 Posts
  • 382 Reply Likes
yes
Photo of matt

matt

  • 2 Posts
  • 0 Reply Likes
so basically if plugin gonna make preset with increased exposure the exposure change and slider gonna move too? Am i understanding that correctly?
Photo of Rob Cole

Rob Cole

  • 4831 Posts
  • 382 Reply Likes
yep - try it and you'll see.
Photo of Gunther Wegner

Gunther Wegner

  • 33 Posts
  • 10 Reply Likes
I'm trying to modify some gradient based adjustments using that method, but unfortunately without success yet.

This is what I'm doing:

local set = photo:getDevelopSettings();

-- Get the current Gradients
gradients = set['GradientBasedCorrections']

-- Modify a setting
gradients[1].LocalExposure2012 = 1

-- Creating temporary preset
local preset = LrApplication.addDevelopPresetForPlugin(pluginObject, 'testing', gradients)

if preset then
photo:applyDevelopPreset( preset, pluginObject )
else
local a = LrDialogs.message(tostring(pluginObject))
end

What happens is, that "preset" is nil and thus does not get applied.
Any help would be appreciated!

Thank you!
Photo of Rob Cole

Rob Cole

  • 4831 Posts
  • 382 Reply Likes
Notes:
* pluginObject should be _PLUGIN (unless you're using Elare Script Framework).
* when you create a preset, try passing 'set' instead of 'gradients', to make sure you have everything else squared away before you try modifying the gradients.
* Consider dumping the 'set' variable using John Ellis' Debug.lognpp function or the like, so you can see exactly what it contains..
R