Commit 3c969e30 authored by Ulrich Pegelow's avatar Ulrich Pegelow

blending: add option to display channels in false colors

parent ad623431
......@@ -593,6 +593,18 @@
<shortdescription>smoothing of brush strokes</shortdescription>
<longdescription>sets level for smoothing of brush strokes. stronger smoothing leads to less nodes and easier editing but with lower control of accuracy.</longdescription>
</dtconfig>
<dtconfig prefs="gui">
<name>channel_display</name>
<type>
<enum>
<option>false color</option>
<option>grey scale</option>
</enum>
</type>
<default>false color</default>
<shortdescription>display of individual color channels</shortdescription>
<longdescription>defines how color channels are displayed when activated in the parametric masks feature.</longdescription>
</dtconfig>
<dtconfig>
<name>database_cache_quality</name>
<type>int</type>
......
......@@ -315,6 +315,7 @@ static void _blendop_masks_mode_callback(GtkWidget *combo, dt_iop_gui_blend_data
if(dt_iop_module_colorspace(data->module) == iop_cs_RAW)
{
data->module->request_mask_display = DT_DEV_PIXELPIPE_DISPLAY_NONE;
dtgtk_button_set_paint(DTGTK_BUTTON(data->showmask), dtgtk_cairo_paint_showmask, CPF_STYLE_FLAT | CPF_DO_NOT_USE_BORDER);
gtk_widget_hide(GTK_WIDGET(data->showmask));
}
else
......@@ -327,6 +328,7 @@ static void _blendop_masks_mode_callback(GtkWidget *combo, dt_iop_gui_blend_data
else
{
data->module->request_mask_display = DT_DEV_PIXELPIPE_DISPLAY_NONE;
dtgtk_button_set_paint(DTGTK_BUTTON(data->showmask), dtgtk_cairo_paint_showmask, CPF_STYLE_FLAT | CPF_DO_NOT_USE_BORDER);
data->module->suppress_mask = 0;
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->suppress), 0);
......@@ -557,6 +559,12 @@ static void _blendop_blendif_showmask_clicked(GtkWidget *button, GdkEventButton
else
module->request_mask_display |= (has_mask_display ? 0 : DT_DEV_PIXELPIPE_DISPLAY_MASK);
if(module->request_mask_display & (DT_DEV_PIXELPIPE_DISPLAY_MASK | DT_DEV_PIXELPIPE_DISPLAY_CHANNEL))
dtgtk_button_set_paint(DTGTK_BUTTON(button), dtgtk_cairo_paint_showmask, CPF_STYLE_FLAT | CPF_DO_NOT_USE_BORDER | CPF_ACTIVE);
else
dtgtk_button_set_paint(DTGTK_BUTTON(button), dtgtk_cairo_paint_showmask, CPF_STYLE_FLAT | CPF_DO_NOT_USE_BORDER);
if(module->off) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(module->off), 1);
dt_iop_request_focus(module);
......@@ -1521,6 +1529,7 @@ void dt_iop_gui_update_blending(dt_iop_module_t *module)
if(dt_iop_module_colorspace(module) == iop_cs_RAW)
{
module->request_mask_display = DT_DEV_PIXELPIPE_DISPLAY_NONE;
dtgtk_button_set_paint(DTGTK_BUTTON(bd->showmask), dtgtk_cairo_paint_showmask, CPF_STYLE_FLAT | CPF_DO_NOT_USE_BORDER);
gtk_widget_hide(GTK_WIDGET(bd->showmask));
}
else
......@@ -1533,6 +1542,7 @@ void dt_iop_gui_update_blending(dt_iop_module_t *module)
else
{
module->request_mask_display = DT_DEV_PIXELPIPE_DISPLAY_NONE;
dtgtk_button_set_paint(DTGTK_BUTTON(bd->showmask), dtgtk_cairo_paint_showmask, CPF_STYLE_FLAT | CPF_DO_NOT_USE_BORDER);
module->suppress_mask = 0;
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(bd->suppress), 0);
......
......@@ -23,6 +23,7 @@
#include <stdlib.h>
#include <string.h>
#include "common/colorspaces.h"
#include "control/control.h"
#include "develop/develop.h"
#include "gui/accelerators.h"
......@@ -59,6 +60,128 @@ int flags()
return IOP_FLAGS_HIDDEN | IOP_FLAGS_ONE_INSTANCE;
}
static inline float Hue_2_RGB(float v1, float v2, float vH)
{
if(vH < 0.0f) vH += 1.0f;
if(vH > 1.0f) vH -= 1.0f;
if((6.0f * vH) < 1.0f) return (v1 + (v2 - v1) * 6.0f * vH);
if((2.0f * vH) < 1.0f) return (v2);
if((3.0f * vH) < 2.0f) return (v1 + (v2 - v1) * ((2.0f / 3.0f) - vH) * 6.0f);
return (v1);
}
static inline void HSL_2_RGB(const float *HSL, float *RGB)
{
float H = HSL[0];
float S = HSL[1];
float L = HSL[2];
float var_1, var_2;
if(S < 1e-6f)
{
RGB[0] = RGB[1] = RGB[2] = L;
}
else
{
if(L < 0.5f)
var_2 = L * (1.0f + S);
else
var_2 = (L + S) - (S * L);
var_1 = 2.0f * L - var_2;
RGB[0] = Hue_2_RGB(var_1, var_2, H + (1.0f / 3.0f));
RGB[1] = Hue_2_RGB(var_1, var_2, H);
RGB[2] = Hue_2_RGB(var_1, var_2, H - (1.0f / 3.0f));
}
}
static inline void LCH_2_Lab(const float *LCH, float *Lab)
{
Lab[0] = LCH[0];
Lab[1] = cosf(2.0f * M_PI * LCH[2]) * LCH[1];
Lab[2] = sinf(2.0f * M_PI * LCH[2]) * LCH[1];
}
static inline void LCH_2_RGB(const float *LCH, float *RGB)
{
float Lab[3], XYZ[3];
LCH_2_Lab(LCH, Lab);
dt_Lab_to_XYZ(Lab, XYZ);
dt_XYZ_to_sRGB(XYZ, RGB);
}
static inline void Lab_2_RGB(const float *Lab, float *RGB)
{
float XYZ[3];
dt_Lab_to_XYZ(Lab, XYZ);
dt_XYZ_to_sRGB(XYZ, RGB);
}
static inline void false_color(float val, dt_dev_pixelpipe_display_mask_t channel, float *out)
{
float in[3];
switch((channel & DT_DEV_PIXELPIPE_DISPLAY_ANY) & ~DT_DEV_PIXELPIPE_DISPLAY_OUTPUT)
{
case DT_DEV_PIXELPIPE_DISPLAY_a:
in[0] = 50.0f;
in[1] = val * 256.0f - 128.0f;
in[2] = 0.0f;
Lab_2_RGB(in, out);
break;
case DT_DEV_PIXELPIPE_DISPLAY_b:
in[0] = 50.0f;
in[1] = 0.0f;
in[2] = val * 256.0f - 128.0f;
Lab_2_RGB(in, out);
break;
case DT_DEV_PIXELPIPE_DISPLAY_R:
out[0] = val;
out[1] = out[2] = 0.0f;
break;
case DT_DEV_PIXELPIPE_DISPLAY_G:
out[1] = val;
out[0] = out[2] = 0.0f;
break;
case DT_DEV_PIXELPIPE_DISPLAY_B:
out[2] = val;
out[0] = out[1] = 0.0f;
break;
case DT_DEV_PIXELPIPE_DISPLAY_LCH_C:
in[0] = 50.0f;
in[1] = val * 128.0f * sqrtf(2.0f);
in[2] = 0.9111f;
LCH_2_RGB(in, out);
break;
case DT_DEV_PIXELPIPE_DISPLAY_LCH_h:
in[0] = 50.0f;
in[1] = 0.25f * 128.0f * sqrtf(2.0f);
in[2] = val;
LCH_2_RGB(in, out);
break;
case DT_DEV_PIXELPIPE_DISPLAY_HSL_H:
in[0] = val;
in[1] = 1.0f;
in[2] = 0.5f;
HSL_2_RGB(in, out);
break;
case DT_DEV_PIXELPIPE_DISPLAY_HSL_S:
in[0] = 0.8333f;
in[1] = val;
in[2] = 0.5f;
HSL_2_RGB(in, out);
break;
case DT_DEV_PIXELPIPE_DISPLAY_L:
case DT_DEV_PIXELPIPE_DISPLAY_GRAY:
case DT_DEV_PIXELPIPE_DISPLAY_HSL_l:
default:
out[0] = out[1] = out[2] = val;
break;
}
}
void process(struct dt_iop_module_t *self, dt_dev_pixelpipe_iop_t *piece, const void *const i, void *const o,
const dt_iop_roi_t *const roi_in, const dt_iop_roi_t *const roi_out)
{
......@@ -66,8 +189,34 @@ void process(struct dt_iop_module_t *self, dt_dev_pixelpipe_iop_t *piece, const
const int ch = piece->colors;
const dt_dev_pixelpipe_display_mask_t mask_display = piece->pipe->mask_display;
char *str = dt_conf_get_string("channel_display");
const int fcolor = !strcmp(str, "false color");
g_free(str);
if(mask_display & (DT_DEV_PIXELPIPE_DISPLAY_CHANNEL & DT_DEV_PIXELPIPE_DISPLAY_ANY))
if((mask_display & DT_DEV_PIXELPIPE_DISPLAY_CHANNEL) && (mask_display & DT_DEV_PIXELPIPE_DISPLAY_ANY) && fcolor)
{
const float yellow[3] = { 1.0f, 1.0f, 0.0f };
#ifdef _OPENMP
#pragma omp parallel for default(none) shared(d) schedule(static)
#endif
for(int k = 0; k < roi_out->height; k++)
{
const float *in = ((float *)i) + (size_t)ch * k * roi_out->width;
uint8_t *out = ((uint8_t *)o) + (size_t)ch * k * roi_out->width;
for(int j = 0; j < roi_out->width; j++, in += ch, out += ch)
{
const float alpha = (mask_display & DT_DEV_PIXELPIPE_DISPLAY_MASK) ? in[3] : 0.0f;
float colors[3];
false_color(in[1], mask_display, colors);
for(int c = 0; c < 3; c++)
{
const float value = colors[c] * (1.0f - alpha) + yellow[c] * alpha;
out[2 - c] = d->table[(uint16_t)CLAMP((int)(0xfffful * value), 0, 0xffff)];
}
}
}
}
else if((mask_display & DT_DEV_PIXELPIPE_DISPLAY_CHANNEL) && (mask_display & DT_DEV_PIXELPIPE_DISPLAY_ANY))
{
const float yellow[3] = { 1.0f, 1.0f, 0.0f };
#ifdef _OPENMP
......@@ -82,7 +231,7 @@ void process(struct dt_iop_module_t *self, dt_dev_pixelpipe_iop_t *piece, const
float alpha = (mask_display & DT_DEV_PIXELPIPE_DISPLAY_MASK) ? in[3] : 0.0f;
for(int c = 0; c < 3; c++)
{
float value = in[1] * (1.0f - alpha) + yellow[c] * alpha;
const float value = in[1] * (1.0f - alpha) + yellow[c] * alpha;
out[2 - c] = d->table[(uint16_t)CLAMP((int)(0xfffful * value), 0, 0xffff)];
}
}
......@@ -100,11 +249,11 @@ void process(struct dt_iop_module_t *self, dt_dev_pixelpipe_iop_t *piece, const
uint8_t *out = ((uint8_t *)o) + (size_t)ch * k * roi_out->width;
for(int j = 0; j < roi_out->width; j++, in += ch, out += ch)
{
float gray = 0.3f * in[0] + 0.59f * in[1] + 0.11f * in[2];
float alpha = in[3];
const float gray = 0.3f * in[0] + 0.59f * in[1] + 0.11f * in[2];
const float alpha = in[3];
for(int c = 0; c < 3; c++)
{
float value = gray * (1.0f - alpha) + yellow[c] * alpha;
const float value = gray * (1.0f - alpha) + yellow[c] * alpha;
out[2 - c] = d->table[(uint16_t)CLAMP((int)(0xfffful * value), 0, 0xffff)];
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment