Skip to content

Commit 480e894

Browse files
aurelienpierreTurboGit
authored andcommitted
iop order: add pipe default pipe order for v3.0 JPEG
I have been told that many Fuji users prefer to edit OOC JPEGs rathen than RAWs. The default v3.0 pipe order assumes linear (RAW) input. For non-linear input, many modules need to be moved after colorin (which removes EOTF/gamma). This introduces a very similar order as the default v3.0 but tuned for JPEG input.
1 parent 14fe465 commit 480e894

File tree

3 files changed

+165
-4
lines changed

3 files changed

+165
-4
lines changed

src/common/iop_order.c

Lines changed: 152 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,8 @@ const char *iop_order_string[] =
5757
{
5858
N_("custom"),
5959
N_("legacy"),
60-
N_("v3.0")
60+
N_("v3.0 RAW"),
61+
N_("v3.0 JPEG")
6162
};
6263

6364
const char *dt_iop_order_string(const dt_iop_order_t order)
@@ -164,6 +165,7 @@ const dt_iop_order_entry_t legacy_order[] = {
164165
{ { 0.0f }, "", 0}
165166
};
166167

168+
// default order for RAW files, assumed to be linear from start
167169
const dt_iop_order_entry_t v30_order[] = {
168170
{ { 1.0 }, "rawprepare", 0},
169171
{ { 2.0 }, "invert", 0},
@@ -269,6 +271,120 @@ const dt_iop_order_entry_t v30_order[] = {
269271
{ { 0.0f }, "", 0 }
270272
};
271273

274+
// default order for JPEG/TIFF/PNG files, non-linear before colorin
275+
const dt_iop_order_entry_t v30_jpg_order[] = {
276+
// the following modules are not used anyway for non-RAW images :
277+
{ { 1.0 }, "rawprepare", 0 },
278+
{ { 2.0 }, "invert", 0 },
279+
{ { 3.0f }, "temperature", 0 },
280+
{ { 4.0f }, "highlights", 0 },
281+
{ { 5.0f }, "cacorrect", 0 },
282+
{ { 6.0f }, "hotpixels", 0 },
283+
{ { 7.0f }, "rawdenoise", 0 },
284+
{ { 8.0f }, "demosaic", 0 },
285+
// all the modules between [8; 28] expect linear RGB, so they need to be moved after colorin
286+
{ { 28.0f }, "colorin", 0 },
287+
// moved modules : (copy-pasted in the same order)
288+
{ { 28.0f }, "denoiseprofile", 0},
289+
{ { 28.0f }, "bilateral", 0},
290+
{ { 28.0f }, "rotatepixels", 0},
291+
{ { 28.0f }, "scalepixels", 0},
292+
{ { 28.0f }, "lens", 0},
293+
{ { 28.0f }, "cacorrectrgb", 0}, // correct chromatic aberrations after lens correction so that lensfun
294+
// does not reintroduce chromatic aberrations when trying to correct them
295+
{ { 28.0f }, "hazeremoval", 0},
296+
{ { 28.0f }, "ashift", 0},
297+
{ { 28.0f }, "flip", 0},
298+
{ { 28.0f }, "clipping", 0},
299+
{ { 28.0f }, "liquify", 0},
300+
{ { 28.0f }, "spots", 0},
301+
{ { 28.0f }, "retouch", 0},
302+
{ { 28.0f }, "exposure", 0},
303+
{ { 28.0f }, "mask_manager", 0},
304+
{ { 28.0f }, "tonemap", 0},
305+
{ { 28.0f }, "toneequal", 0}, // last module that need enlarged roi_in
306+
{ { 28.0f }, "crop", 0}, // should go after all modules that may need a wider roi_in
307+
{ { 28.0f }, "graduatednd", 0},
308+
{ { 28.0f }, "profile_gamma", 0},
309+
{ { 28.0f }, "equalizer", 0},
310+
// from there, it's the same as the raw order
311+
{ { 28.5f }, "diffuse", 0 },
312+
{ { 28.5f }, "channelmixerrgb", 0 },
313+
{ { 28.5f }, "censorize", 0 },
314+
{ { 28.5f }, "negadoctor", 0 }, // Cineon film encoding comes after scanner input color profile
315+
{ { 28.5f }, "blurs", 0 }, // physically-accurate blurs (motion and lens)
316+
{ { 29.0f }, "nlmeans", 0 }, // signal processing (denoising)
317+
// -> needs a signal as scene-referred as possible (even if it works in Lab)
318+
{ { 30.0f }, "colorchecker", 0 }, // calibration to "neutral" exchange colour space
319+
// -> improve colour calibration of colorin and reproductibility
320+
// of further edits (styles etc.)
321+
{ { 31.0f }, "defringe", 0 }, // desaturate fringes in Lab, so needs properly calibrated colours
322+
// in order for chromaticity to be meaningful,
323+
{ { 32.0f }, "atrous", 0 }, // frequential operation, needs a signal as scene-referred as possible to avoid halos
324+
{ { 33.0f }, "lowpass", 0 }, // same
325+
{ { 34.0f }, "highpass", 0 }, // same
326+
{ { 35.0f }, "sharpen", 0 }, // same, worst than atrous in same use-case, less control overall
327+
{ { 36.0f }, "lut3d", 0 }, // apply a creative style or film emulation, possibly non-linear,
328+
// so better move it after frequential ops that need L2 Hilbert spaces
329+
// of square summable functions
330+
{ { 37.0f }, "colortransfer", 0 }, // probably better if source and destination colours are neutralized in the
331+
// same
332+
// colour exchange space, hence after colorin and colorcheckr,
333+
// but apply after frequential ops in case it does non-linear witchcraft,
334+
// just to be safe
335+
{ { 38.0f }, "colormapping", 0 }, // same
336+
{ { 39.0f }, "channelmixer", 0 }, // does exactly the same thing as colorin, aka RGB to RGB matrix conversion,
337+
// but coefs are user-defined instead of calibrated and read from ICC
338+
// profile. Really versatile yet under-used module, doing linear ops, very
339+
// good in scene-referred workflow
340+
{ { 40.0f }, "basicadj", 0 }, // module mixing view/model/control at once, usage should be discouraged
341+
{ { 41.0f }, "colorbalance", 0 }, // scene-referred color manipulation
342+
{ { 41.5f }, "colorbalancergb", 0 }, // scene-referred color manipulation
343+
{ { 42.0f }, "rgbcurve", 0 }, // really versatile way to edit colour in scene-referred and display-referred
344+
// workflow
345+
{ { 43.0f }, "rgblevels", 0 }, // same
346+
{ { 44.0f }, "basecurve", 0 }, // conversion from scene-referred to display referred, reverse-engineered
347+
// on camera JPEG default look
348+
{ { 45.0f }, "filmic", 0 }, // same, but different (parametric) approach
349+
{ { 46.0f }, "filmicrgb", 0 }, // same, upgraded
350+
{ { 47.0f }, "colisa", 0 }, // edit contrast while damaging colour
351+
{ { 48.0f }, "tonecurve", 0 }, // same
352+
{ { 49.0f }, "levels", 0 }, // same
353+
{ { 50.0f }, "shadhi", 0 }, // same
354+
{ { 51.0f }, "zonesystem", 0 }, // same
355+
{ { 52.0f }, "globaltonemap", 0 }, // same
356+
{ { 53.0f }, "relight", 0 }, // flatten local contrast while pretending do add lightness
357+
{ { 54.0f }, "bilat", 0 }, // improve clarity/local contrast after all the bad things we have done
358+
// to it with tonemapping
359+
{ { 55.0f }, "colorcorrection", 0 }, // now that the colours have been damaged by contrast manipulations,
360+
// try to recover them - global adjustment of white balance for shadows and
361+
// highlights
362+
{ { 56.0f }, "colorcontrast", 0 }, // adjust chrominance globally
363+
{ { 57.0f }, "velvia", 0 }, // same
364+
{ { 58.0f }, "vibrance", 0 }, // same, but more subtle
365+
{ { 60.0f }, "colorzones", 0 }, // same, but locally
366+
{ { 61.0f }, "bloom", 0 }, // creative module
367+
{ { 62.0f }, "colorize", 0 }, // creative module
368+
{ { 63.0f }, "lowlight", 0 }, // creative module
369+
{ { 64.0f }, "monochrome", 0 }, // creative module
370+
{ { 65.0f }, "grain", 0 }, // creative module
371+
{ { 66.0f }, "soften", 0 }, // creative module
372+
{ { 67.0f }, "splittoning", 0 }, // creative module
373+
{ { 68.0f }, "vignette", 0 }, // creative module
374+
{ { 69.0f }, "colorreconstruct", 0 }, // try to salvage blown areas before ICC intents in LittleCMS2 do things
375+
// with them.
376+
{ { 70.0f }, "colorout", 0 },
377+
{ { 71.0f }, "clahe", 0 },
378+
{ { 72.0f }, "finalscale", 0 },
379+
{ { 73.0f }, "overexposed", 0 },
380+
{ { 74.0f }, "rawoverexposed", 0 },
381+
{ { 75.0f }, "dither", 0 },
382+
{ { 76.0f }, "borders", 0 },
383+
{ { 77.0f }, "watermark", 0 },
384+
{ { 78.0f }, "gamma", 0 },
385+
{ { 0.0f }, "", 0 }
386+
};
387+
272388
static void *_dup_iop_order_entry(const void *src, gpointer data);
273389
static int _count_entries_operation(GList *e_list, const char *operation);
274390

@@ -447,7 +563,7 @@ gint dt_sort_iop_list_by_order_f(gconstpointer a, gconstpointer b)
447563

448564
dt_iop_order_t dt_ioppr_get_iop_order_list_kind(GList *iop_order_list)
449565
{
450-
// first check if this is the v30 order
566+
// first check if this is the v30 order RAW
451567
int k = 0;
452568
GList *l = iop_order_list;
453569
gboolean ok = TRUE;
@@ -473,6 +589,32 @@ dt_iop_order_t dt_ioppr_get_iop_order_list_kind(GList *iop_order_list)
473589

474590
if(ok) return DT_IOP_ORDER_V30;
475591

592+
// then check if this is the v30 order JPG
593+
k = 0;
594+
l = iop_order_list;
595+
ok = TRUE;
596+
while(l)
597+
{
598+
const dt_iop_order_entry_t *const restrict entry = (dt_iop_order_entry_t *)l->data;
599+
if(strcmp(v30_jpg_order[k].operation, entry->operation))
600+
{
601+
ok = FALSE;
602+
break;
603+
}
604+
else
605+
{
606+
// skip all the other instance of same module if any
607+
while(g_list_next(l)
608+
&& !strcmp(v30_jpg_order[k].operation, ((dt_iop_order_entry_t *)(g_list_next(l)->data))->operation))
609+
l = g_list_next(l);
610+
}
611+
612+
k++;
613+
l = g_list_next(l);
614+
}
615+
616+
if(ok) return DT_IOP_ORDER_V30_JPG;
617+
476618
// then check if this is the legacy order
477619
k = 0;
478620
l = iop_order_list;
@@ -596,6 +738,10 @@ GList *dt_ioppr_get_iop_order_list_version(dt_iop_order_t version)
596738
{
597739
iop_order_list = _table_to_list(v30_order);
598740
}
741+
else if(version == DT_IOP_ORDER_V30_JPG)
742+
{
743+
iop_order_list = _table_to_list(v30_jpg_order);
744+
}
599745

600746
return iop_order_list;
601747
}
@@ -677,6 +823,10 @@ GList *dt_ioppr_get_iop_order_list(int32_t imgid, gboolean sorted)
677823
{
678824
iop_order_list = _table_to_list(v30_order);
679825
}
826+
else if(version == DT_IOP_ORDER_V30_JPG)
827+
{
828+
iop_order_list = _table_to_list(v30_jpg_order);
829+
}
680830
else
681831
fprintf(stderr, "[dt_ioppr_get_iop_order_list] invalid iop order version %d for imgid %d\n", version, imgid);
682832

src/common/iop_order.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,8 @@ typedef enum dt_iop_order_t
133133
DT_IOP_ORDER_CUSTOM = 0, // a customr order (re-ordering the pipe)
134134
DT_IOP_ORDER_LEGACY = 1, // up to dt 2.6.3
135135
DT_IOP_ORDER_V30 = 2, // starts with dt 3.0
136-
DT_IOP_ORDER_LAST = 3
136+
DT_IOP_ORDER_V30_JPG = 3, // same as previous but tuned for non-linear input
137+
DT_IOP_ORDER_LAST = 4
137138
} dt_iop_order_t;
138139

