diff --git a/BASLER_cameras/basler.c b/BASLER_cameras/basler.c index 8ff2958..8ec791b 100644 --- a/BASLER_cameras/basler.c +++ b/BASLER_cameras/basler.c @@ -292,14 +292,26 @@ static int setdevno(int N){ } static int setbitdepth(int i){ +#define MONON 4 + const char *fmts[MONON] = {"Mono16", "Mono14", "Mono12", "Mono10"}; if(i == 0){ // 8 bit if(!PylonDeviceFeatureIsAvailable( hDev, "EnumEntry_PixelFormat_Mono8" )) return FALSE; PYLONFN(PylonDeviceFeatureFromString, hDev, "PixelFormat", "Mono8"); + green("Pixel format: Mono8\n"); is16bit = FALSE; DBG("8 bit"); }else{ // 16 bit - if(!PylonDeviceFeatureIsAvailable( hDev, "EnumEntry_PixelFormat_Mono16" )) return FALSE; - PYLONFN(PylonDeviceFeatureFromString, hDev, "PixelFormat", "Mono16"); + char buf[128]; + int i = 0; + for(; i < MONON; ++i){ + snprintf(buf, 127, "EnumEntry_PixelFormat_%s", fmts[i]); + if(!PylonDeviceFeatureIsAvailable( hDev, buf)) continue; + green("Pixel format: %s\n", fmts[i]); + PYLONFN(PylonDeviceFeatureFromString, hDev, "PixelFormat", fmts[i]); + break; + } + if(i == MONON) return FALSE; +#undef MONON is16bit = TRUE; DBG("16 bit"); } diff --git a/GRH_cameras/grasshopper.c b/GRH_cameras/grasshopper.c index 93046f0..8c4cd7b 100644 --- a/GRH_cameras/grasshopper.c +++ b/GRH_cameras/grasshopper.c @@ -391,7 +391,7 @@ static int changeformat(frameformat *fmt){ static int setbitdepth(int i){ frameformat fmt; - getformat(&fmt); + if(!getformat(&fmt)) return FALSE; int o16bit = is16bit; if(i == 0) is16bit = FALSE; // 8 bit else is16bit = TRUE; diff --git a/Readme.md b/Readme.md index a60cd64..a5486cd 100644 --- a/Readme.md +++ b/Readme.md @@ -23,7 +23,6 @@ cmake options: ``` Usage: ccd_capture [args] [output file prefix] Args are: - -8, --8bit run in 8-bit mode -A, --author=arg program author -C, --cameradev=arg camera device plugin (e.g. devfli.so) @@ -67,6 +66,7 @@ Usage: ccd_capture [args] [output file prefix] --focdevno=arg focuser device number (if many: 0, 1, 2 etc) --gain=arg CMOS gain level --help show this help + --imageport=arg local INET socket port to send/receive images --logfile=arg logging file name (if run as server) --open-shutter open shutter --path=arg UNIX socket name @@ -78,6 +78,7 @@ Usage: ccd_capture [args] [output file prefix] --set-fan=arg set fan speed (0 - off, 1 - low, 2 - high) --shutter-on-high run exposition on HIGH @ pin5 I/O port --shutter-on-low run exposition on LOW @ pin5 I/O port + --viewer passive viewer (only get last images) --wait wait while exposition ends --wheeldevno=arg filter wheel device number (if many: 0, 1, 2 etc) ``` diff --git a/basestructs.h b/basestructs.h index d9a6d76..de934a0 100644 --- a/basestructs.h +++ b/basestructs.h @@ -63,7 +63,7 @@ typedef struct{ int Ndevices; // amount of devices found void (*close)(); // disconnect & close device int (*startexposition)(); // start exposition - int (*pollcapture)(capture_status *st, float *remain);// start or poll capture process, `remain` - time remain (s) + int (*pollcapture)(capture_status *st, float *remain);// get `st` - status of capture process, `remain` - time remain (s); @return FALSE if error (exp aborted), TRUE while no errors int (*capture)(IMG *ima); // capture an image, struct `ima` should be prepared before void (*cancel)(); // cancel exposition // setters: diff --git a/ccdfunc.c b/ccdfunc.c index a1d08ae..2aad89a 100644 --- a/ccdfunc.c +++ b/ccdfunc.c @@ -829,22 +829,43 @@ void camstop(){ #ifdef IMAGEVIEW +#define NFRM (10) +void framerate(){ + if(GP->verbose == 0) return; + static double tlast = 0., lastn[NFRM] = {0.}, sumn = 0.; + static int lastidx = 0; + if(tlast == 0.){tlast = dtime(); return;} + double t = dtime(), dT = t-tlast; + if(++lastidx > NFRM-1) lastidx = 0; + sumn = sumn - lastn[lastidx] + dT; + lastn[lastidx] = dT; + //for(int i = 0; i < NFRM; ++i) printf("last[%d]=%g\n", i, lastn[i]); + green("Framerate=%.2f (%g seconds for exp); mean framerate=%.2f\n", 1./dT, dT, NFRM/sumn); + tlast = t; +} + static volatile int grabno = 0, lastgrabno = 0, exitgrab = FALSE; static void *grabnext(void *arg){ FNAME(); IMG *ima = (IMG*) arg; do{ if(exitgrab) return NULL; - TIMESTAMP("Start next exp"); + TIMESTAMP("Start exp #%d", grabno+1); TIMEINIT(); if(!ima || !camera) return NULL; - if(!camera->startexposition()){ WARNX(_("Can't start exposition")); continue; } - capture_status cs; + if(!camera->startexposition()){ + WARNX(_("Can't start exposition")); + usleep(10000); + continue; + } + capture_status cs = CAPTURE_ABORTED; TIMESTAMP("Poll"); - while(!camera->pollcapture(&cs, NULL)){ + while(camera->pollcapture(&cs, NULL)){ + if(cs != CAPTURE_PROCESS) break; usleep(10000); if(!camera) return NULL; } + if(cs != CAPTURE_READY){ WARNX(_("Some error when capture")); return NULL;} TIMESTAMP("get"); if(!camera->capture(ima)){ WARNX(_("Can't grab image")); continue; } //calculate_stat(ima); @@ -861,8 +882,8 @@ static void *grabnext(void *arg){ * @return TRUE if new image available */ int ccdcaptured(IMG **imgptr){ - static double tlast = 0.; if(!imgptr) return FALSE; + TIMESTAMP("ccdcaptured() start"); static pthread_t grabthread = 0; if(imgptr == (void*)-1){ // kill `grabnext` DBG("Wait for grabbing thread ends"); @@ -897,26 +918,15 @@ int ccdcaptured(IMG **imgptr){ WARN("Can't create grabbing thread"); grabthread = 0; } - tlast = dtime(); }else{ // grab in process if(grabno != lastgrabno){ // done lastgrabno = grabno; - TIMESTAMP("Grab ends"); - //void *vr; - //pthread_join(grabthread, &vr); - //int retcode = *(int*)vr; - //DBG("retcode = %d", retcode); - //grabthread = 0; - if(GP->verbose > 1){ - double t = dtime(); - green("Framerate=%.2g (%g seconds for exp)\n", 1./(t-tlast), t-tlast); - tlast = t; - } - //TIMESTAMP("Framerate"); - //if(retcode) + TIMESTAMP("Got exp #%d", grabno); + framerate(); return TRUE; } } + TIMESTAMP("ccdcaptured() end"); return FALSE; } #endif diff --git a/ccdfunc.h b/ccdfunc.h index dbd2583..63eed0e 100644 --- a/ccdfunc.h +++ b/ccdfunc.h @@ -38,6 +38,7 @@ void focclose(); void closewheel(); void closecam(); #ifdef IMAGEVIEW +void framerate(); int ccdcaptured(IMG **img); #endif diff --git a/client.c b/client.c index 9c770c7..e701438 100644 --- a/client.c +++ b/client.c @@ -25,6 +25,7 @@ #include #include +#include "ccdfunc.h" // framerate #include "client.h" #include "cmdlnopts.h" #include "server.h" // for common commands names @@ -74,7 +75,7 @@ static char *readmsg(int fd){ // parser of CCD server messages; return TRUE to exit from polling cycle of `getans` (if receive 'FAIL', 'OK' or 'BUSY') static int parseans(char *ans){ if(!ans) return FALSE; - TIMESTAMP("parseans() begin"); + //TIMESTAMP("parseans() begin"); //DBG("Parsing of '%s'", ans); if(0 == strcmp(hresult2str(RESULT_BUSY), ans)){ WARNX("Server busy"); @@ -104,7 +105,7 @@ static int parseans(char *ans){ imdatalen = ima.w * ima.h * 2; } #endif - TIMESTAMP("parseans() end"); + //TIMESTAMP("parseans() end"); return FALSE; } @@ -311,9 +312,9 @@ static void getimage(){ } double t0 = dtime(); int got = 0; + TIMESTAMP("Start of data read"); while(dtime() - t0 < CLIENT_TIMEOUT){ if(!canberead(imsock)) continue; - TIMESTAMP("Read data"); uint8_t *target = ((uint8_t*)ima.data)+got; int rd = read(imsock, target, imdatalen - got); if(rd <= 0){ @@ -321,8 +322,8 @@ static void getimage(){ signals(1); } got += rd; - DBG("Read %d bytes; total read %d from %d; first: %x %x %x %x", rd, got, imdatalen, target[0], - target[1], target[2], target[3]); + //DBG("Read %d bytes; total read %d from %d; first: %x %x %x %x", rd, got, imdatalen, target[0], + // target[1], target[2], target[3]); if(got == imdatalen){ break; } @@ -339,7 +340,7 @@ static void *grabnext(void _U_ *arg){ // daemon grabbing images through the net int sock = controlfd; while(1){ expstate = CAMERA_CAPTURE; - TIMESTAMP("End of cycle, start new"); + TIMESTAMP("End of cycle, start new #%d", grabno+1); TIMEINIT(); SENDMSG(CMD_EXPSTATE "=%d", CAMERA_CAPTURE); // start capture double timeout = GP->exptime + CLIENT_TIMEOUT, t0 = dtime(); @@ -353,7 +354,7 @@ static void *grabnext(void _U_ *arg){ // daemon grabbing images through the net usleep(sleept); TIMESTAMP("check answer"); getans(sock, NULL); - TIMESTAMP("EXPSTATE ===> %d", expstate); + //TIMESTAMP("EXPSTATE ===> %d", expstate); if(expstate != CAMERA_CAPTURE) break; } if(dtime() - t0 >= timeout || expstate != CAMERA_FRAMERDY){ @@ -376,7 +377,7 @@ static void *waitimage(void _U_ *arg){ // passive waiting for next image usleep(1000); continue; } - TIMESTAMP("End of cycle, start new"); + TIMESTAMP("End of cycle, start new #%d", grabno+1); TIMEINIT(); getimage(); expstate = CAMERA_IDLE; @@ -386,6 +387,7 @@ static void *waitimage(void _U_ *arg){ // passive waiting for next image // try to capture images through socket int sockcaptured(IMG **imgptr){ + //TIMESTAMP("sockcaptured() start"); if(!imgptr) return FALSE; static pthread_t grabthread = 0; if(controlfd < 0) return FALSE; @@ -417,13 +419,16 @@ int sockcaptured(IMG **imgptr){ } }else{ // grab in process if(grabno != oldgrabno){ // image is ready - TIMESTAMP("Image ready"); + TIMESTAMP("Image #%d ready", grabno); if(*imgptr && (*imgptr != &ima)) free(*imgptr); *imgptr = &ima; oldgrabno = grabno; + framerate(); + //TIMESTAMP("sockcaptured() end, return TRUE"); return TRUE; } } + //TIMESTAMP("sockcaptured() end, return FALSE"); return FALSE; } // IMAGEVIEW diff --git a/imageview.c b/imageview.c index 9ffd2bd..4e092cd 100644 --- a/imageview.c +++ b/imageview.c @@ -32,7 +32,7 @@ windowData *win = NULL; // main window (common variable for events.c) static pthread_t GLUTthread = 0; // main GLUT thread -static int imequalize = TRUE; +static int imequalize = FALSE; static int initialized = 0; // ==1 if GLUT is initialized; ==0 after clear_GL_context static void *Redraw(_U_ void *p); @@ -218,7 +218,7 @@ static void RedrawWindow(){ glFinish(); glutSwapBuffers(); pthread_mutex_unlock(&win->mutex); - usleep(10000); + usleep(1000); } /** @@ -407,6 +407,8 @@ 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(); + /* -- takes too long because of sync #pragma omp parallel { //printf("%d\n", omp_get_thread_num()); @@ -419,45 +421,53 @@ static uint8_t *equalize(uint16_t *ori, int w, int h){ { for(int i = 0; i < 0x10000; ++i) orig_hysto[i] += histogram_private[i]; } -} +}*/ + for(int i = 0; i < s; ++i){ + ++orig_hysto[ori[i]]; + } + //DBG("HISTOGRAM takes %g", 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() + //OMP_FOR() -- takes too long! for(int i = 0; i < s; ++i){ retn[i] = eq_levls[ori[i]]; } + //DBG("EQUALIZATION takes %g", dtime() - t0); return retn; } static void change_displayed_image(IMG *img){ - if(!win || !win->image) return; + if(!win || !img) return; pthread_mutex_lock(&win->mutex); rawimage *im = win->image; DBG("imh=%d, imw=%d, ch=%u, cw=%u", im->h, im->w, img->h, img->w); int w = img->w, h = img->h, s = w*h; if(!im || (im->h != h) || (im->w != w)){ // realloc image to new size DBG("\n\nRealloc rawdata"); - if(im) FREE(im->rawdata); - else im = MALLOC(rawimage, 1); - im->rawdata = MALLOC(GLubyte, w*h*3); + if(!im) im = MALLOC(rawimage, 1); + if(im->h*im->w < s) im->rawdata = realloc(im->rawdata, s*3); im->h = h; im->w = w; win->image = im; DBG("win->image changed"); } if(imequalize){ + DBG("equalize"); uint8_t *newima = equalize(img->data, w, h); GLubyte *dst = im->rawdata; - OMP_FOR() + 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() 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() + //OMP_FOR() for(int i = 0; i < s; ++i){ gray2rgb(colorfun(img->data[i] / 65536.), &dst[i*3]); } @@ -476,6 +486,7 @@ static void change_displayed_image(IMG *img){ } FREE(b); }*/ + DBG("Unlock"); win->image->changed = 1; pthread_mutex_unlock(&win->mutex); } @@ -549,6 +560,7 @@ int viewer(imagefunc newimage){ return 1; } IMG *img = NULL; + //double t0 = dtime(); while(1){ if(!win || win->killthread){ DBG("got killthread"); @@ -557,15 +569,18 @@ int viewer(imagefunc newimage){ return 0; } if((win->winevt & WINEVT_GETIMAGE) || !(win->winevt & WINEVT_PAUSE)){ + //DBG("CHK new image, t=%g", dtime()-t0); if(newimage(&img)){ //TIMESTAMP("got image -> change"); win->winevt &= ~WINEVT_GETIMAGE; change_displayed_image(img); // change image if refreshed //TIMESTAMP("changed"); } + //DBG("Next cycle, t=%g", dtime()-t0); } if(!win->winevt){ - usleep(10000); + //DBG("No events"); + //usleep(1000); continue; } if(win->winevt & WINEVT_SAVEIMAGE){ // save image diff --git a/locale/ru/messages.po b/locale/ru/messages.po index b68c315..b10157c 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-04-06 15:51+0300\n" +"POT-Creation-Date: 2023-04-07 14:35+0300\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -533,7 +533,7 @@ msgstr "" msgid "Capture frame %d" msgstr "" -#: ccdfunc.c:783 ccdfunc.c:841 server.c:122 +#: ccdfunc.c:783 ccdfunc.c:857 server.c:122 msgid "Can't start exposition" msgstr "" @@ -545,25 +545,29 @@ msgstr "" msgid "Read grabbed image" msgstr "" -#: ccdfunc.c:795 ccdfunc.c:849 +#: ccdfunc.c:795 ccdfunc.c:870 msgid "Can't grab image" msgstr "" #. %d секунд до окончания паузы\n -#: ccdfunc.c:807 client.c:271 +#: ccdfunc.c:807 client.c:272 #, c-format msgid "%d seconds till pause ends\n" msgstr "" +#: ccdfunc.c:868 +msgid "Some error when capture" +msgstr "" + #: server.c:170 msgid "No camera device" msgstr "" -#: client.c:258 +#: client.c:259 msgid "Can't make exposition" msgstr "" -#: client.c:287 +#: client.c:288 msgid "Server timeout" msgstr "" @@ -580,19 +584,19 @@ msgstr "" msgid "Histogram conversion: %s" msgstr "" -#: imageview.c:509 imageview.c:584 +#: imageview.c:520 imageview.c:599 #, c-format msgid "Equalization of histogram: %s" msgstr "" -#: imageview.c:509 imageview.c:584 +#: imageview.c:520 imageview.c:599 msgid "on" msgstr "" -#: imageview.c:509 imageview.c:584 +#: imageview.c:520 imageview.c:599 msgid "off" msgstr "" -#: imageview.c:548 +#: imageview.c:559 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 598754f..9b6d8a6 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-04-06 15:49+0300\n" + "POT-Creation-Date: 2023-04-07 12:51+0300\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -22,7 +22,7 @@ msgid "%.1f seconds till exposition ends" msgstr "%.1f " #. %d секунд до окончания паузы\n -#: ccdfunc.c:807 client.c:271 +#: ccdfunc.c:807 client.c:272 #, c-format msgid "%d seconds till pause ends\n" msgstr "%d \n" @@ -105,7 +105,7 @@ msgstr " msgid "Can't get max wheel position" msgstr " " -#: ccdfunc.c:795 ccdfunc.c:849 +#: ccdfunc.c:795 ccdfunc.c:870 msgid "Can't grab image" msgstr " " @@ -117,11 +117,11 @@ msgstr " msgid "Can't init mutex!" msgstr " !" -#: client.c:258 +#: client.c:259 msgid "Can't make exposition" msgstr " " -#: imageview.c:548 +#: imageview.c:559 msgid "Can't open OpenGL window, image preview will be inaccessible" msgstr " OpenGL, " @@ -213,7 +213,7 @@ msgstr " msgid "Can't set wheel position %d" msgstr " %d" -#: ccdfunc.c:783 ccdfunc.c:841 server.c:122 +#: ccdfunc.c:783 ccdfunc.c:857 server.c:122 msgid "Can't start exposition" msgstr " " @@ -232,7 +232,7 @@ msgstr "" msgid "Display image in OpenGL window" msgstr " OpenGL" -#: imageview.c:509 imageview.c:584 +#: imageview.c:520 imageview.c:599 #, c-format msgid "Equalization of histogram: %s" msgstr " : %s" @@ -327,7 +327,7 @@ msgstr " msgid "Readout mode: %s" msgstr " : %s" -#: client.c:287 +#: client.c:288 msgid "Server timeout" msgstr " " @@ -351,6 +351,10 @@ msgstr " msgid "Shutter command: %s\n" msgstr " : %s\n" +#: ccdfunc.c:868 +msgid "Some error when capture" +msgstr "" + #. "Попытка сконфигурировать порт I/O как %d\n" #: ccdfunc.c:690 #, c-format @@ -510,11 +514,11 @@ msgstr " msgid "observing program name" msgstr " " -#: imageview.c:509 imageview.c:584 +#: imageview.c:520 imageview.c:599 msgid "off" msgstr "" -#: imageview.c:509 imageview.c:584 +#: imageview.c:520 imageview.c:599 msgid "on" msgstr "" diff --git a/socket.c b/socket.c index 6f96248..14ed413 100644 --- a/socket.c +++ b/socket.c @@ -48,14 +48,14 @@ pthread_mutex_t locmutex = PTHREAD_MUTEX_INITIALIZER; // mutex for wheel/camera/ * @return socket FD or -1 if failed */ int open_socket(int isserver, char *path, int isnet){ - DBG("isserver=%d, path=%s, isnet=%d", isserver, path, isnet); + //DBG("isserver=%d, path=%s, isnet=%d", isserver, path, isnet); if(!path) return 1; - DBG("path/port: %s", path); + //DBG("path/port: %s", path); int sock = -1; struct addrinfo hints = {0}, *res; struct sockaddr_un unaddr = {0}; if(isnet){ - DBG("Network socket"); + //DBG("Network socket"); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; @@ -63,7 +63,7 @@ int open_socket(int isserver, char *path, int isnet){ ERR("getaddrinfo"); } }else{ - DBG("UNIX socket"); + //DBG("UNIX socket"); char apath[128]; if(*path == 0){ DBG("convert name"); @@ -187,7 +187,7 @@ int sendmessage(int fd, const char *msg, int l){ buflen += 1024; tmpbuf = realloc(tmpbuf, buflen); } - DBG("send to fd %d: %s [%d]", fd, msg, l); + //DBG("send to fd %d: %s [%d]", fd, msg, l); memcpy(tmpbuf, msg, l); if(msg[l-1] != '\n') tmpbuf[l++] = '\n'; if(l != send(fd, tmpbuf, l, MSG_NOSIGNAL)){ @@ -195,7 +195,7 @@ int sendmessage(int fd, const char *msg, int l){ LOGWARN("write()"); return FALSE; }else{ - DBG("success"); + //DBG("success"); if(globlog){ // logging turned ON tmpbuf[l-1] = 0; // remove trailing '\n' for logging LOGDBG("SEND '%s'", tmpbuf); @@ -230,7 +230,7 @@ const char *hresult2str(hresult r){ * @return `val` */ char *get_keyval(char *keyval){ - DBG("Got string %s", keyval); + //DBG("Got string %s", keyval); // remove starting spaces in key while(isspace(*keyval)) ++keyval; char *val = strchr(keyval, '='); @@ -238,7 +238,7 @@ char *get_keyval(char *keyval){ *val++ = 0; while(isspace(*val)) ++val; } - DBG("val = %s (%zd bytes)", val, (val)?strlen(val):0); + //DBG("val = %s (%zd bytes)", val, (val)?strlen(val):0); // remove trailing spaces in key char *e = keyval + strlen(keyval) - 1; // last key symbol while(isspace(*e) && e > keyval) --e; diff --git a/socket.h b/socket.h index d2d85a0..805ebaf 100644 --- a/socket.h +++ b/socket.h @@ -44,7 +44,7 @@ extern double __t0; #define TIMESTAMP(...) do{DBG(__VA_ARGS__); fprintf(stderr, COLOR_GREEN "%g" COLOR_OLD "\n", dtime()-__t0);}while(0) #else #define TIMEINIT() -#define TIMESTAMP() +#define TIMESTAMP(...) #endif extern pthread_mutex_t locmutex;