f.refine.cc (fotoxx-22.30) | : | f.refine.cc (fotoxx-22.35) | ||
---|---|---|---|---|
skipping to change at line 1524 | skipping to change at line 1524 | |||
if (Bz1 <= Bz2) { Blo = Bz1; Bhi = Bz2; } | if (Bz1 <= Bz2) { Blo = Bz1; Bhi = Bz2; } | |||
else { Blo = Bz2; Bhi = Bz1; } | else { Blo = Bz2; Bhi = Bz1; } | |||
if (Bp <= Blo) BR = Blo / Bp; | if (Bp <= Blo) BR = Blo / Bp; | |||
else if (Bp >= Bhi) BR = Bhi / Bp; | else if (Bp >= Bhi) BR = Bhi / Bp; | |||
else BR = 1.0; | else BR = 1.0; | |||
BR = pow(Bp,BR*BR); // new pixel brightness | BR = pow(Bp,BR*BR); // new pixel brightness | |||
if (BR < 1 && Fbrite > 0) // brighten darker areas | if (BR < 1 && Fbrite > 0) // brighten darker areas | |||
BR = BR + Fbrite * pow(1.0-BR,0.3); // Fbrite, 0-1 | BR = BR + Fbrite * sqrtf(1.0-BR); // Fbrite, 0-1 22.35 | |||
R9 = BR * R1; // modified RGB values | R9 = BR * R1; // modified RGB values | |||
G9 = BR * G1; | G9 = BR * G1; | |||
B9 = BR * B1; | B9 = BR * B1; | |||
if (Fcolor) { // + saturation | if (Fcolor) { // + saturation | |||
pixbrite = 0.333 * (R9 + G9 + B9); // pixel brightness, 0-255 | pixbrite = 0.333 * (R9 + G9 + B9); // pixel brightness, 0-255 | |||
R9 = R9 + Fcolor * (R9 - pixbrite); // Fcolor, 0-1 | R9 = R9 + Fcolor * (R9 - pixbrite); // Fcolor, 0-1 | |||
G9 = G9 + Fcolor * (G9 - pixbrite); | G9 = G9 + Fcolor * (G9 - pixbrite); | |||
B9 = B9 + Fcolor * (B9 - pixbrite); | B9 = B9 + Fcolor * (B9 - pixbrite); | |||
skipping to change at line 1660 | skipping to change at line 1660 | |||
EFgradients.zd = zd; | EFgradients.zd = zd; | |||
zdialog_add_widget(zd,"frame","frame","dialog",0,"expand"); | zdialog_add_widget(zd,"frame","frame","dialog",0,"expand"); | |||
zdialog_add_widget(zd,"hbox","hb1","dialog",0,"space=5"); | zdialog_add_widget(zd,"hbox","hb1","dialog",0,"space=5"); | |||
zdialog_add_widget(zd,"label","labcL","hb1","low","space=4"); | zdialog_add_widget(zd,"label","labcL","hb1","low","space=4"); | |||
zdialog_add_widget(zd,"label","labcM","hb1","Contrast","expand"); | zdialog_add_widget(zd,"label","labcM","hb1","Contrast","expand"); | |||
zdialog_add_widget(zd,"label","labcH","hb1","high","space=5"); | zdialog_add_widget(zd,"label","labcH","hb1","high","space=5"); | |||
zdialog_add_widget(zd,"hbox","hb2","dialog",0,"space=5"); | zdialog_add_widget(zd,"hbox","hb2","dialog",0,"space=5"); | |||
zdialog_add_widget(zd,"label","labcon","hb2","Amplify","space=5"); | zdialog_add_widget(zd,"label","labcon","hb2","Amplify","space=5"); | |||
zdialog_add_widget(zd,"hscale","amplify","hb2","0|1|0.005|0","expand"); | zdialog_add_widget(zd,"hscale","amplify","hb2","0|1|0.01|0","expand"); // step size 0.01 22.35 | |||
zdialog_add_widget(zd,"label","ampval","hb2",0,"space=5"); | zdialog_add_widget(zd,"label","ampval","hb2",0,"space=5"); | |||
zdialog_add_widget(zd,"hbox","hbcf","dialog",0,"space=8"); | zdialog_add_widget(zd,"hbox","hbcf","dialog",0,"space=8"); | |||
zdialog_add_widget(zd,"label","labcf","hbcf","Curve File","space=5"); | zdialog_add_widget(zd,"label","labcf","hbcf","Curve File","space=5"); | |||
zdialog_add_widget(zd,"button","loadcurve","hbcf","Open","space=5"); | zdialog_add_widget(zd,"button","loadcurve","hbcf","Open","space=5"); | |||
zdialog_add_widget(zd,"button","savecurve","hbcf","Save","space=5"); | zdialog_add_widget(zd,"button","savecurve","hbcf","Save","space=5"); | |||
GtkWidget *frame = zdialog_gtkwidget(zd,"frame"); // set up curve edit | GtkWidget *frame = zdialog_gtkwidget(zd,"frame"); // set up curve edit | |||
spldat *sd = splcurve_init(frame,gradients_curvedit); | spldat *sd = splcurve_init(frame,gradients_curvedit); | |||
EFgradients.sd = sd; | EFgradients.sd = sd; | |||
skipping to change at line 2708 | skipping to change at line 2708 | |||
/******************************************************************************* */ | /******************************************************************************* */ | |||
// Local Retinex function | // Local Retinex function | |||
// Rescale RGB values within local areas: increase local contrast and color. | // Rescale RGB values within local areas: increase local contrast and color. | |||
namespace lretinex_names | namespace lretinex_names | |||
{ | { | |||
editfunc EFlretinex; // edit function data | editfunc EFlretinex; // edit function data | |||
cchar *thread_command; | cchar *thread_command; | |||
int E1ww, E1hh; | int E1ww, E1hh; | |||
float blend, reducedark, reducebright; | float imageblend, reducedark, reducebright; | |||
int maxzones = 2000; | int maxzones = 2000; | |||
int Nzones = 100, Pzones = 0; // zone count, 1-2000 | int Nzones = 100, Pzones = 0; // zone count, 1-2000 | |||
int zsize, zrows, zcols, zww, zhh; // zone data | int zsize, zrows, zcols, zww, zhh; // zone data | |||
typedef struct { // zone structure | typedef struct { // zone structure | |||
int cx, cy; // zone center in image | int cx, cy; // zone center in image | |||
float minR, minG, minB; // RGB minimum values in zone | float minR, minG, minB; // RGB minimum values in zone | |||
float maxR, maxG, maxB; // RGB mazimum values in zone | float maxR, maxG, maxB; // RGB mazimum values in zone | |||
} zone_t; | } zone_t; | |||
skipping to change at line 2743 | skipping to change at line 2743 | |||
F1_help_topic = "local retinex"; | F1_help_topic = "local retinex"; | |||
Plog(1,"m_lretinex \n"); | Plog(1,"m_lretinex \n"); | |||
EFlretinex.menuname = "Local Retinex"; | EFlretinex.menuname = "Local Retinex"; | |||
EFlretinex.menufunc = m_lretinex; | EFlretinex.menufunc = m_lretinex; | |||
EFlretinex.Farea = 2; // select area usable | EFlretinex.Farea = 2; // select area usable | |||
EFlretinex.Frestart = 1; // allow restart | EFlretinex.Frestart = 1; // allow restart | |||
EFlretinex.Fscript = 1; // scripting supported | EFlretinex.Fscript = 1; // scripting supported | |||
EFlretinex.Fpaintedits = 1; // use with paint edits OK 22.35 | ||||
EFlretinex.threadfunc = lretinex_thread; // thread function | EFlretinex.threadfunc = lretinex_thread; // thread function | |||
if (! edit_setup(EFlretinex)) return; // setup edit | if (! edit_setup(EFlretinex)) return; // setup edit | |||
E1ww = E1pxm->ww; // image size | E1ww = E1pxm->ww; // image size | |||
E1hh = E1pxm->hh; | E1hh = E1pxm->hh; | |||
E9pxm = PXM_copy(E1pxm); | E9pxm = PXM_copy(E1pxm); | |||
/*** | /*** | |||
______________________________________ | ______________________________________ | |||
| Local Retinex | | | Local Retinex | | |||
| | | | | | |||
| zone count: [___] [apply] | | | zone count: [___] [apply] | | |||
| blend: =======[]=================== | | | image blend: =======[]============= | | |||
| reduce dark: ==========[]========== | | | reduce dark: ==========[]========== | | |||
| reduce bright: ==========[]======== | | | reduce bright: ==========[]======== | | |||
| | | | | | |||
| [reset] [ OK ] [cancel] | | | [reset] [ OK ] [cancel] | | |||
|______________________________________| | |______________________________________| | |||
***/ | ***/ | |||
zdialog *zd = zdialog_new("Local Retinex",Mwin,"Reset","OK","Cancel",null); | zdialog *zd = zdialog_new("Local Retinex",Mwin,"Reset","OK","Cancel",null); | |||
EFlretinex.zd = zd; | EFlretinex.zd = zd; | |||
zdialog_add_widget(zd,"hbox","hbz","dialog",0,"space=3"); | zdialog_add_widget(zd,"hbox","hbz","dialog",0,"space=3"); | |||
zdialog_add_widget(zd,"label","labzs","hbz","zone count:","space=5"); | zdialog_add_widget(zd,"label","labzs","hbz","zone count:","space=5"); | |||
zdialog_add_widget(zd,"zspin","zone count","hbz","20|2000|10|100"); // max. zones | zdialog_add_widget(zd,"zspin","zone count","hbz","20|2000|10|100"); // max. zones | |||
zdialog_add_widget(zd,"button","apply","hbz","Apply","space=3"); | zdialog_add_widget(zd,"button","apply","hbz","Apply","space=3"); | |||
zdialog_add_widget(zd,"hbox","hbb","dialog"); | zdialog_add_widget(zd,"hbox","hbb","dialog"); | |||
zdialog_add_widget(zd,"label","labb","hbb","blend","space=5"); | zdialog_add_widget(zd,"label","labb","hbb","image blend","space=5"); | |||
zdialog_add_widget(zd,"hscale2","blend","hbb","0|1.0|0.01|1.0","expand"); | zdialog_add_widget(zd,"hscale2","image blend","hbb","0|1.0|0.01|0.0","expand" | |||
); | ||||
zdialog_add_widget(zd,"hbox","hbrd","dialog"); | zdialog_add_widget(zd,"hbox","hbrd","dialog"); | |||
zdialog_add_widget(zd,"label","labrd","hbrd","reduce dark","space=5"); | zdialog_add_widget(zd,"label","labrd","hbrd","reduce dark","space=5"); | |||
zdialog_add_widget(zd,"hscale2","reduce dark","hbrd","0|1.0|0.01|0.0","expand "); | zdialog_add_widget(zd,"hscale2","reduce dark","hbrd","0|1.0|0.01|0.0","expand "); | |||
zdialog_add_widget(zd,"hbox","hbrl","dialog"); | zdialog_add_widget(zd,"hbox","hbrl","dialog"); | |||
zdialog_add_widget(zd,"label","labrd","hbrl","reduce bright","space=5"); | zdialog_add_widget(zd,"label","labrd","hbrl","reduce bright","space=5"); | |||
zdialog_add_widget(zd,"hscale2","reduce bright","hbrl","0|1.0|0.01|0.0","expa nd"); | zdialog_add_widget(zd,"hscale2","reduce bright","hbrl","0|1.0|0.01|0.0","expa nd"); | |||
zdialog_run(zd,lretinex_dialog_event,"save"); // run dialog - parallel | zdialog_run(zd,lretinex_dialog_event,"save"); // run dialog - parallel | |||
zdialog_send_event(zd,"reset"); | zdialog_send_event(zd,"reset"); | |||
zdialog_send_event(zd,"apply"); | ||||
return; | return; | |||
} | } | |||
// dialog event and completion function | // dialog event and completion function | |||
int lretinex_dialog_event(zdialog *zd, cchar *event) | int lretinex_dialog_event(zdialog *zd, cchar *event) | |||
{ | { | |||
using namespace lretinex_names; | using namespace lretinex_names; | |||
int lretinex_zonesetup(zdialog *zd); | int lretinex_zonesetup(zdialog *zd); | |||
if (strmatch(event,"escape")) zd->zstat = -2; // escape key | if (strmatch(event,"escape")) zd->zstat = -2; // escape key | |||
if (strmatch(event,"done")) zd->zstat = 2; // from edit_setup() or f_save() | if (strmatch(event,"done")) zd->zstat = 2; // from edit_setup() or f_save() | |||
if (strmatch(event,"cancel")) zd->zstat = 3; // from f_open() | if (strmatch(event,"cancel")) zd->zstat = 3; // from f_open() | |||
if (strmatch(event,"reset")) zd->zstat = 1; // initz. | if (strmatch(event,"reset")) zd->zstat = 1; // initz. | |||
if (zd->zstat) | if (zd->zstat) | |||
{ | { | |||
if (zd->zstat == 1) { // reset | if (zd->zstat == 1) { // reset | |||
zd->zstat = 0; // keep dialog active | zd->zstat = 0; // keep dialog active | |||
blend = 1.0; | imageblend = 0.0; | |||
reducedark = 0.0; | reducedark = 0.0; | |||
reducebright = 0.0; | reducebright = 0.0; | |||
zdialog_stuff(zd,"image blend",imageblend); | ||||
// 22.35 | ||||
zdialog_stuff(zd,"reduce dark",reducedark); | ||||
zdialog_stuff(zd,"reduce bright",reducebright); | ||||
edit_reset(); | edit_reset(); | |||
PXM_free(E9pxm); | PXM_free(E9pxm); | |||
E9pxm = PXM_copy(E1pxm); | E9pxm = PXM_copy(E1pxm); | |||
return 1; | return 1; | |||
} | } | |||
else if (zd->zstat == 2) { // done | else if (zd->zstat == 2) { // done | |||
edit_addhist("zones:%d blend:%.3f red.D:%.3f red.B:%.3f", | edit_addhist("zones:%d blend:%.3f red.D:%.3f red.B:%.3f", | |||
Nzones,blend,reducedark,reducebright); // edit parms > edit hist | Nzones,imageblend,reducedark,reducebright); // edit parms > edit hist | |||
edit_done(0); // commit edit | edit_done(0); // commit edit | |||
PXM_free(E9pxm); | PXM_free(E9pxm); | |||
if (zones) zfree(zones); | if (zones) zfree(zones); | |||
if (zoneindex) zfree(zoneindex); | if (zoneindex) zfree(zoneindex); | |||
if (zoneweight) zfree(zoneweight); | if (zoneweight) zfree(zoneweight); | |||
zones = 0; | zones = 0; | |||
zoneindex = 0; | zoneindex = 0; | |||
zoneweight = 0; | zoneweight = 0; | |||
return 1; | return 1; | |||
} | } | |||
skipping to change at line 2852 | skipping to change at line 2857 | |||
if (! lretinex_zonesetup(zd)) { // setup zones | if (! lretinex_zonesetup(zd)) { // setup zones | |||
edit_cancel(0); // failed (insufficient memory) | edit_cancel(0); // failed (insufficient memory) | |||
PXM_free(E9pxm); | PXM_free(E9pxm); | |||
return 1; | return 1; | |||
} | } | |||
thread_command = "apply"; | thread_command = "apply"; | |||
thread_signal(); // update image | thread_signal(); // update image | |||
thread_wait(); | thread_wait(); | |||
} | } | |||
if (strmatch(event,"blend")) { | if (strmatch(event,"image blend")) { | |||
// blend param changed | // image blend param changed | |||
zdialog_fetch(zd,"blend",blend); | zdialog_fetch(zd,"image blend",imageblend); | |||
thread_command = "blend"; | thread_command = "image blend"; | |||
thread_signal(); // update image | thread_signal(); // update image | |||
thread_wait(); | thread_wait(); | |||
} | } | |||
if (zstrstr(event,"reduce")) { // reduce param changed | if (zstrstr(event,"reduce")) { // reduce param changed | |||
zdialog_fetch(zd,"reduce dark",reducedark); | zdialog_fetch(zd,"reduce dark",reducedark); | |||
zdialog_fetch(zd,"reduce bright",reducebright); | zdialog_fetch(zd,"reduce bright",reducebright); | |||
thread_command = "blend"; | thread_command = "image blend"; | |||
thread_signal(); | ||||
// update image | ||||
thread_wait(); | ||||
} | ||||
if (zstrstr("blendwidth paint",event)) { | ||||
// area blendwidth change or mouse paint | ||||
thread_command = "image blend"; | ||||
// 22.35 | ||||
thread_signal(); // update image | thread_signal(); // update image | |||
thread_wait(); | thread_wait(); | |||
} | } | |||
return 1; | return 1; | |||
} | } | |||
// setup new zone parameters and allocate memory | // setup new zone parameters and allocate memory | |||
int lretinex_zonesetup(zdialog *zd) | int lretinex_zonesetup(zdialog *zd) | |||
skipping to change at line 2967 | skipping to change at line 2978 | |||
using namespace lretinex_names; | using namespace lretinex_names; | |||
void * lretinex_wthread1(void *arg); | void * lretinex_wthread1(void *arg); | |||
void * lretinex_wthread2(void *arg); | void * lretinex_wthread2(void *arg); | |||
void * lretinex_wthread3(void *arg); | void * lretinex_wthread3(void *arg); | |||
if (strmatch(thread_command,"apply")) // update zones and image | if (strmatch(thread_command,"apply")) // update zones and image | |||
{ | { | |||
do_wthreads(lretinex_wthread1,NWT); // compute zone RGB levels and weights | do_wthreads(lretinex_wthread1,NWT); // compute zone RGB levels and weights | |||
do_wthreads(lretinex_wthread2,NWT); // compute new pixel RGB values | do_wthreads(lretinex_wthread2,NWT); // compute new pixel RGB values | |||
thread_command = "blend"; // auto blend after | thread_command = "image blend"; // auto blend after | |||
} | } | |||
if (strmatch(thread_command,"blend")) | if (strmatch(thread_command,"image blend")) { | |||
get_edit_pixels_init(NWT,0); | ||||
// initz. pixel loop 22.35 | ||||
do_wthreads(lretinex_wthread3,NWT); // blend input and retinex images | do_wthreads(lretinex_wthread3,NWT); // blend input and retinex images | |||
} | ||||
CEF->Fmods++; // image modified | CEF->Fmods++; // image modified | |||
CEF->Fsaved = 0; | CEF->Fsaved = 0; | |||
Fpaint2(); | if (! Fpaintedits) Fpaint2(); | |||
// update window | // update window 22.35 | |||
return 0; | return 0; | |||
} | } | |||
// worker thread to compute zone RGB levels and weights per image pixel | // worker thread to compute zone RGB levels and weights per image pixel | |||
void * lretinex_wthread1(void *arg) | void * lretinex_wthread1(void *arg) | |||
{ | { | |||
using namespace lretinex_names; | using namespace lretinex_names; | |||
int index = *((int *) arg); | int index = *((int *) arg); | |||
skipping to change at line 3160 | skipping to change at line 3174 | |||
// worker thread to blend input image with retinex image | // worker thread to blend input image with retinex image | |||
// and attenuate bright pixels | // and attenuate bright pixels | |||
void * lretinex_wthread3(void *arg) | void * lretinex_wthread3(void *arg) | |||
{ | { | |||
using namespace lretinex_names; | using namespace lretinex_names; | |||
int index = *((int *) arg); | int index = *((int *) arg); | |||
int px, py; | int px, py; | |||
int ii, dist = 0; | int Fend, max$; | |||
float *pix1, *pix2, *pix3; | float *pix1, *pix2, *pix3; | |||
float R1, G1, B1, R2, G2, B2, R3, G3, B3; | float R1, G1, B1, R3, G3, B3, R9, G9, B9; | |||
float F1, F2, Lmax; | float F1, F2, Lmax, blend; | |||
for (py = index; py < E1hh; py += NWT) | while (true) | |||
// loop all image pixels | ||||
for (px = 0; px < E1ww; px++) | ||||
{ | { | |||
if (sa_stat == 3) { | Fend = get_edit_pixels(index,px,py,blend); | |||
// select area active | if (Fend) break; | |||
ii = py * E1ww + px; | if (blend == 0) continue; | |||
dist = sa_pixmap[ii]; | ||||
// distance from edge | ||||
if (! dist) continue; | ||||
// outside area | ||||
} | ||||
pix1 = PXMpix(E1pxm,px,py); // input image pixel | pix1 = PXMpix(E1pxm,px,py); // input image pixel | |||
pix2 = PXMpix(E9pxm,px,py); // retinex image pixel | pix2 = PXMpix(E9pxm,px,py); // retinex image pixel | |||
pix3 = PXMpix(E3pxm,px,py); // output image pixel | pix3 = PXMpix(E3pxm,px,py); // output image pixel | |||
R1 = pix1[0]; // input color - original image | R1 = pix1[0]; // input RGB | |||
G1 = pix1[1]; | G1 = pix1[1]; | |||
B1 = pix1[2]; | B1 = pix1[2]; | |||
R2 = pix2[0]; | R3 = pix3[0]; | |||
// input color - retinex image | // current output RGB | |||
G2 = pix2[1]; | G3 = pix3[1]; | |||
B2 = pix2[2]; | B3 = pix3[2]; | |||
if (sa_stat == 3 && dist < sa_blendwidth) { | R9 = pix2[0]; | |||
// select area is active, | // retinex RGB | |||
F1 = sa_blendfunc(dist); | G9 = pix2[1]; | |||
// blend changes over sa_blendwidth | B9 = pix2[2]; | |||
F2 = 1.0 - F1; | ||||
R2 = F1 * R2 + F2 * R1; | ||||
G2 = F1 * G2 + F2 * G1; | ||||
B2 = F1 * B2 + F2 * B1; | ||||
} | ||||
Lmax = R1; // max. RGB input | Lmax = R1; // max. RGB input | |||
if (G1 > Lmax) Lmax = G1; | if (G1 > Lmax) Lmax = G1; | |||
if (B1 > Lmax) Lmax = B1; | if (B1 > Lmax) Lmax = B1; | |||
Lmax = Lmax / 255.0; // scale 0-1 | Lmax = Lmax / 255.0; // scale 0-1 | |||
F1 = blend; // 0 ... 1 >> E1 ... E3 | F1 = imageblend; // 0 ... 1 >> E1 ... E3 | |||
F2 = reducedark; | F2 = reducedark; | |||
F1 = F1 * (1.0 - F2 * (1.0 - Lmax)); // reduce F1 for high F2 * (1 - Lmax) | F1 = F1 * (1.0 - F2 * (1.0 - Lmax)); // reduce F1 for high F2 * (1 - Lmax) | |||
F2 = reducebright; // 0 ... 1 | F2 = reducebright; // 0 ... 1 | |||
F1 = F1 * (1.0 - F2 * Lmax); // reduce F1 for high F2 * Lmax | F1 = F1 * (1.0 - F2 * Lmax); // reduce F1 for high F2 * Lmax | |||
R3 = F1 * R2 + (1.0 - F1) * R1; | R9 = F1 * R9 + (1.0 - F1) * R1; | |||
// output RGB = blended inputs | // output RGB = blended inputs | |||
G3 = F1 * G2 + (1.0 - F1) * G1; | G9 = F1 * G9 + (1.0 - F1) * G1; | |||
B3 = F1 * B2 + (1.0 - F1) * B1; | B9 = F1 * B9 + (1.0 - F1) * B1; | |||
RGBFIX(R9,G9,B9) | ||||
if (Fpaintedits) | ||||
// gradual edit within mouse circle 22.35 | ||||
{ | ||||
if (blend > 0) | ||||
{ | ||||
// increase edit | ||||
R3 = blend * R9 + (1-blend) * R3; | ||||
G3 = blend * G9 + (1-blend) * G3; | ||||
B3 = blend * B9 + (1-blend) * B3; | ||||
} | ||||
else if (blend < 0) | ||||
{ | ||||
// decrease edit | ||||
R3 = -blend * R1 + (1+blend) * R3; | ||||
G3 = -blend * G1 + (1+blend) * G3; | ||||
B3 = -blend * B1 + (1+blend) * B3; | ||||
} | ||||
} | ||||
else | ||||
// full edit for image or area | ||||
{ | ||||
R3 = blend * R9 + (1-blend) * R1; | ||||
G3 = blend * G9 + (1-blend) * G1; | ||||
B3 = blend * B9 + (1-blend) * B1; | ||||
} | ||||
pix3[0] = R3; // output RGB values | pix3[0] = R3; // output RGB values | |||
pix3[1] = G3; | pix3[1] = G3; | |||
pix3[2] = B3; | pix3[2] = B3; | |||
} | } | |||
return 0; | return 0; | |||
} | } | |||
/******************************************************************************* */ | /******************************************************************************* */ | |||
End of changes. 25 change blocks. | ||||
50 lines changed or deleted | 88 lines changed or added |