139140
typedef struct dt_iop_order_entry_t

src/libs/ioporder.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,11 @@ void update(dt_lib_module_t *self)
117117
d->current_mode = kind;
118118
gtk_label_set_text(GTK_LABEL(d->widget), _(dt_iop_order_string(DT_IOP_ORDER_V30)));
119119
}
120+
else if(kind == DT_IOP_ORDER_V30_JPG)
121+
{
122+
d->current_mode = kind;
123+
gtk_label_set_text(GTK_LABEL(d->widget), _(dt_iop_order_string(DT_IOP_ORDER_V30_JPG)));
124+
}
120125
}
121126

122127
static void _image_loaded_callback(gpointer instance, gpointer user_data)
@@ -190,7 +195,12 @@ void init_presets(dt_lib_module_t *self)
190195

191196
list = dt_ioppr_get_iop_order_list_version(DT_IOP_ORDER_V30);
192197
params = dt_ioppr_serialize_iop_order_list(list, &size);
193-
dt_lib_presets_add(_("v3.0 (default)"), self->plugin_name, self->version(), (const char *)params, (int32_t)size,
198+
dt_lib_presets_add(_("v3.0 for RAW input (default)"), self->plugin_name, self->version(), (const char *)params, (int32_t)size,
199+
TRUE);
200+
201+
list = dt_ioppr_get_iop_order_list_version(DT_IOP_ORDER_V30_JPG);
202+
params = dt_ioppr_serialize_iop_order_list(list, &size);
203+
dt_lib_presets_add(_("v3.0 for JPEG/non-RAW input"), self->plugin_name, self->version(), (const char *)params, (int32_t)size,
194204
TRUE);
195205
free(params);
196206
}

0 commit comments

Comments
 (0)