diff --git a/Dummy_cameras/dummyfunc.c b/Dummy_cameras/dummyfunc.c
index ccbae21..795139b 100644
--- a/Dummy_cameras/dummyfunc.c
+++ b/Dummy_cameras/dummyfunc.c
@@ -73,7 +73,7 @@ static int camcapt(IMG *ima){
uint16_t *d = &ima->data[y*ima->w];
for(int x = 0; x < ima->w; ++x){ // sinusoide 100x200
//*d++ = (uint16_t)(((n+x)%100)/99.*65535.);
- *d++ = (uint16_t)((1 + sin((n+x) * M_PI/50)*sin((n+y) * M_PI/100))*32767.);
+ *d++ = (uint16_t)((1. + sin((n+x) * M_PI/50.)*sin((n+y) * M_PI/100.))*32767.);
}
}
++n;
diff --git a/ccdfunc.c b/ccdfunc.c
index 2c9ac01..6cc3737 100644
--- a/ccdfunc.c
+++ b/ccdfunc.c
@@ -883,7 +883,7 @@ static void *grabnext(void *arg){
*/
int ccdcaptured(IMG **imgptr){
if(!imgptr) return FALSE;
- TIMESTAMP("ccdcaptured() start");
+ //TIMESTAMP("ccdcaptured() start");
static pthread_t grabthread = 0;
if(imgptr == (void*)-1){ // kill `grabnext`
DBG("Wait for grabbing thread ends");
@@ -926,7 +926,7 @@ int ccdcaptured(IMG **imgptr){
return TRUE;
}
}
- TIMESTAMP("ccdcaptured() end");
+ //TIMESTAMP("ccdcaptured() end");
return FALSE;
}
#endif
diff --git a/client.c b/client.c
index 330b982..f1d201b 100644
--- a/client.c
+++ b/client.c
@@ -273,7 +273,7 @@ void client(int sock){
t0 = dtime();
if(expstate == CAMERA_ERROR){
WARNX(_("Can't make exposition"));
- return;
+ continue;
}
if(expstate != CAMERA_CAPTURE){
verbose(2, "Frame ready!");
diff --git a/imageview.c b/imageview.c
index f2c6cc0..8eb4ae6 100644
--- a/imageview.c
+++ b/imageview.c
@@ -16,7 +16,7 @@
* along with this program. If not, see .
*/
-#include // XInitThreads();
+//#include // XInitThreads();
#include // roundf(), log(), sqrt()
#include
#include
@@ -51,10 +51,12 @@ static void imageview_init(){
WARNX(_("Already initialized!"));
return;
}
- XInitThreads(); // we need it for threaded windows
+ //XInitThreads(); // we need it for threaded windows
glutInit(&c, v);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
- glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_CONTINUE_EXECUTION);
+ // we should call desctructors before exiting
+ //glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_CONTINUE_EXECUTION);
+ glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_GLUTMAINLOOP_RETURNS);
initialized = 1;
}
@@ -138,28 +140,37 @@ static void killwindow(){
if(win->menu){
DBG("Destroy menu");
glutDestroyMenu(win->menu);
+ win->menu = 0;
+ }
+ if(win->ID){
+ DBG("Destroy window");
+ glutDestroyWindow(win->ID);
+ win->ID = 0;
}
- DBG("Destroy window");
- glutDestroyWindow(win->ID);
DBG("Delete textures");
- glDeleteTextures(1, &(win->Tex));
+ if(win->Tex){
+ glDeleteTextures(1, &(win->Tex));
+ win->Tex = 0;
+ }
if(GLUTthread){
DBG("Leave mainloop");
glutLeaveMainLoop();
- DBG("cancel GLUTthread");
- pthread_cancel(GLUTthread);
+ DBG("wait GLUTthread");
+ pthread_join(GLUTthread, NULL);
GLUTthread = 0;
}
DBG("main GL thread cancelled");
initialized = 0;
- windowData *old = win;
- win = NULL;
- DBG("free(rawdata)");
- FREE(old->image->rawdata);
- DBG("free(image)");
- FREE(old->image);
- DBG("free(win)");
- FREE(old);
+ if(win){
+ windowData *old = win;
+ win = NULL;
+ DBG("free(rawdata)");
+ FREE(old->image->rawdata);
+ DBG("free(image)");
+ FREE(old->image);
+ DBG("free(win)");
+ FREE(old);
+ }
DBG("return");
return;
}
@@ -233,6 +244,12 @@ static void *Redraw(_U_ void *arg){
FNAME();
createWindow();
glutMainLoop();
+ // cleanup after window closing
+ win->menu = 0; // prevent deleting of non-existant menu and window
+ win->ID = 0;
+ win->killthread = 1; // kill all threads
+ GLUTthread = 0; // prevent call of glutLeaveMainLoop
+ DBG("\n\nCLOSE ALL after window closing");
return NULL;
}
@@ -354,17 +371,20 @@ static void gray2rgb(double gray, GLubyte *rgb){
}
typedef enum{
- COLORFN_LINEAR, // linear
- COLORFN_LOG, // ln
- COLORFN_SQRT, // sqrt
- COLORFN_POW, // power
- COLORFN_MAX // end of list
+ COLORFN_BWLINEAR, // gray levels, linear
+ COLORFN_BWLOG, // gray ln
+ COLORFN_LINEAR, // linear
+ COLORFN_LOG, // ln
+ COLORFN_SQRT, // sqrt
+ COLORFN_POW, // power
+ COLORFN_MAX // end of list
} colorfn_type;
-static colorfn_type ft = COLORFN_LINEAR;
+static colorfn_type ft = COLORFN_BWLINEAR;
// all colorfun's should get argument in [0, 1] and return in [0, 1]
static double linfun(double arg){ return arg; } // bung for PREVIEW_LINEAR
+static double glogfun(double arg){ return 45.98590 * log(1.+arg); } // gray for log (arg in [0, 255])
static double logfun(double arg){ return log(1.+arg) / 0.6931472; } // for PREVIEW_LOG [log_2(x+1)]
static double powfun(double arg){ return arg * arg;}
static double (*colorfun)(double) = linfun; // default function to convert color
@@ -374,6 +394,14 @@ static void change_colorfun(colorfn_type f){
const char *cfn = NULL;
ft = f;
switch (f){
+ case COLORFN_BWLINEAR:
+ colorfun = linfun;
+ cfn = "bw linear";
+ break;
+ case COLORFN_BWLOG:
+ colorfun = glogfun;
+ cfn = "bw log";
+ break;
case COLORFN_LOG:
colorfun = logfun;
cfn = "log";
@@ -396,9 +424,19 @@ static void change_colorfun(colorfn_type f){
// cycle switch between palettes
static void roll_colorfun(){
colorfn_type t = ++ft;
- if(t == COLORFN_MAX) t = COLORFN_LINEAR;
+ if(t == COLORFN_MAX) t = COLORFN_BWLINEAR;
change_colorfun(t);
}
+/*
+no omp
+histo: 0.000675201s
+equal: 0.000781059s
+result: 0.00135899s
+omp:
+histo: 0.000928879s
+equal: 0.0010879s
+result: 0.0014689s
+*/
/**
* @brief equalize - hystogram equalization
@@ -411,7 +449,7 @@ static uint8_t *equalize(uint16_t *ori, int w, int h){
double orig_hysto[0x10000] = {0.}; // original hystogram
uint8_t eq_levls[0x10000] = {0}; // levels to convert: newpix = eq_levls[oldpix]
int s = w*h;
- //double t0 = dtime();
+//double t0 = dtime();
/* -- takes too long because of sync
#pragma omp parallel
{
@@ -429,17 +467,88 @@ static uint8_t *equalize(uint16_t *ori, int w, int h){
for(int i = 0; i < s; ++i){
++orig_hysto[ori[i]];
}
- //DBG("HISTOGRAM takes %g", dtime() - t0);
+//WARNX("histo: %gs", dtime()-t0);
double part = (double)(s + 1) / 0x100, N = 0.;
for(int i = 0; i <= 0xffff; ++i){
N += orig_hysto[i];
eq_levls[i] = (uint8_t)(N/part);
}
- //OMP_FOR() -- takes too long!
+//WARNX("equal: %gs", dtime()-t0);
+ //OMP_FOR() -- takes the same time!
for(int i = 0; i < s; ++i){
retn[i] = eq_levls[ori[i]];
}
- //DBG("EQUALIZATION takes %g", dtime() - t0);
+//WARNX("result: %gs", dtime()-t0);
+ return retn;
+}
+/*
+ no omp @ histo:
+histo: 0.00269914s
+stat: 0.00272393s
+cuts: 0.00357103s
+ omp @ histo:
+histo: 0.00120497s
+stat: 0.00127792s
+cuts: 0.00188208s
+*/
+
+// count image cuts as [median-sigma median+5sigma]
+static uint8_t *mkcuts(uint16_t *ori, int w, int h){
+ uint8_t *retn = MALLOC(uint8_t, w*h);
+ int orig_hysto[0x10000] = {0.}; // original hystogram
+ int s = w*h;
+ double sum = 0., sum2 = 0.;
+//double t0 = dtime();
+#pragma omp parallel
+{
+ size_t histogram_private[0x10000] = {0};
+ double sm = 0., sm2 = 0.;
+ #pragma omp for nowait
+ for(int i = 0; i < s; ++i){
+ ++histogram_private[ori[i]];
+ double b = ori[i];
+ sm += b;
+ sm2 += b*b;
+ }
+ #pragma omp critical
+ {
+ for(int i = 0; i < 0x10000; ++i) orig_hysto[i] += histogram_private[i];
+ sum += sm;
+ sum2 += sm2;
+ }
+}
+/*
+ for(int i = 0; i < s; ++i){
+ double b = ori[i];
+ ++orig_hysto[ori[i]];
+ sum += b;
+ sum2 += b*b;
+ }
+*/
+//WARNX("histo: %gs", dtime()-t0);
+ // get median level
+ int counts = s/2, median = 0;
+ for(; median < 0xffff; ++median){
+ if((counts -= orig_hysto[median]) < 0) break;
+ }
+ sum /= s;
+ double sigma = sqrt(sum2/s - sum*sum);
+ int low = median - sigma, high = median + 5.*sigma;
+ if(low < 0) low = 0;
+ if(high > 0xffff) high = 0xffff;
+ double A = 255./(high - low);
+ DBG("Got: sigma=%.1f, low=%d, high=%d, A=%g", sigma, low, high, A);
+ // now we can recalculate values: new = (old - low)*A
+//WARNX("stat: %gs", dtime()-t0);
+// DEBUG: 2ms without OMP; 0.7ms with
+ OMP_FOR()
+ for(int i = 0; i < s; ++i){
+ uint16_t old = ori[i];
+ if(old > high){ retn[i] = 255; continue; }
+ else if(old < low){ retn[i] = 0; continue; }
+ retn[i] = (uint8_t)(A*(old - low));
+ }
+//WARNX("cuts: %gs", dtime()-t0);
return retn;
}
@@ -457,25 +566,32 @@ static void change_displayed_image(IMG *img){
win->image = im;
DBG("win->image changed");
}
+ uint8_t *newima;
if(imequalize){
DBG("equalize");
- uint8_t *newima = equalize(img->data, w, h);
- GLubyte *dst = im->rawdata;
- DBG("convert; s=%d, im->s=%d", s, im->h*im->w);
- // openmp would make all calculations MORE SLOW than even in one thread!
- //OMP_FOR()
+ newima = equalize(img->data, w, h);
+ }else{
+ DBG("cuts");
+ newima = mkcuts(img->data, w, h);
+ }
+ GLubyte *dst = im->rawdata;
+//double t0 = dtime();
+ if(ft < COLORFN_LINEAR){ // gray
+ // without OMP: 1.8ms; with OMP: 0.8ms
+ OMP_FOR()
+ for(int i = 0; i < s; ++i){
+ GLubyte *t = &dst[i*3];
+ t[0] = t[1] = t[2] = colorfun(newima[i]);
+ }
+ }else{
+ // without OMP: 3.6ms; with OMP: 1.7ms
+ OMP_FOR()
for(int i = 0; i < s; ++i){
gray2rgb(colorfun(newima[i] / 256.), &dst[i*3]);
}
- FREE(newima);
- }else{
- DBG("convert; s=%d, im->s=%d", s, im->h*im->w);
- GLubyte *dst = im->rawdata;
- //OMP_FOR()
- for(int i = 0; i < s; ++i){
- gray2rgb(colorfun(img->data[i] / 65536.), &dst[i*3]);
- }
}
+//WARNX("Conversion time: %g", dtime()-t0);
+ FREE(newima);
/*
// mirror image around Y
int w3 = w*3, h1 = h-1, wsz = w3*sizeof(GLubyte);
@@ -495,40 +611,6 @@ static void change_displayed_image(IMG *img){
pthread_mutex_unlock(&win->mutex);
}
-#if 0
-// thread for checking
-static void* image_thread(void *data){
- FNAME();
- IMG *(*newimage)(const char *) = (IMG*(*)(const char*)) data;
- IMG *img = NULL;
- while(1){
- if(!win || win->killthread){
- DBG("got killthread");
- clear_GL_context();
- pthread_exit(NULL);
- }
- if(win && win->winevt){
- if(win->winevt & WINEVT_SAVEIMAGE){ // save image
- verbose(2, "Make screenshot\n");
- saveFITS(img, NULL);
- win->winevt &= ~WINEVT_SAVEIMAGE;
- }
- if(win->winevt & WINEVT_ROLLCOLORFUN){
- roll_colorfun();
- win->winevt &= ~WINEVT_ROLLCOLORFUN;
- change_displayed_image(win, img);
- }
- if(win->winevt & WINEVT_EQUALIZE){
- win->winevt &= ~WINEVT_EQUALIZE;
- imequalize = !imequalize;
- verbose(1, _("Equalization of histogram: %s"), imequalize ? N_("on") : N_("off"));
- }
- }
- usleep(10000);
- }
-}
-#endif
-
void closeGL(){ // killed by external signal or ctrl+c
if(!initialized) return;
DBG("KILLL");
diff --git a/locale/ru/messages.po b/locale/ru/messages.po
index 7969e43..8e6c950 100644
--- a/locale/ru/messages.po
+++ b/locale/ru/messages.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2023-05-06 14:36+0300\n"
+"POT-Creation-Date: 2023-05-31 16:14+0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME \n"
"Language-Team: LANGUAGE \n"
@@ -571,28 +571,28 @@ msgstr ""
msgid "Already initialized!"
msgstr ""
-#: imageview.c:291
+#: imageview.c:308
msgid "Can't init mutex!"
msgstr ""
-#: imageview.c:393
+#: imageview.c:421
#, c-format
msgid "Histogram conversion: %s"
msgstr ""
-#: imageview.c:524 imageview.c:600
+#: imageview.c:640
+msgid "Can't open OpenGL window, image preview will be inaccessible"
+msgstr ""
+
+#: imageview.c:682
#, c-format
msgid "Equalization of histogram: %s"
msgstr ""
-#: imageview.c:524 imageview.c:600
+#: imageview.c:682
msgid "on"
msgstr ""
-#: imageview.c:524 imageview.c:600
+#: imageview.c:682
msgid "off"
msgstr ""
-
-#: imageview.c:558
-msgid "Can't open OpenGL window, image preview will be inaccessible"
-msgstr ""
diff --git a/locale/ru/ru.po b/locale/ru/ru.po
index a33fab3..9f8b9e1 100644
--- a/locale/ru/ru.po
+++ b/locale/ru/ru.po
@@ -7,7 +7,7 @@
msgid ""
msgstr "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
- "POT-Creation-Date: 2023-05-06 14:36+0300\n"
+ "POT-Creation-Date: 2023-05-31 16:14+0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME \n"
"Language-Team: LANGUAGE \n"
@@ -113,7 +113,7 @@ msgstr "
msgid "Can't home focuser"
msgstr "Не могу установить фокусер в нуль"
-#: imageview.c:291
+#: imageview.c:308
msgid "Can't init mutex!"
msgstr "Не могу инициализировать мьютекс!"
@@ -121,7 +121,7 @@ msgstr "
msgid "Can't make exposition"
msgstr "Не могу выполнить экспозицию"
-#: imageview.c:558
+#: imageview.c:640
msgid "Can't open OpenGL window, image preview will be inaccessible"
msgstr "Не могу открыть окно OpenGL, отображение будет недоступно"
@@ -232,7 +232,7 @@ msgstr ""
msgid "Display image in OpenGL window"
msgstr "Отображение изображения в окне OpenGL"
-#: imageview.c:524 imageview.c:600
+#: imageview.c:682
#, c-format
msgid "Equalization of histogram: %s"
msgstr "Эквализация гистограммы: %s"
@@ -275,7 +275,7 @@ msgstr "
msgid "Full array: %s"
msgstr "Полный формат: %s"
-#: imageview.c:393
+#: imageview.c:421
#, c-format
msgid "Histogram conversion: %s"
msgstr "Преобразование гистограммы: %s"
@@ -510,11 +510,11 @@ msgstr "
msgid "observing program name"
msgstr "название программы"
-#: imageview.c:524 imageview.c:600
+#: imageview.c:682
msgid "off"
msgstr "выкл"
-#: imageview.c:524 imageview.c:600
+#: imageview.c:682
msgid "on"
msgstr "вкл"