"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "f.effects.cc" between
fotoxx-22.41.tar.gz and fotoxx-22.50.tar.gz

About: fotoxx is a program for photo editing and collection management.

f.effects.cc  (fotoxx-22.41):f.effects.cc  (fotoxx-22.50)
skipping to change at line 542 skipping to change at line 542
editfunc EFcartoon; editfunc EFcartoon;
int line_threshold = 100; int line_threshold = 100;
int line_width = 3; int line_width = 3;
int blur_radius = 4; int blur_radius = 4;
int kuwahara_depth = 2; int kuwahara_depth = 2;
int priorKD, priorBR; int priorKD, priorBR;
int Eww, Ehh; int Eww, Ehh;
float *pixcon; float *pixcon;
float Fthreshold; float Fthreshold;
float Wrad[41][41]; // radius <= 20 float Wrad[41][41]; // radius <= 20
int dialog_event(zdialog* zd, cchar *event);
void * thread(void *);
void blur();
void * blur_wthread(void *);
void kuwahara();
void * kuwahara_wthread(void *);
void contrast_map();
void drawlines();
void * drawlines_wthread(void *);
} }
// menu function // menu function
void m_cartoon(GtkWidget *, cchar *menu) void m_cartoon(GtkWidget *, cchar *menu)
{ {
using namespace cartoon; using namespace cartoon;
int cartoon_dialog_event(zdialog *zd, cchar *event);
void * cartoon_thread(void *);
F1_help_topic = "cartoon"; F1_help_topic = "cartoon";
Plog(1,"m_cartoon \n"); Plog(1,"m_cartoon \n");
EFcartoon.menuname = "Cartoon"; EFcartoon.menuname = "Cartoon";
EFcartoon.menufunc = m_cartoon; EFcartoon.menufunc = m_cartoon;
EFcartoon.Farea = 2; // select area usable EFcartoon.Farea = 2; // select area usable
EFcartoon.Fscript = 1; // scripting supported EFcartoon.Fscript = 1; // scripting supported
EFcartoon.threadfunc = thread; // thread function EFcartoon.threadfunc = cartoon_thread; // thread function
if (! edit_setup(EFcartoon)) return; // setup edit if (! edit_setup(EFcartoon)) return; // setup edit
Eww = E1pxm->ww; Eww = E1pxm->ww;
Ehh = E1pxm->hh; Ehh = E1pxm->hh;
pixcon = (float *) zmalloc(Eww * Ehh * sizeof(float),"cartoon"); pixcon = (float *) zmalloc(Eww * Ehh * sizeof(float),"cartoon");
E8pxm = PXM_copy(E1pxm); // blurred image E8pxm = PXM_copy(E1pxm); // blurred image
E9pxm = PXM_copy(E1pxm); // kuwahara image E9pxm = PXM_copy(E1pxm); // kuwahara image
skipping to change at line 611 skipping to change at line 604
zdialog_add_widget(zd,"label","lab1","vb1","Line Threshold"); zdialog_add_widget(zd,"label","lab1","vb1","Line Threshold");
zdialog_add_widget(zd,"label","lab1","vb1","Line Width"); zdialog_add_widget(zd,"label","lab1","vb1","Line Width");
zdialog_add_widget(zd,"label","lab1","vb1","Kuwahara Depth"); zdialog_add_widget(zd,"label","lab1","vb1","Kuwahara Depth");
zdialog_add_widget(zd,"zspin","line_threshold","vb2","0|1000|1|1000"); zdialog_add_widget(zd,"zspin","line_threshold","vb2","0|1000|1|1000");
zdialog_add_widget(zd,"zspin","line_width","vb2","0|10|1|1"); zdialog_add_widget(zd,"zspin","line_width","vb2","0|10|1|1");
zdialog_add_widget(zd,"zspin","kuwahara_depth","vb2","0|10|1|1"); zdialog_add_widget(zd,"zspin","kuwahara_depth","vb2","0|10|1|1");
zdialog_resize(zd,200,0); zdialog_resize(zd,200,0);
zdialog_restore_inputs(zd); zdialog_restore_inputs(zd);
zdialog_run(zd,dialog_event,"save"); // run dialog, parallel zdialog_run(zd,cartoon_dialog_event,"save"); // run dialog, parallel
zdialog_fetch(zd,"line_threshold",line_threshold); zdialog_fetch(zd,"line_threshold",line_threshold);
zdialog_fetch(zd,"line_width",line_width); zdialog_fetch(zd,"line_width",line_width);
zdialog_fetch(zd,"kuwahara_depth",kuwahara_depth); zdialog_fetch(zd,"kuwahara_depth",kuwahara_depth);
blur_radius = 2 * kuwahara_depth; // 22.30 blur_radius = 2 * kuwahara_depth; // 22.30
priorKD = priorBR = -1; // initial edit priorKD = priorBR = -1; // initial edit
return; return;
} }
// dialog event and completion callback function // dialog event and completion callback function
int cartoon::dialog_event(zdialog *zd, cchar *event) // dialog event function int cartoon_dialog_event(zdialog *zd, cchar *event) // dialog event function
{ {
using namespace cartoon; using namespace cartoon;
if (strmatch(event,"escape")) zd->zstat = -2; // escape key if (strmatch(event,"escape")) zd->zstat = -2; // escape key
if (strmatch(event,"focus")) return 1; if (strmatch(event,"focus")) return 1;
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,"apply")) zd->zstat = 1; // from script if (strmatch(event,"apply")) zd->zstat = 1; // from script
zdialog_fetch(zd,"line_threshold",line_threshold); // get outline threshold 0-1000 zdialog_fetch(zd,"line_threshold",line_threshold); // get outline threshold 0-1000
skipping to change at line 667 skipping to change at line 660
} }
else edit_cancel(0); // discard edit else edit_cancel(0); // discard edit
zfree(pixcon); zfree(pixcon);
} }
return 1; return 1;
} }
// thread function to update image // thread function to update image
void * cartoon::thread(void *) void * cartoon_thread(void *)
{ {
using namespace cartoon; using namespace cartoon;
void cartoon_blur();
void cartoon_kuwahara();
void cartoon_contrast_map();
void cartoon_drawlines();
int Fblur, Fkuwa, Fcon; int Fblur, Fkuwa, Fcon;
Fblur = Fkuwa = Fcon = 0; Fblur = Fkuwa = Fcon = 0;
if (blur_radius != priorBR) Fblur = Fkuwa = Fcon = 1; if (blur_radius != priorBR) Fblur = Fkuwa = Fcon = 1;
if (kuwahara_depth != priorKD) Fkuwa = Fcon = 1; if (kuwahara_depth != priorKD) Fkuwa = Fcon = 1;
priorBR = blur_radius; // capture now, can change during process priorBR = blur_radius; // capture now, can change during process
priorKD = kuwahara_depth; priorKD = kuwahara_depth;
progress_reset((Fblur*Fkuwa*Fcon+1)*Eww*Ehh); // 22.30 progress_reset((Fblur*Fkuwa*Fcon+1)*Eww*Ehh); // 22.30
if (Fblur) blur(); if (Fblur) cartoon_blur();
// E1 + blur >> E8 // E1 + blur >> E8
if (Fkuwa) kuwahara(); if (Fkuwa) cartoon_kuwahara();
// E8 + kuwahara >> E9 // E8 + kuwahara >> E9
if (Fcon) contrast_map(); if (Fcon) cartoon_contrast_map();
// compute E9 pixel contrast // compute E9 pixel contrast
drawlines(); // draw lines where contrast > threshold cartoon_drawlines(); // draw lines where contrast > threshold
progress_reset(0); progress_reset(0);
CEF->Fmods++; CEF->Fmods++;
CEF->Fsaved = 0; CEF->Fsaved = 0;
Fpaint2(); // update window Fpaint2(); // update window
return 0; return 0;
} }
// Blur the image using blur_radius. E1 + blur >> E8 // Blur the image using blur_radius. E1 + blur >> E8
void cartoon::blur() void cartoon_blur()
{ {
using namespace cartoon; using namespace cartoon;
void * cartoon_blur_wthread(void *arg);
int rad, px, py, qx, qy; int rad, px, py, qx, qy;
float R, W; float R, W;
PXM_free(E8pxm); PXM_free(E8pxm);
E8pxm = PXM_copy(E1pxm); E8pxm = PXM_copy(E1pxm);
if (blur_radius == 0) return; if (blur_radius == 0) return;
rad = blur_radius; rad = blur_radius;
skipping to change at line 726 skipping to change at line 726
{ {
R = sqrtf(qx * qx + qy * qy); R = sqrtf(qx * qx + qy * qy);
if (R > rad) W = 0.0; if (R > rad) W = 0.0;
else if (R == 0) W = 1.0; else if (R == 0) W = 1.0;
else W = 1.0 / R; else W = 1.0 / R;
py = qy + rad; py = qy + rad;
px = qx + rad; px = qx + rad;
Wrad[py][px] = W; Wrad[py][px] = W;
} }
do_wthreads(blur_wthread,NWT); // worker threads do_wthreads(cartoon_blur_wthread,NWT); // worker threads
return; return;
} }
void * cartoon::blur_wthread(void *arg) // worker thread function void * cartoon_blur_wthread(void *arg) // worker thread function
{ {
using namespace cartoon; using namespace cartoon;
int index = *((int *) arg); int index = *((int *) arg);
int rad = blur_radius; int rad = blur_radius;
int ii, dist = 0, px, py, qx, qy; int ii, dist = 0, px, py, qx, qy;
float W, Wsum, f1, f2; float W, Wsum, f1, f2;
float R, G, B, *pix1, *pixq, *pix8; float R, G, B, *pix1, *pixq, *pix8;
for (py = index + rad; py < Ehh-rad; py += NWT) // loop all image pixels for (py = index + rad; py < Ehh-rad; py += NWT) // loop all image pixels
for (px = rad; px < Eww-rad; px++) for (px = rad; px < Eww-rad; px++)
{ {
if (Fkillfunc) break; if (Fkillfunc) break;
if (sa_stat == 3) { // select area active if (sa_stat == 3) { // select area active
ii = py * Eww + px; ii = py * Eww + px;
dist = sa_pixmap[ii]; // distance from edge dist = sa_pixmap[ii]; // distance from edge
if (! dist) continue; // pixel is outside area if (! dist) continue; // pixel is outside area
} }
skipping to change at line 793 skipping to change at line 793
pix8[2] = B; pix8[2] = B;
progress_add(index,1); // 22.30 progress_add(index,1); // 22.30
} }
return 0; return 0;
} }
// Perform a kuwahara sharpen of the image. E8 + kuwahara >> E9. // Perform a kuwahara sharpen of the image. E8 + kuwahara >> E9.
void cartoon::kuwahara() void cartoon_kuwahara()
{ {
using namespace cartoon; using namespace cartoon;
void * cartoon_kuwahara_wthread(void *arg);
PXM_free(E9pxm); PXM_free(E9pxm);
E9pxm = PXM_copy(E8pxm); E9pxm = PXM_copy(E8pxm);
if (kuwahara_depth == 0) return; if (kuwahara_depth == 0) return;
do_wthreads(kuwahara_wthread,NWT); // worker threads do_wthreads(cartoon_kuwahara_wthread,NWT); // worker threads
return; return;
} }
void * cartoon::kuwahara_wthread(void *arg) // worker thread function void * cartoon_kuwahara_wthread(void *arg) // worker thread function
{ {
using namespace cartoon; using namespace cartoon;
int index = *((int *) arg); int index = *((int *) arg);
int px, py, qx, qy, rx, ry; int px, py, qx, qy, rx, ry;
int ii, rad, N, dist = 0; int ii, rad, N, dist = 0;
float *pix1, *pix8, *pix9; float *pix1, *pix8, *pix9;
float red, green, blue, red2, green2, blue2; float red, green, blue, red2, green2, blue2;
float vmin, vall, vred, vgreen, vblue; float vmin, vall, vred, vgreen, vblue;
float red9, green9, blue9; float red9, green9, blue9;
skipping to change at line 894 skipping to change at line 896
pix9[2] = blue9; pix9[2] = blue9;
progress_add(index,1); // 22.30 progress_add(index,1); // 22.30
} }
return 0; return 0;
} }
// Map contrast for E9 image pixels and set threshold scale. // Map contrast for E9 image pixels and set threshold scale.
void cartoon::contrast_map() void cartoon_contrast_map()
{ {
using namespace cartoon; using namespace cartoon;
int ii, px, py, qx, qy; int ii, px, py, qx, qy;
double sumcon, pix1con, maxcon; double sumcon, pix1con, maxcon;
float *pixx, *pixq; float *pixx, *pixq;
maxcon = 0; maxcon = 0;
for (py = 1; py < Ehh-1; py++) // make image pixel contrast map for (py = 1; py < Ehh-1; py++) // make image pixel contrast map
skipping to change at line 935 skipping to change at line 937
progress_add(0,1); progress_add(0,1);
} }
Fthreshold = maxcon; // threshold scale factor Fthreshold = maxcon; // threshold scale factor
return; return;
} }
// Draw lines on the image where edges are detected. // Draw lines on the image where edges are detected.
// E9 >> E3, add lines to E3, use E1 for area blend. // E9 >> E3, add lines to E3, use E1 for area blend.
void cartoon::drawlines() void cartoon_drawlines()
{ {
void * cartoon_drawlines_wthread(void *arg);
PXM_free(E3pxm); PXM_free(E3pxm);
E3pxm = PXM_copy(E9pxm); E3pxm = PXM_copy(E9pxm);
do_wthreads(drawlines_wthread,NWT); // worker threads do_wthreads(cartoon_drawlines_wthread,NWT); // worker threads
} }
void * cartoon::drawlines_wthread(void *arg) // worker thread function void * cartoon_drawlines_wthread(void *arg) // worker thread function
{ {
using namespace cartoon; using namespace cartoon;
int index = *((int *) arg); int index = *((int *) arg);
int px, py, qx, qy, ii, dist = 0; int px, py, qx, qy, ii, dist = 0;
float Fthresh, paint, f1, f2; float Fthresh, paint, f1, f2;
float *pix1, *pix3, *pix3q; float *pix1, *pix3, *pix3q;
Fthresh = 0.001 * line_threshold * Fthreshold; // 0 .. 1000 >> 0 .. Fthreshold Fthresh = 0.001 * line_threshold * Fthreshold; // 0 .. 1000 >> 0 .. Fthreshold
skipping to change at line 1301 skipping to change at line 1305
void * emboss_thread(void *); void * emboss_thread(void *);
F1_help_topic = "emboss"; F1_help_topic = "emboss";
Plog(1,"m_emboss \n"); Plog(1,"m_emboss \n");
EFemboss.menuname = "Emboss"; EFemboss.menuname = "Emboss";
EFemboss.menufunc = m_emboss; EFemboss.menufunc = m_emboss;
EFemboss.Fscript = 1; // scripting supported EFemboss.Fscript = 1; // scripting supported
EFemboss.Farea = 2; // select area usable EFemboss.Farea = 2; // select area usable
EFemboss.Fpaintedits = 1; // can use paint edits 22.50
EFemboss.threadfunc = emboss_thread; // thread function EFemboss.threadfunc = emboss_thread; // thread function
if (! edit_setup(EFemboss)) return; // setup edit if (! edit_setup(EFemboss)) return; // setup edit
/*** /***
__________________________ __________________________
| Emboss | | Emboss |
| | | |
| Radius [__] Depth [__] | // remove B/W option 22.30 | Radius [__] Depth [__] | // remove B/W option 22.30
| | | |
skipping to change at line 1358 skipping to change at line 1363
} }
else if (zd->zstat == 2) { // [OK] commit edit else if (zd->zstat == 2) { // [OK] commit edit
edit_addhist("radius:%d depth:%d",radius,depth); // edit parms > edit hist edit_addhist("radius:%d depth:%d",radius,depth); // edit parms > edit hist
edit_done(0); edit_done(0);
} }
else edit_cancel(0); // discard edit else edit_cancel(0); // discard edit
return 1; return 1;
} }
if (zstrstr("blendwidth paint",event)) {
// area edge blend or mouse paint 22.50
zdialog_fetch(zd,"radius",radius);
// get user inputs
zdialog_fetch(zd,"depth",depth);
thread_signal();
}
return 1; return 1;
} }
// thread function - use multiple working threads // thread function - use multiple working threads
void * emboss_thread(void *) void * emboss_thread(void *)
{ {
using namespace emboss_names; using namespace emboss_names;
void * emboss_wthread(void *arg); void * emboss_wthread(void *arg);
skipping to change at line 1385 skipping to change at line 1396
for (dy = -rad; dy <= rad; dy++) // build kernel with radius and depth for (dy = -rad; dy <= rad; dy++) // build kernel with radius and depth
for (dx = -rad; dx <= rad; dx++) for (dx = -rad; dx <= rad; dx++)
{ {
kern = coeff * (dx + dy); kern = coeff * (dx + dy);
kernel[dx+rad][dy+rad] = kern; kernel[dx+rad][dy+rad] = kern;
} }
kernel[rad][rad] = 1; // kernel center cell = 1 kernel[rad][rad] = 1; // kernel center cell = 1
get_edit_pixels_init(NWT,0);
// initz. pixel loop 22.50
do_wthreads(emboss_wthread,NWT); // worker threads do_wthreads(emboss_wthread,NWT); // worker threads
CEF->Fmods++; CEF->Fmods++;
CEF->Fsaved = 0; CEF->Fsaved = 0;
Fpaint2(); // update window if (! Fpaintedits) Fpaint2(); // update window
return 0; return 0;
} }
void * emboss_wthread(void *arg) // worker thread function void * emboss_wthread(void *arg) // worker thread function
{ {
using namespace emboss_names; using namespace emboss_names;
void emboss_1pix(int px, int py);
int index = *((int *) (arg)); int index = *((int *) (arg));
int px, py; int px, py, Fend;
int dx, dy, rad;
int nc = E1pxm->nc;
float R1, G1, B1, R3, G3, B3, R9, G9, B9;
float bright1, bright3;
float *pix1, *pix3, *pixN;
float sumpix, kern;
float blend, max$;
for (py = index; py < E3pxm->hh; py += NWT) rad = radius;
// process all pixels
for (px = 0; px < E3pxm->ww; px++)
emboss_1pix(px,py);
return 0; while (true)
} {
Fend = get_edit_pixels(index,px,py,blend);
// 22.50
if (Fend) break;
if (blend == 0) continue;
void emboss_1pix(int px, int py) if (px < rad || py < rad) continue;
// process one pixel 22.30 if (px > E3pxm->ww-rad-1 || py > E3pxm->hh-rad-1) continue;
{
using namespace emboss_names;
int ii, dist = 0; pix1 = PXMpix(E1pxm,px,py);
float bright1, bright3; // input pixel
int dx, dy, rad; pix3 = PXMpix(E3pxm,px,py);
float *pix1, *pix3, *pixN; // output pixel
float sumpix, kern, dold, dnew;
float max$;
int nc = E1pxm->nc;
if (sa_stat == 3) { R1 = pix1[0];
// select area active G1 = pix1[1];
ii = py * E3pxm->ww + px; B1 = pix1[2];
dist = sa_pixmap[ii];
// distance from edge
if (! dist) return;
// outside pixel
}
rad = radius; R3 = pix3[0];
G3 = pix3[1];
B3 = pix3[2];
sumpix = 0;
if (px < rad || py < rad) return; for (dy = -rad; dy <= rad; dy++)
if (px > E3pxm->ww-rad-1 || py > E3pxm->hh-rad-1) return; // loop surrounding block of pixels
for (dx = -rad; dx <= rad; dx++)
{
pixN = pix1 + (dy * E1pxm->ww + dx) * nc;
kern = kernel[dx+rad][dy+rad];
sumpix += kern * (pixN[0] + pixN[1] + pixN[2]);
// kern sums to 1.0
}
pix1 = PXMpix(E1pxm,px,py); bright1 = pix1[0] + pix1[1] + pix1[2] + 1;
// input pixel bright3 = (sumpix + 1) / bright1;
pix3 = PXMpix(E3pxm,px,py); // ratio of brightness change
// output pixel
sumpix = 0; R9 = bright3 * R1;
G9 = bright3 * G1;
B9 = bright3 * B1;
for (dy = -rad; dy <= rad; dy++) RGBFIX(R9,G9,B9);
// loop surrounding block of pixels
for (dx = -rad; dx <= rad; dx++)
{
pixN = pix1 + (dy * E1pxm->ww + dx) * nc;
kern = kernel[dx+rad][dy+rad];
sumpix += kern * (pixN[0] + pixN[1] + pixN[2]);
// kern sums to 1.0
}
bright1 = pix1[0] + pix1[1] + pix1[2] + 1; if (Fpaintedits)
bright3 = (sumpix + 1) / bright1; // mouse paint edit
// ratio of brightness change {
if (blend > 0)
{
// increase edit
R3 = blend * R9 + (1-blend) * R3;
G3 = blend * G9 + (1-blend) * G3;
B3 = blend * B9 + (1-blend) * B3;
}
if (sa_stat == 3 && dist < sa_blendwidth) { else if (blend < 0)
// select area is active, {
dnew = sa_blendfunc(dist); // decrease edit
// blend changes over sa_blendwidth R3 = -blend * R1 + (1+blend) * R3;
dold = 1.0 - dnew; G3 = -blend * G1 + (1+blend) * G3;
bright3 = dnew * bright3 + dold * 1.0; B3 = -blend * B1 + (1+blend) * B3;
} }
}
pix3[0] = bright3 * pix1[0]; else
pix3[1] = bright3 * pix1[1]; // full image edit
pix3[2] = bright3 * pix1[2]; {
R3 = blend * R9 + (1-blend) * R1;
G3 = blend * G9 + (1-blend) * G1;
B3 = blend * B9 + (1-blend) * B1;
}
RGBFIX(pix3[0],pix3[1],pix3[2]); pix3[0] = R3;
pix3[1] = G3;
pix3[2] = B3;
}
return; return 0;
} }
/******************************************************************************* */ /******************************************************************************* */
// convert image to simulate square tiles // convert image to simulate square tiles
namespace tiles_names namespace tiles_names
{ {
editfunc EFtiles; editfunc EFtiles;
int size, gap, D3; int size, gap, D3;
skipping to change at line 2342 skipping to change at line 2372
zdialog *zd; zdialog *zd;
F1_help_topic = "texture"; F1_help_topic = "texture";
Plog(1,"m_texture \n"); Plog(1,"m_texture \n");
EFtexture.menuname = "Texture"; EFtexture.menuname = "Texture";
EFtexture.menufunc = m_texture; EFtexture.menufunc = m_texture;
EFtexture.Farea = 2; // select area OK EFtexture.Farea = 2; // select area OK
EFtexture.Fpaintedits = 1; // can use paint edits 22.50
EFtexture.Fscript = 1; // scripting supported EFtexture.Fscript = 1; // scripting supported
EFtexture.threadfunc = texture_thread; // thread function EFtexture.threadfunc = texture_thread; // thread function
if (! edit_setup(EFtexture)) return; // setup edit if (! edit_setup(EFtexture)) return; // setup edit
e3ww = E3pxm->ww; // image dimensions e3ww = E3pxm->ww; // image dimensions
e3hh = E3pxm->hh; e3hh = E3pxm->hh;
/*** /***
___________________________________ ___________________________________
skipping to change at line 2408 skipping to change at line 2439
return 1; return 1;
} }
if (zd->zstat == 2) { // commit edit if (zd->zstat == 2) { // commit edit
edit_addhist("radius:%d power:%d",radius,power); // edit parms > edit hist edit_addhist("radius:%d power:%d",radius,power); // edit parms > edit hist
edit_done(0); edit_done(0);
} }
else edit_cancel(0); // discard edit else edit_cancel(0); // discard edit
return 1; return 1;
} }
if (zstrstr("blendwidth paint",event)) {
// edge blend or mouse paint 22.50
zdialog_fetch(zd,"radius",radius);
zdialog_fetch(zd,"power",power);
thread_signal();
}
return 1; return 1;
} }
// thread function - update image // thread function - update image
void * texture_thread(void *) void * texture_thread(void *)
{ {
using namespace texturenames; using namespace texturenames;
void * texture_wthread(void *arg); // worker thread void * texture_wthread(void *arg); // worker thread
if (sa_stat == 3) progress_reset(sa_Npixel); // initz. progress counter if (sa_stat == 3) progress_reset(sa_Npixel); // initz. progress counter
else progress_reset(e3ww * e3hh); else progress_reset(e3ww * e3hh);
get_edit_pixels_init(NWT,0);
// initz. pixel loop 22.50
do_wthreads(texture_wthread,NWT); // worker threads do_wthreads(texture_wthread,NWT); // worker threads
progress_reset(0); progress_reset(0);
CEF->Fmods = 1; // image modified CEF->Fmods = 1; // image modified
CEF->Fsaved = 0; // not saved CEF->Fsaved = 0; // not saved
Fpaint2(); // update window if (! Fpaintedits) Fpaint2(); // update window
return 0; return 0;
} }
void * texture_wthread(void *arg) // worker thread function void * texture_wthread(void *arg) // worker thread function
{ {
using namespace texturenames; using namespace texturenames;
int index = *((int *) (arg)); int index = *((int *) (arg));
int px, py, qx, qy, npix, dist = 0; int px, py, qx, qy, npix;
int ii, rank1, rank2; int Fend, rank1, rank2;
float fred, fgreen, fblue; float R1, G1, B1, R3, G3, B3, R9, G9, B9;
float *pix1, *pix3, *qpix; float *pix1, *pix3, *qpix;
float pow, ff, f1, f3; float pow, ff;
float pbright, qbright; float pbright, qbright;
float max$; float blend, max$;
pow = 0.001 * powf(power,1.5); // 0.001 ... 1.0 pow = 0.001 * powf(power,1.5); // 0.001 ... 1.0
for (py = index+radius; py < e3hh-radius; py += NWT) while (true)
// loop all image pixels
for (px = radius; px < e3ww-radius; px++)
{ {
if (sa_stat == 3) { Fend = get_edit_pixels(index,px,py,blend);
// select area active // 22.50
ii = py * e3ww + px; if (Fend) break;
dist = sa_pixmap[ii]; if (blend == 0) continue;
// distance from edge
if (! dist) continue;
// pixel outside area
}
pix1 = PXMpix(E1pxm,px,py); // input pixel pix1 = PXMpix(E1pxm,px,py); // input pixel
pix3 = PXMpix(E3pxm,px,py);
// output pixel
R1 = pix1[0];
G1 = pix1[1];
B1 = pix1[2];
R3 = pix3[0];
G3 = pix3[1];
B3 = pix3[2];
pbright = PIXBRIGHT(pix1); // input pixel brightness pbright = PIXBRIGHT(pix1); // input pixel brightness
npix = 0; npix = 0;
rank1 = rank2 = 0; rank1 = rank2 = 0;
for (qy = py-radius; qy <= py+radius; qy++) // loop pixels in neighborhood for (qy = py-radius; qy <= py+radius; qy++) // loop pixels in neighborhood
for (qx = px-radius; qx <= px+radius; qx++) for (qx = px-radius; qx <= px+radius; qx++)
{ {
qpix = PXMpix(E1pxm,qx,qy); // neighbor pixel qpix = PXMpix(E1pxm,qx,qy); // neighbor pixel
qbright = PIXBRIGHT(qpix); // compare neighbor brightness qbright = PIXBRIGHT(qpix); // compare neighbor brightness
skipping to change at line 2481 skipping to change at line 2527
} }
if (! pbright) ff = 1; if (! pbright) ff = 1;
else { else {
qbright = 255.9 * (rank1 + 0.5 * rank2) / npix; // assigned brightness = 256*rank/npix qbright = 255.9 * (rank1 + 0.5 * rank2) / npix; // assigned brightness = 256*rank/npix
ff = qbright / pbright; // new/old brightness ratio ff = qbright / pbright; // new/old brightness ratio
} }
ff = 1.0 - pow * (1.0 - ff); // 1 ... ff for pow = 0 ... 1 ff = 1.0 - pow * (1.0 - ff); // 1 ... ff for pow = 0 ... 1
fred = ff * pix1[0]; R9 = ff * R1;
// RGB for new brightness level // RGB for new brightness level
fgreen = ff * pix1[1]; G9 = ff * G1;
fblue = ff * pix1[2]; B9 = ff * B1;
RGBFIX(fred,fgreen,fblue) RGBFIX(R9,G9,B9)
if (sa_stat == 3 && dist < sa_blendwidth) { if (Fpaintedits)
// select area is active, // mouse paint edit
f3 = sa_blendfunc(dist); {
// blend changes over sa_blendwidth if (blend > 0)
f1 = 1.0 - f3; {
fred = f3 * fred + f1 * pix1[0]; // increase edit
fgreen = f3 * fgreen + f1 * pix1[1]; R3 = blend * R9 + (1-blend) * R3;
fblue = f3 * fblue + f1 * pix1[2]; 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;
}
} }
pix3 = PXMpix(E3pxm,px,py); else
// output pixel // full image edit
pix3[0] = fred; {
pix3[1] = fgreen; R3 = blend * R9 + (1-blend) * R1;
pix3[2] = fblue; G3 = blend * G9 + (1-blend) * G1;
B3 = blend * B9 + (1-blend) * B1;
}
pix3[0] = R3;
pix3[1] = G3;
pix3[2] = B3;
progress_add(index,1); progress_add(index,1);
} }
return 0; // exit thread return 0; // exit thread
} }
/******************************************************************************* */ /******************************************************************************* */
// pattern menu function // pattern menu function
skipping to change at line 4053 skipping to change at line 4114
if (strmatch(event,"LOAD")) // load a palette file if (strmatch(event,"LOAD")) // load a palette file
{ {
pp = zgetfile("palette file",MWIN,"file",palettes_folder,0); pp = zgetfile("palette file",MWIN,"file",palettes_folder,0);
if (pp) { if (pp) {
zdialog_show(zd,0); zdialog_show(zd,0);
poptext_window(MWIN,"mapping palette ...",200,200,0,1000); poptext_window(MWIN,"mapping palette ...",200,200,0,1000);
zmainsleep(0.1); zmainsleep(0.1);
Ncolors = load_palette_map(pp); // CPU loops for a long time Ncolors = load_palette_map(pp); // CPU loops for a long time
poptext_window(0,0,0,0,0,0); poptext_window(0,0,0,0,0,0);
if (Ncolors) { if (Ncolors) {
zmessage_post(Mwin,"parent",3,"palette loaded, %d colors",Ncolors); zmessage_post_bold(Mwin,"parent",3,"palette loaded, %d colors",Ncolo rs);
pp = strrchr(pp,'/'); pp = strrchr(pp,'/');
zdialog_stuff(zd,"palname",pp+1); zdialog_stuff(zd,"palname",pp+1);
} }
zdialog_show(zd,1); zdialog_show(zd,1);
} }
} }
return 1; return 1;
} }
skipping to change at line 5348 skipping to change at line 5409
F1_help_topic = "shift colors"; F1_help_topic = "shift colors";
Plog(1,"m_shift_colors \n"); Plog(1,"m_shift_colors \n");
EFshiftcolors.menuname = "Shift Colors"; EFshiftcolors.menuname = "Shift Colors";
EFshiftcolors.menufunc = m_shift_colors; EFshiftcolors.menufunc = m_shift_colors;
EFshiftcolors.FprevReq = 1; // use preview EFshiftcolors.FprevReq = 1; // use preview
EFshiftcolors.Farea = 2; // select area OK EFshiftcolors.Farea = 2; // select area OK
EFshiftcolors.Fscript = 1; // scripting supported EFshiftcolors.Fscript = 1; // scripting supported
EFshiftcolors.Fpaintedits = 1; // can use with paint edits 22.50
EFshiftcolors.threadfunc = shiftcolors_thread; // thread function EFshiftcolors.threadfunc = shiftcolors_thread; // thread function
if (! edit_setup(EFshiftcolors)) return; // setup edit if (! edit_setup(EFshiftcolors)) return; // setup edit
E3ww = E3pxm->ww; E3ww = E3pxm->ww;
E3hh = E3pxm->hh; E3hh = E3pxm->hh;
/*** /***
Shift Colors Shift Colors
skipping to change at line 5466 skipping to change at line 5528
shiftred = shiftgreen = shiftblue = shiftall; shiftred = shiftgreen = shiftblue = shiftall;
zdialog_stuff(zd,"red",shiftred); zdialog_stuff(zd,"red",shiftred);
zdialog_stuff(zd,"green",shiftgreen); zdialog_stuff(zd,"green",shiftgreen);
zdialog_stuff(zd,"blue",shiftblue); zdialog_stuff(zd,"blue",shiftblue);
} }
zdialog_fetch(zd,"red",shiftred); zdialog_fetch(zd,"red",shiftred);
zdialog_fetch(zd,"green",shiftgreen); zdialog_fetch(zd,"green",shiftgreen);
zdialog_fetch(zd,"blue",shiftblue); zdialog_fetch(zd,"blue",shiftblue);
if (zstrstr("red green blue all blendwidth apply",event)) // trigger update thread if (zstrstr("red green blue all blendwidth apply paint",event)) // trigger update thread
thread_signal(); thread_signal();
return 1; return 1;
} }
// thread function - launch multiple working threads to update image // thread function - launch multiple working threads to update image
void * shiftcolors_thread(void *) void * shiftcolors_thread(void *)
{ {
using namespace shiftcolors_names; using namespace shiftcolors_names;
void * shiftcolors_wthread(void *arg); // worker thread void * shiftcolors_wthread(void *arg); // worker thread
do_wthreads(shiftcolors_wthread,NWT); get_edit_pixels_init(NWT,0);
// worker threads // initz. pixel loop
do_wthreads(shiftcolors_wthread,NWT);
// do worker threads
CEF->Fmods++; // image modified CEF->Fmods++; // image modified
CEF->Fsaved = 0; CEF->Fsaved = 0;
Fpaint2(); // update window if (! Fpaintedits) Fpaint2(); // update window
return 0; return 0;
} }
void * shiftcolors_wthread(void *arg) // worker thread function void * shiftcolors_wthread(void *arg) // worker thread function
{ {
using namespace shiftcolors_names; using namespace shiftcolors_names;
int index = *((int *) (arg)); int index = *((int *) (arg));
int px, py, ii, dist = 0; int px, py, Fend;
float *pix1, *pix3; float *pix1, *pix3;
float red1, green1, blue1, red3, green3, blue3; float R1, G1, B1, R3, G3, B3, R9, G9, B9;
float lossR, lossG, lossB, gainR, gainG, gainB; float lossR, lossG, lossB, gainR, gainG, gainB;
float shift, move, f1, f2; float shift, move;
float max$; float blend, max$;
for (py = index; py < E3hh; py += NWT) while (true)
// loop all image pixels // 22.50
for (px = 0; px < E3ww; px++)
{ {
if (sa_stat == 3) { Fend = get_edit_pixels(index,px,py,blend);
// select area active
ii = py * E3ww + px; if (Fend) break;
dist = sa_pixmap[ii]; if (blend == 0) continue;
// distance from edge
if (! dist) continue;
// outside pixel
}
pix1 = PXMpix(E1pxm,px,py); // input pixel pix1 = PXMpix(E1pxm,px,py); // input pixel
pix3 = PXMpix(E3pxm,px,py); // output pixel
red1 = pix1[0]; R1 = pix1[0];
green1 = pix1[1]; G1 = pix1[1];
blue1 = pix1[2]; B1 = pix1[2];
R3 = pix3[0];
G3 = pix3[1];
B3 = pix3[2];
lossR = lossG = lossB = 0; lossR = lossG = lossB = 0;
gainR = gainG = gainB = 0; gainR = gainG = gainB = 0;
shift = shiftred; // red shift: green <-- red --> blue shift = shiftred; // red shift: green <-- red --> blue
if (shift <= 0.5) { // 0.0 ... 0.5 if (shift <= 0.5) { // 0.0 ... 0.5
move = red1 * 2.0 * (0.5 - shift); move = R1 * 2.0 * (0.5 - shift);
lossR += move; lossR += move;
gainG += move; gainG += move;
} }
if (shift > 0.5) { // 0.5 ... 1.0 if (shift > 0.5) { // 0.5 ... 1.0
move = red1 * 2.0 * (shift - 0.5); move = R1 * 2.0 * (shift - 0.5);
lossR += move; lossR += move;
gainB += move; gainB += move;
} }
shift = shiftgreen; // green shift: blue <-- green --> red shift = shiftgreen; // green shift: blue <-- green --> red
if (shift <= 0.5) { // 0.0 ... 0.5 if (shift <= 0.5) { // 0.0 ... 0.5
move = green1 * 2.0 * (0.5 - shift); move = G1 * 2.0 * (0.5 - shift);
lossG += move; lossG += move;
gainB += move; gainB += move;
} }
if (shift > 0.5) { // 0.5 ... 1.0 if (shift > 0.5) { // 0.5 ... 1.0
move = green1 * 2.0 * (shift - 0.5); move = G1 * 2.0 * (shift - 0.5);
lossG += move; lossG += move;
gainR += move; gainR += move;
} }
shift = shiftblue; // blue shift: red <-- blue --> green shift = shiftblue; // blue shift: red <-- blue --> green
if (shift <= 0.5) { // 0.0 ... 0.5 if (shift <= 0.5) { // 0.0 ... 0.5
move = blue1 * 2.0 * (0.5 - shift); move = B1 * 2.0 * (0.5 - shift);
lossB += move; lossB += move;
gainR += move; gainR += move;
} }
if (shift > 0.5) { // 0.5 ... 1.0 if (shift > 0.5) { // 0.5 ... 1.0
move = blue1 * 2.0 * (shift - 0.5); move = B1 * 2.0 * (shift - 0.5);
lossB += move; lossB += move;
gainG += move; gainG += move;
} }
pix3 = PXMpix(E3pxm,px,py); R9 = R1 - lossR + gainR;
// output pixel // output pixel
G9 = G1 - lossG + gainG;
B9 = B1 - lossB + gainB;
red3 = red1 - lossR + gainR; RGBFIX(R9,G9,B9)
green3 = green1 - lossG + gainG;
blue3 = blue1 - lossB + gainB;
RGBFIX(red3,green3,blue3) if (Fpaintedits)
// mouse paint edit 22.50
{
if (blend > 0)
{
// increase edit
R3 = blend * R9 + (1-blend) * R3;
G3 = blend * G9 + (1-blend) * G3;
B3 = blend * B9 + (1-blend) * B3;
}
if (sa_stat == 3 && dist < sa_blendwidth) { else if (blend < 0)
// select area is active {
f1 = sa_blendfunc(dist); // decrease edit
// blend changes over sa_blendwidth R3 = -blend * R1 + (1+blend) * R3;
f2 = 1.0 - f1; G3 = -blend * G1 + (1+blend) * G3;
red3 = f1 * red3 + f2 * red1; B3 = -blend * B1 + (1+blend) * B3;
green3 = f1 * green3 + f2 * green1; }
blue3 = f1 * blue3 + f2 * blue1;
} }
pix3[0] = red3; else
pix3[1] = green3; // full image edit
pix3[2] = blue3; {
R3 = blend * R9 + (1-blend) * R1;
G3 = blend * G9 + (1-blend) * G1;
B3 = blend * B9 + (1-blend) * B1;
}
pix3[0] = R3;
pix3[1] = G3;
pix3[2] = B3;
} }
return 0; return 0;
} }
/******************************************************************************* */ /******************************************************************************* */
// alien colors - displace hue by an angle that varies over the image // alien colors - displace hue by an angle that varies over the image
namespace alien_colors_names namespace alien_colors_names
{ {
editfunc EFaliencolors; editfunc EFaliencolors;
float BLsz, Ampl; // block size, amplitude float BLsz, Ampl; // block size, amplitude
float Frand[200][200]; // random numbers float Frand[200][200]; // random numbers
#define maxblocks 200 #define maxblocks 200 // max. rows and cols
} }
// menu function // menu function
void m_alien_colors(GtkWidget *, cchar *menu) void m_alien_colors(GtkWidget *, cchar *menu)
{ {
using namespace alien_colors_names; using namespace alien_colors_names;
int alien_colors_dialog_event(zdialog* zd, const char *event); int alien_colors_dialog_event(zdialog* zd, const char *event);
void * alien_colors_thread(void *); void * alien_colors_thread(void *);
skipping to change at line 5707 skipping to change at line 5787
float d1, d7, dx, dy; float d1, d7, dx, dy;
float W0, W1, W2, W3, W4, W5, W6, W7, W8, Wsum; float W0, W1, W2, W3, W4, W5, W6, W7, W8, Wsum;
float R1, G1, B1, R3, G3, B3, H, S, L; float R1, G1, B1, R3, G3, B3, H, S, L;
float theta, f1, f2; float theta, f1, f2;
float *pix1, *pix3; float *pix1, *pix3;
Eww = E3pxm->ww; Eww = E3pxm->ww;
Ehh = E3pxm->hh; Ehh = E3pxm->hh;
bsize = BLsz; // block size bsize = BLsz; // block size
if (Eww / bsize >= maxblocks) bsize = Eww / (maxblocks - 1); // stop > maxblocks rows or cols if (Eww / bsize >= maxblocks) bsize = Eww / (maxblocks - 1); // stop > maxblocks rows or cols
if (Ehh / bsize >= maxblocks) bsize = Ehh / (maxblocks - 1); if (Ehh / bsize >= maxblocks) bsize = Ehh / (maxblocks - 1);
maxrow = 1 + Ehh / bsize; maxrow = 1 + Ehh / bsize;
maxcol = 1 + Eww / bsize; maxcol = 1 + Eww / bsize;
for (py = index; py < Ehh; py += NWT) for (py = index; py < Ehh; py += NWT)
for (px = 0; px < Eww; px++) for (px = 0; px < Eww; px++)
{ {
if (sa_stat == 3) { // select area active if (sa_stat == 3) { // select area active
int ii = py * Eww + px; int ii = py * Eww + px;
skipping to change at line 6234 skipping to change at line 6314
return 0; // exit thread return 0; // exit thread
} }
/******************************************************************************* */ /******************************************************************************* */
// process image using a custom kernel // process image using a custom kernel
namespace anykernel_names namespace anykernel_names
{ {
int Eww, Ehh; // image dimensions int Eww, Ehh; // image dimensions
int kernsize = 5; // kernel size, N x N int kernsize = 5; // kernel size, N x N
float fmpyer = 1.0; // multiplier float fmpyer = 1.0; // multiplier
int fadder = 0; // adder int fadder = 0; // adder
int kernel[15][15]; // up to 15 x 15 int kernel[15][15]; // up to 15 x 15
editfunc EFanykernel; editfunc EFanykernel;
} }
void m_anykernel(GtkWidget *, cchar *menu) // menu function void m_anykernel(GtkWidget *, cchar *menu) // menu function
{ {
using namespace anykernel_names; using namespace anykernel_names;
skipping to change at line 6262 skipping to change at line 6342
EFanykernel.menuname = "Custom Kernel"; EFanykernel.menuname = "Custom Kernel";
EFanykernel.menufunc = m_anykernel; EFanykernel.menufunc = m_anykernel;
EFanykernel.Farea = 2; // select area usable EFanykernel.Farea = 2; // select area usable
EFanykernel.Fscript = 1; // scripting supported EFanykernel.Fscript = 1; // scripting supported
EFanykernel.threadfunc = anykernel_thread; // thread function EFanykernel.threadfunc = anykernel_thread; // thread function
EFanykernel.Frestart = 1; // allow restart EFanykernel.Frestart = 1; // allow restart
if (! edit_setup(EFanykernel)) return; // setup edit if (! edit_setup(EFanykernel)) return; // setup edit
Eww = E3pxm->ww; // image dimensions Eww = E3pxm->ww; // image dimensions
Ehh = E3pxm->hh; Ehh = E3pxm->hh;
anykernel_make_dialog(); anykernel_make_dialog();
return; return;
} }
// build the input dialog with the requested array size // build the input dialog with the requested array size
int anykernel_make_dialog() int anykernel_make_dialog()
{ {
 End of changes. 85 change blocks. 
178 lines changed or deleted 260 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)