From 8132c074797b7e830028f97b6e276af4bbf4ae95 Mon Sep 17 00:00:00 2001 From: Edward Emelianov Date: Thu, 14 Dec 2023 16:55:03 +0300 Subject: [PATCH] change stored size (8/16 bit); allocate img for server in shared memory (TODO: add to client ability of reading from shm) --- BASLER_cameras/basler.c | 18 +- Dummy_cameras/dummyfunc.c | 40 +++- FLI_cameras/flifunc.c | 3 +- HIKROBOT_cameras/mvsfunc.c | 31 ++- ZWO_cameras/zwofunc.c | 4 +- basestructs.h | 16 +- ccdfunc.c | 79 ++++++-- ccdfunc.h | 2 + client.c | 73 ++++--- cmdlnopts.c | 3 + cmdlnopts.h | 1 + imageview.c | 105 +++++++--- locale/ru/LC_MESSAGES/ccd_capture.mo | Bin 11053 -> 14380 bytes locale/ru/messages.po | 276 ++++++++++++++------------- locale/ru/ru.po | 254 ++++++++++++------------ server.c | 113 +++++++++-- server.h | 2 + socket.c | 10 +- socket.h | 2 +- 19 files changed, 637 insertions(+), 395 deletions(-) diff --git a/BASLER_cameras/basler.c b/BASLER_cameras/basler.c index bf82be5..80ff5c1 100644 --- a/BASLER_cameras/basler.c +++ b/BASLER_cameras/basler.c @@ -293,10 +293,10 @@ static int setdevno(int N){ return TRUE; } -static int setbitdepth(int i){ +static int setbitdepth(int depth){ #define MONON 4 const char *fmts[MONON] = {"Mono16", "Mono14", "Mono12", "Mono10"}; - if(i == 0){ // 8 bit + if(depth == 0){ // 8 bit if(!PylonDeviceFeatureIsAvailable( hDev, "EnumEntry_PixelFormat_Mono8" )) return FALSE; PYLONFN(PylonDeviceFeatureFromString, hDev, "PixelFormat", "Mono8"); green("Pixel format: Mono8\n"); @@ -370,21 +370,21 @@ static int capture(IMG *ima){ int width = grabResult.SizeX, height = grabResult.SizeY, stride = grabResult.SizeX + grabResult.PaddingX; //TIMESTAMP("start converting"); if(is16bit){ - int s2 = stride<<1, w2 = width<<1; + int s2 = stride<<1; OMP_FOR() for(int y = 0; y < height; ++y){ - uint16_t *Out = &ima->data[y*width]; + uint8_t *Out = &((uint8_t*)ima->data)[y*width]; const uint8_t *In = &imgBuf[y*s2]; - memcpy(Out, In, w2); + for(int x = 0; x < width; ++x){ + *Out++ = *In; In += 2; + } } }else{ OMP_FOR() for(int y = 0; y < height; ++y){ - uint16_t *Out = &ima->data[y*width]; + uint16_t *Out = &((uint16_t*)ima->data)[y*width]; const uint8_t *In = &imgBuf[y*stride]; - for(int x = 0; x < width; ++x){ - *Out++ = *In++; - } + memcpy(Out, In, width); } } //TIMESTAMP("image ready"); diff --git a/Dummy_cameras/dummyfunc.c b/Dummy_cameras/dummyfunc.c index 795139b..73eaa98 100644 --- a/Dummy_cameras/dummyfunc.c +++ b/Dummy_cameras/dummyfunc.c @@ -40,6 +40,7 @@ static float focuserpos = 1., brightness = 1., gain = 0.; static float camtemp = -30., exptime = 0.; static capture_status capstat = CAPTURE_NO; static double texpstart = 0.; +static uint8_t bitpix = 16; // bit depth: 8 or 16 static int campoll(capture_status *st, float *remain){ if(capstat != CAPTURE_PROCESS){ @@ -68,16 +69,37 @@ static int startexp(){ static int camcapt(IMG *ima){ static int n = 0; if(!ima || !ima->data) return FALSE; - OMP_FOR() - for(int y = 0; y < ima->h; ++y){ - 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.); + if(bitpix == 16){ + OMP_FOR() + for(int y = 0; y < ima->h; ++y){ + uint16_t *d = &((uint16_t*)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.); + } + } + }else{ + OMP_FOR() + for(int y = 0; y < ima->h; ++y){ + uint8_t *d = &((uint8_t*)ima->data)[y*ima->w]; + for(int x = 0; x < ima->w; ++x){ // sinusoide 100x200 + //*d++ = (uint16_t)(((n+x)%100)/99.*65535.); + *d++ = (uint8_t)((1. + sin((n+x) * M_PI/50.)*sin((n+y) * M_PI/100.))*127.); + } } } ++n; - ima->bitpix = 16; + ima->bitpix = bitpix; + return TRUE; +} + +static int camsetbit(int b){ + bitpix = (b) ? 16 : 8; + return TRUE; +} + +static int camgetbp(uint8_t *bp){ + if(bp) *bp = bitpix; return TRUE; } @@ -105,7 +127,6 @@ static int camsetexp(float t){ exptime = t; return TRUE; } - static int camsetgain(float g){ gain = g; return TRUE; @@ -261,11 +282,12 @@ __attribute__ ((visibility("default"))) Camera camera = { .confio = istub, .setio = istub, .setframetype = istub, - .setbitdepth = istub, + .setbitdepth = camsetbit, .setfastspeed = istub, .setgeometry = camsetgeom, .setfanspeed = camfan, // getters: + .getbitpix = camgetbp, .getbrightness = camgetbrig, .getModelName = camgetnam, .getgain = camgetgain, diff --git a/FLI_cameras/flifunc.c b/FLI_cameras/flifunc.c index b58291f..9f0786a 100644 --- a/FLI_cameras/flifunc.c +++ b/FLI_cameras/flifunc.c @@ -463,7 +463,8 @@ retn: static int fli_capt(IMG *ima){ if(!ima || !ima->data) return FALSE; for(int row = 0; row < ima->h; row++){ - TRYFUNC(FLIGrabRow, camdev, &ima->data[row * ima->w], ima->w); + void *ptr = (void*)((is16bit) ? ((uint16_t*)ima->data) + row * ima->w : ((uint8_t*)ima->data) + row * ima->w); + TRYFUNC(FLIGrabRow, camdev, ptr, ima->w); if(fli_err) return FALSE; } ima->bitpix = is16bit ? 16 : 8; diff --git a/HIKROBOT_cameras/mvsfunc.c b/HIKROBOT_cameras/mvsfunc.c index 83353dc..483eb62 100644 --- a/HIKROBOT_cameras/mvsfunc.c +++ b/HIKROBOT_cameras/mvsfunc.c @@ -445,36 +445,27 @@ retn: static int cam_capt(IMG *ima){ if(!handle || !pdata) return FALSE; if(!ima || !ima->data) return FALSE; - ; - int bytes = ima->h*ima->w * 2, stbytes = stImageInfo.nWidth * stImageInfo.nHeight * 2; - if(bytes > pdatasz) bytes = pdatasz; - if(bytes != stbytes) WARNX("Different sizes of image buffer & grabbed image"); - if(stbytes > bytes) bytes = stbytes; - DBG("Copy %d bytes (stbytes=%d)", bytes, stbytes); MVCC_ENUMVALUE EnumValue; TRY(GetEnumValue, "PixelSize", &EnumValue); DBG("PixelSize = %u", EnumValue.nCurValue); ONOK(){ -//green("pixsize=%d\n", EnumValue.nCurValue); + int bytes = ima->h*ima->w * ((7 + ima->bitpix) / 8), stbytes = stImageInfo.nWidth * stImageInfo.nHeight; if(EnumValue.nCurValue == 16){ - memcpy(ima->data, pdata, bytes); ima->bitpix = 12; - return TRUE; - }else if(EnumValue.nCurValue != 8){ + stbytes *= 2; + }else if(EnumValue.nCurValue == 8){ + ima->bitpix = 8; + }else{ WARNX("Unsupported pixel size"); return FALSE; } + if(bytes > pdatasz) bytes = pdatasz; + if(bytes != stbytes) WARNX("Different sizes of image buffer & grabbed image"); + DBG("Copy %d bytes (stbytes=%d)", bytes, stbytes); + memcpy(ima->data, pdata, bytes); + return TRUE; } - // transform 8bits to 16 - DBG("TRANSFORM 8 bit to 16"); - bytes /= 2; - uint8_t *ptr = (uint8_t*) pdata; - OMP_FOR() - for(int i = 0; i < bytes; ++i){ - ima->data[i] = (uint16_t) *ptr++; - } - ima->bitpix = 8; - return TRUE; + return FALSE; } static int cam_modelname(char *buf, int bufsz){ diff --git a/ZWO_cameras/zwofunc.c b/ZWO_cameras/zwofunc.c index a4916df..da300fd 100644 --- a/ZWO_cameras/zwofunc.c +++ b/ZWO_cameras/zwofunc.c @@ -101,7 +101,8 @@ static int campoll(capture_status *st, float *remain){ break; default: // failed DBG("Failed: %d", s); - *st = CAPTURE_ABORTED; + //*st = CAPTURE_ABORTED; + *st = CAPTURE_READY; } if(remain){ float diff = exptime - (dtime() - starttime); @@ -392,6 +393,7 @@ static int setfspd(int spd){ // set fast speed (0..3): 0 - 40% bandwidthovrl, 3 if(spd > 2) bw = 100.; else if(spd > 0) bw += 20. * spd; DBG("set BANDWIDTH to %g", bw); + zwo_setfloat(1, ASI_HIGH_SPEED_MODE); if(ASI_SUCCESS != zwo_setfloat(bw, ASI_BANDWIDTHOVERLOAD)){ DBG("Can't set"); return FALSE; diff --git a/basestructs.h b/basestructs.h index de934a0..91e8a03 100644 --- a/basestructs.h +++ b/basestructs.h @@ -18,13 +18,22 @@ #pragma once #include +#include // for size_t -typedef struct{ - uint16_t *data; // image data +// magic to mark our SHM +#define SHM_MAGIC (0xdeadbeef) + +// base image parameters - sent by socket and stored in shared memory +typedef struct __attribute__((packed, aligned(4))){ + uint32_t MAGICK; // magick (DEADBEEF) - to mark our shm + double timestamp; // timestamp of image taken uint8_t bitpix; // bits per pixel (8 or 16) int w, h; // image size uint16_t max, min; // min/max values float avr, std; // statistics + size_t bytelen; // size of image in bytes + void *data; // pointer to data (next byte after this struct) - only for server + /* `data` is uint8_t or uint16_t depending on `bitpix` */ } IMG; // format of single frame @@ -78,12 +87,13 @@ typedef struct{ int (*confio)(int s); // configure IO-port int (*setio)(int s); // set IO-port to given state int (*setframetype)(int l); // set frametype: 1 - light, 0 - dark - int (*setbitdepth)(int h); // set bit depth: 1 - high, 0 - low + int (*setbitdepth)(int h); // set bit depth : 1 - high (16 bit), 0 - low (8 bit) int (*setfastspeed)(int s); // set readout speed: 1 - fast, 0 - low // geometry (if TRUE, all args are changed to suitable values) int (*setgeometry)(frameformat *fmt); // set geometry in UNBINNED coordinates int (*setfanspeed)(fan_speed spd); // set fan speed // getters: + int (*getbitpix)(uint8_t *bp); // get bit depth in bits per pixel (8, 12, 16 etc) int (*getbrightness)(float *b);// get brightnes level int (*getModelName)(char *n, int l);// string with model name (l - length of n in bytes) int (*getgain)(float *g); // get gain value diff --git a/ccdfunc.c b/ccdfunc.c index 6cc3737..85662e1 100644 --- a/ccdfunc.c +++ b/ccdfunc.c @@ -211,7 +211,6 @@ int saveFITS(IMG *img, char **outp){ } } int width = img->w, height = img->h; - void *data = (void*) img->data; long naxes[2] = {width, height}; double tmpd = 0.0; float tmpf = 0.0; @@ -224,7 +223,9 @@ int saveFITS(IMG *img, char **outp){ fitserror = 0; TRYFITS(fits_create_file, &fp, fnam); if(fitserror) goto cloerr; - TRYFITS(fits_create_img, fp, USHORT_IMG, 2, naxes); + int nbytes = getNbytes(img); + if(nbytes == 1) TRYFITS(fits_create_img, fp, BYTE_IMG, 2, naxes); + else TRYFITS(fits_create_img, fp, USHORT_IMG, 2, naxes); if(fitserror) goto cloerr; // ORIGIN / organization responsible for the data WRITEKEY(fp, TSTRING, "ORIGIN", "SAO RAS", "organization responsible for the data"); @@ -348,7 +349,8 @@ int saveFITS(IMG *img, char **outp){ // INSTRUME / Instrument if(GP->instrument) WRITEKEY(fp, TSTRING, "INSTRUME", GP->instrument, "Instrument"); - TRYFITS(fits_write_img, fp, TUSHORT, 1, width * height, data); + if(nbytes == 1) TRYFITS(fits_write_img, fp, TBYTE, 1, width * height, img->data); + else TRYFITS(fits_write_img, fp, TUSHORT, 1, width * height, img->data); if(fitserror) goto cloerr; TRYFITS(fits_close_file, fp); cloerr: @@ -369,24 +371,23 @@ cloerr: return ret; } -void calculate_stat(IMG *image){ - uint64_t Noverld = 0L, size = image->h*image->w; +static void stat8(IMG *image){ double sum = 0., sum2 = 0.; - uint16_t max = 0, min = 65535; + size_t size = image->w * image->h; + uint8_t max = 0, min = UINT8_MAX; + uint8_t *idata = (uint8_t*)image->data; #pragma omp parallel { - uint16_t maxpriv = 0, minpriv = 65535; - uint64_t ovrpriv = 0; + uint8_t maxpriv = 0, minpriv = UINT8_MAX; double sumpriv = 0., sum2priv = 0.; #pragma omp for nowait - for(uint64_t i = 0; i < size; ++i){ - uint16_t val = image->data[i]; + for(size_t i = 0; i < size; ++i){ + uint8_t val = idata[i]; float pv = (float) val; sum += pv; sum2 += (pv * pv); if(max < val) max = val; if(min > val) min = val; - if(val >= 65530) ovrpriv++; } #pragma omp critical { @@ -394,7 +395,6 @@ void calculate_stat(IMG *image){ if(min > minpriv) min = minpriv; sum += sumpriv; sum2 += sum2priv; - Noverld += ovrpriv; } } double sz = (float)size; @@ -402,10 +402,49 @@ void calculate_stat(IMG *image){ image->avr = avr; image->std = sqrt(fabs(sum2/sz - avr*avr)); image->max = max; image->min = min; +} +static void stat16(IMG *image){ + double sum = 0., sum2 = 0.; + size_t size = image->w * image->h; + uint16_t max = 0, min = UINT16_MAX; + uint16_t *idata = (uint16_t*)image->data; +#pragma omp parallel +{ + uint16_t maxpriv = 0, minpriv = UINT16_MAX; + double sumpriv = 0., sum2priv = 0.; + #pragma omp for nowait + for(size_t i = 0; i < size; ++i){ + uint16_t val = idata[i]; + float pv = (float) val; + sum += pv; + sum2 += (pv * pv); + if(max < val) max = val; + if(min > val) min = val; + } + #pragma omp critical + { + if(max < maxpriv) max = maxpriv; + if(min > minpriv) min = minpriv; + sum += sumpriv; + sum2 += sum2priv; + } +} + double sz = (float)size; + double avr = sum/sz; + image->avr = avr; + image->std = sqrt(fabs(sum2/sz - avr*avr)); + image->max = max; image->min = min; +} + + +void calculate_stat(IMG *image){ + int nbytes = ((7 + image->bitpix) / 8); + if(nbytes == 1) stat8(image); + else stat16(image); if(GP->verbose){ printf(_("Image stat:\n")); - printf("avr = %.1f, std = %.1f, Noverload = %ld\n", avr, image->std, Noverld); - printf("max = %u, min = %u, size = %ld\n", max, min, size); + printf("avr = %.1f, std = %.1f\n", image->avr, image->std); + printf("max = %u, min = %u, size = %d pix\n", image->max, image->min, image->w * image->h); } } @@ -770,6 +809,7 @@ void ccds(){ frameformat fmt = camera->geometry; int raw_width = fmt.w / GP->hbin, raw_height = fmt.h / GP->vbin; DBG("w=%d, h=%d", raw_width, raw_height); + // allocate maximum available memory - for 16bit image uint16_t *img = MALLOC(uint16_t, raw_width * raw_height); DBG("\n\nAllocated image 2x%dx%d=%d", raw_width, raw_height, 2 * raw_width * raw_height); IMG ima = {.data = img, .w = raw_width, .h = raw_height}; @@ -827,6 +867,17 @@ void camstop(){ } } +/** + * @brief getNbytes - calculate amount of bytes to store bitpix (1/2) + * @param image - image + * @return 1 for bitpix<8 or 2 + */ +int getNbytes(IMG *image){ + int n = (image->bitpix + 7) / 8; + if(n < 1) n = 1; + if(n > 2) n = 2; + return n; +} #ifdef IMAGEVIEW #define NFRM (10) diff --git a/ccdfunc.h b/ccdfunc.h index 63eed0e..f3aa659 100644 --- a/ccdfunc.h +++ b/ccdfunc.h @@ -31,6 +31,8 @@ int prepare_ccds(); void ccds(); void camstop(); +int getNbytes(IMG *image); + int startCCD(void **dlh); int startWheel(void **dlh); int startFocuser(void **dlh); diff --git a/client.c b/client.c index f1d201b..758473e 100644 --- a/client.c +++ b/client.c @@ -46,7 +46,8 @@ static int xc0,yc0,xc1,yc1; // current format #ifdef IMAGEVIEW static IMG ima = {0}; static volatile atomic_int grabno = 0, oldgrabno = 0; -static int imdatalen = 0, imbufsz = 0; +static size_t imbufsz = 0; +static uint8_t *imbuf = NULL; #endif static char *readmsg(int fd){ @@ -100,6 +101,7 @@ static int parseans(char *ans){ DBG("Got current format: %d,%d,%d,%d", xc0, yc0, xc1, yc1); return TRUE; } + /* #ifdef IMAGEVIEW else if(0 == strcmp(CMD_IMWIDTH, ans)){ ima.w = atoi(val); @@ -113,6 +115,7 @@ static int parseans(char *ans){ return TRUE; } #endif +*/ //TIMESTAMP("parseans() end"); return FALSE; } @@ -313,40 +316,56 @@ void init_grab_sock(int sock){ send_headers(sock); } -static void getimage(){ - FNAME(); - int sock = controlfd; - TIMESTAMP("Get image sizes"); - SENDCMDW(CMD_IMWIDTH); - SENDCMDW(CMD_IMHEIGHT); - int imsock = open_socket(FALSE, GP->imageport, TRUE); - if(imsock < 0) ERRX("getimage(): can't open image transport socket"); - if(imbufsz < imdatalen){ - DBG("Reallocate memory from %d to %d", imbufsz, imdatalen); - ima.data = realloc(ima.data, imdatalen); - imbufsz = imdatalen; - } +/** + * @brief readNbytes - read `N` bytes from descriptor `fd` into buffer *buf + * @return false if failed + */ +static int readNbytes(int fd, size_t N, uint8_t *buf){ + size_t got = 0, need = N; double t0 = dtime(); - int got = 0; - TIMESTAMP("Start of data read"); - while(dtime() - t0 < CLIENT_TIMEOUT){ - if(!canberead(imsock)) continue; - uint8_t *target = ((uint8_t*)ima.data)+got; - int rd = read(imsock, target, imdatalen - got); + while(dtime() - t0 < CLIENT_TIMEOUT && canberead(fd) && need){ + ssize_t rd = read(fd, buf + got, need); if(rd <= 0){ WARNX("Server disconnected"); 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]); - if(got == imdatalen){ - break; - } + got += rd; need -= rd; + } + if(need) return FALSE; // didn't got whole packet + return TRUE; +} + +static void getimage(){ + FNAME(); + TIMESTAMP("Get image sizes"); + /*SENDCMDW(CMD_IMWIDTH); + SENDCMDW(CMD_IMHEIGHT);*/ + int imsock = open_socket(FALSE, GP->imageport, TRUE); + if(imsock < 0) ERRX("getimage(): can't open image transport socket"); + // get image size + if(!readNbytes(imsock, sizeof(IMG), (uint8_t*)&ima)){ + WARNX("Can't read image header"); + goto eofg; + } + if(ima.bytelen < 1){ + WARNX("Wrong image size"); + goto eofg; + } + if(imbufsz < ima.bytelen){ + size_t newsz = 1024 * (1 + ima.bytelen / 1024); + DBG("Reallocate memory from %zd to %zd", imbufsz, newsz); + imbufsz = newsz; + imbuf = realloc(imbuf, imbufsz); + } + ima.data = imbuf; // renew this value each time after getting `ima` from server + TIMESTAMP("Start of data read"); + if(!readNbytes(imsock, ima.bytelen, imbuf)){ + WARNX("Can't read image data"); + goto eofg; } - if(dtime() - t0 > CLIENT_TIMEOUT) WARNX("Timeout, image didn't received"); TIMESTAMP("Got image"); ++grabno; +eofg: close(imsock); } diff --git a/cmdlnopts.c b/cmdlnopts.c index 21e704f..fcbdd7b 100644 --- a/cmdlnopts.c +++ b/cmdlnopts.c @@ -30,6 +30,7 @@ static glob_pars G = { .brightness = NAN, .gain = NAN, .setwheel = -1, .fanspeed = -1, + .shmkey = 7777777 }; /* @@ -102,6 +103,8 @@ myoption cmdlnopts[] = { {"viewer", NO_ARGS, &G.viewer,1, arg_none, NULL, N_("passive viewer (only get last images)")}, {"restart", NO_ARGS, &G.restart,1, arg_none, NULL, N_("restart image server")}, + {"shmkey", NEED_ARG, NULL, 'k', arg_int, APTR(&G.shmkey), N_("shared memory (with image data) key (default: 7777777")}, + #ifdef IMAGEVIEW {"display", NO_ARGS, NULL, 'D', arg_int, APTR(&G.showimage), N_("Display image in OpenGL window")}, #endif diff --git a/cmdlnopts.h b/cmdlnopts.h index 122a5da..25a477d 100644 --- a/cmdlnopts.h +++ b/cmdlnopts.h @@ -69,6 +69,7 @@ typedef struct{ int verbose; // each '-V' increases it int rewrite; // rewrite file int showimage; // show image preview + int shmkey; // shared memory (with image data) key float gain; // gain level (only for CMOS) float brightness; // brightness (only for CMOS) double exptime; // time of exposition in seconds diff --git a/imageview.c b/imageview.c index 8eb4ae6..005b9d3 100644 --- a/imageview.c +++ b/imageview.c @@ -427,6 +427,7 @@ static void roll_colorfun(){ if(t == COLORFN_MAX) t = COLORFN_BWLINEAR; change_colorfun(t); } + /* no omp histo: 0.000675201s @@ -444,7 +445,7 @@ result: 0.0014689s * @param w,h - image width and height * @return data allocated here */ -static uint8_t *equalize(uint16_t *ori, int w, int h){ +static uint8_t *equalize(IMG *img, int w, int h){ uint8_t *retn = MALLOC(uint8_t, w*h); double orig_hysto[0x10000] = {0.}; // original hystogram uint8_t eq_levls[0x10000] = {0}; // levels to convert: newpix = eq_levls[oldpix] @@ -464,19 +465,39 @@ 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]]; + int bytes = getNbytes(img); + + if(bytes == 1){ + uint8_t *data = (uint8_t*) img->data; + for(int i = 0; i < s; ++i){ + ++orig_hysto[data[i]]; + } + }else{ + uint16_t *data = (uint16_t*) img->data; + for(int i = 0; i < s; ++i){ + ++orig_hysto[data[i]]; + } } + //WARNX("histo: %gs", dtime()-t0); + int max = (bytes == 1) ? 0xff : 0xffff; double part = (double)(s + 1) / 0x100, N = 0.; - for(int i = 0; i <= 0xffff; ++i){ + for(int i = 0; i <= max; ++i){ N += orig_hysto[i]; eq_levls[i] = (uint8_t)(N/part); } //WARNX("equal: %gs", dtime()-t0); //OMP_FOR() -- takes the same time! - for(int i = 0; i < s; ++i){ - retn[i] = eq_levls[ori[i]]; + if(bytes == 1){ + uint8_t *data = (uint8_t*) img->data; + for(int i = 0; i < s; ++i){ + retn[i] = eq_levls[data[i]]; + } + }else{ + uint16_t *data = (uint16_t*) img->data; + for(int i = 0; i < s; ++i){ + retn[i] = eq_levls[data[i]]; + } } //WARNX("result: %gs", dtime()-t0); return retn; @@ -493,20 +514,42 @@ cuts: 0.00188208s */ // count image cuts as [median-sigma median+5sigma] -static uint8_t *mkcuts(uint16_t *ori, int w, int h){ +static uint8_t *mkcuts(IMG *img, 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(); + int bytes = getNbytes(img); + if(bytes == 1){ + uint8_t *data = (uint8_t*) img->data; +#pragma omp parallel +{ + size_t histogram_private[0x100] = {0}; + double sm = 0., sm2 = 0.; + #pragma omp for nowait + for(int i = 0; i < s; ++i){ + ++histogram_private[data[i]]; + double b = data[i]; + sm += b; + sm2 += b*b; + } + #pragma omp critical + { + for(int i = 0; i < 0x100; ++i) orig_hysto[i] += histogram_private[i]; + sum += sm; + sum2 += sm2; + } +} + }else{ + uint16_t *data = (uint16_t*) img->data; #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]; + ++histogram_private[data[i]]; + double b = data[i]; sm += b; sm2 += b*b; } @@ -517,36 +560,42 @@ static uint8_t *mkcuts(uint16_t *ori, int w, int h){ 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){ + int counts = s/2, median = 0, max = (bytes == 1) ? 0xff : 0xffff; + for(; median < max; ++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; + if(high > max) high = max; 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)); + if(bytes == 1){ + uint8_t *data = (uint8_t*) img->data; + OMP_FOR() + for(int i = 0; i < s; ++i){ + uint16_t old = data[i]; + if(old > high){ retn[i] = 255; continue; } + else if(old < low){ retn[i] = 0; continue; } + retn[i] = (uint8_t)(A*(old - low)); + } + }else{ + uint16_t *data = (uint16_t*) img->data; + OMP_FOR() + for(int i = 0; i < s; ++i){ + uint16_t old = data[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; @@ -569,10 +618,10 @@ static void change_displayed_image(IMG *img){ uint8_t *newima; if(imequalize){ DBG("equalize"); - newima = equalize(img->data, w, h); + newima = equalize(img, w, h); }else{ DBG("cuts"); - newima = mkcuts(img->data, w, h); + newima = mkcuts(img, w, h); } GLubyte *dst = im->rawdata; //double t0 = dtime(); diff --git a/locale/ru/LC_MESSAGES/ccd_capture.mo b/locale/ru/LC_MESSAGES/ccd_capture.mo index e92041678f8e8dd16f545fc940a9ce0259df0492..610c50fca1ed43cfb9bcb2018fe9b42388dda949 100644 GIT binary patch literal 14380 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 literal 11053 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 diff --git a/locale/ru/messages.po b/locale/ru/messages.po index 8e6c950..048947b 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-31 16:14+0300\n" +"POT-Creation-Date: 2023-12-14 16:53+0300\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,235 +17,239 @@ msgstr "" "Content-Type: text/plain; charset=koi8-r\n" "Content-Transfer-Encoding: 8bit\n" -#: cmdlnopts.c:40 +#: cmdlnopts.c:41 msgid "common device plugin (e.g devfli.so)" msgstr "" -#: cmdlnopts.c:41 +#: cmdlnopts.c:42 msgid "camera device plugin (e.g. devfli.so)" msgstr "" -#: cmdlnopts.c:42 +#: cmdlnopts.c:43 msgid "focuser device plugin (e.g. devzwo.so)" msgstr "" -#: cmdlnopts.c:43 +#: cmdlnopts.c:44 msgid "wheel device plugin (e.g. devdummy.so)" msgstr "" -#: cmdlnopts.c:44 +#: cmdlnopts.c:45 msgid "list connected devices" msgstr "" -#: cmdlnopts.c:45 +#: cmdlnopts.c:46 msgid "camera device number (if many: 0, 1, 2 etc)" msgstr "" -#: cmdlnopts.c:46 +#: cmdlnopts.c:47 msgid "filter wheel device number (if many: 0, 1, 2 etc)" msgstr "" -#: cmdlnopts.c:47 +#: cmdlnopts.c:48 msgid "focuser device number (if many: 0, 1, 2 etc)" msgstr "" -#: cmdlnopts.c:48 +#: cmdlnopts.c:49 msgid "show this help" msgstr "" -#: cmdlnopts.c:49 +#: cmdlnopts.c:50 msgid "rewrite output file if exists" msgstr "" -#: cmdlnopts.c:50 +#: cmdlnopts.c:51 msgid "verbose level (-V - messages, -VV - debug, -VVV - all shit)" msgstr "" -#: cmdlnopts.c:51 +#: cmdlnopts.c:52 msgid "not open shutter, when exposing (\"dark frames\")" msgstr "" -#: cmdlnopts.c:52 +#: cmdlnopts.c:53 msgid "run in 8-bit mode" msgstr "" -#: cmdlnopts.c:53 +#: cmdlnopts.c:54 msgid "fast readout mode" msgstr "" -#: cmdlnopts.c:54 +#: cmdlnopts.c:55 msgid "set CCD temperature to given value (degr C)" msgstr "" -#: cmdlnopts.c:55 +#: cmdlnopts.c:56 msgid "set fan speed (0 - off, 1 - low, 2 - high)" msgstr "" -#: cmdlnopts.c:57 +#: cmdlnopts.c:58 msgid "program author" msgstr "" -#: cmdlnopts.c:58 +#: cmdlnopts.c:59 msgid "object type (neon, object, flat etc)" msgstr "" -#: cmdlnopts.c:59 +#: cmdlnopts.c:60 msgid "instrument name" msgstr "" -#: cmdlnopts.c:60 +#: cmdlnopts.c:61 msgid "object name" msgstr "" -#: cmdlnopts.c:61 +#: cmdlnopts.c:62 msgid "observers' names" msgstr "" -#: cmdlnopts.c:62 +#: cmdlnopts.c:63 msgid "observing program name" msgstr "" -#: cmdlnopts.c:63 +#: cmdlnopts.c:64 msgid "add records to header from given file[s]" msgstr "" -#: cmdlnopts.c:64 +#: cmdlnopts.c:65 msgid "output file name" msgstr "" -#: cmdlnopts.c:65 +#: cmdlnopts.c:66 msgid "wait while exposition ends" msgstr "" -#: cmdlnopts.c:67 +#: cmdlnopts.c:68 msgid "N flushes before exposing (default: 1)" msgstr "" -#: cmdlnopts.c:68 +#: cmdlnopts.c:69 msgid "horizontal binning to N pixels" msgstr "" -#: cmdlnopts.c:69 +#: cmdlnopts.c:70 msgid "vertical binning to N pixels" msgstr "" -#: cmdlnopts.c:70 +#: cmdlnopts.c:71 msgid "make series of N frames" msgstr "" -#: cmdlnopts.c:71 +#: cmdlnopts.c:72 msgid "make pause for N seconds between expositions" msgstr "" -#: cmdlnopts.c:72 +#: cmdlnopts.c:73 msgid "set exposure time to given value (seconds!)" msgstr "" -#: cmdlnopts.c:73 +#: cmdlnopts.c:74 msgid "cancel current exposition" msgstr "" -#: cmdlnopts.c:74 +#: cmdlnopts.c:75 msgid "" "absolute (not divided by binning!) frame X0 coordinate (-1 - all with " "overscan)" msgstr "" -#: cmdlnopts.c:75 +#: cmdlnopts.c:76 msgid "absolute frame Y0 coordinate (-1 - all with overscan)" msgstr "" -#: cmdlnopts.c:76 +#: cmdlnopts.c:77 msgid "absolute frame X1 coordinate (-1 - all with overscan)" msgstr "" -#: cmdlnopts.c:77 +#: cmdlnopts.c:78 msgid "absolute frame Y1 coordinate (-1 - all with overscan)" msgstr "" -#: cmdlnopts.c:79 +#: cmdlnopts.c:80 msgid "open shutter" msgstr "" -#: cmdlnopts.c:80 +#: cmdlnopts.c:81 msgid "close shutter" msgstr "" -#: cmdlnopts.c:81 +#: cmdlnopts.c:82 msgid "run exposition on LOW @ pin5 I/O port" msgstr "" -#: cmdlnopts.c:82 +#: cmdlnopts.c:83 msgid "run exposition on HIGH @ pin5 I/O port" msgstr "" -#: cmdlnopts.c:83 +#: cmdlnopts.c:84 msgid "get value of I/O port pins" msgstr "" -#: cmdlnopts.c:84 +#: cmdlnopts.c:85 msgid "move stepper motor asynchronous" msgstr "" -#: cmdlnopts.c:86 +#: cmdlnopts.c:87 msgid "set I/O port pins to given value (decimal number, pin1 is LSB)" msgstr "" -#: cmdlnopts.c:87 +#: cmdlnopts.c:88 msgid "" "configure I/O port pins to given value (decimal number, pin1 is LSB, 1 == " "output, 0 == input)" msgstr "" -#: cmdlnopts.c:89 +#: cmdlnopts.c:90 msgid "move focuser to absolute position, mm" msgstr "" -#: cmdlnopts.c:90 +#: cmdlnopts.c:91 msgid "move focuser to relative position, mm (only for standalone)" msgstr "" -#: cmdlnopts.c:92 +#: cmdlnopts.c:93 msgid "set wheel position" msgstr "" -#: cmdlnopts.c:94 +#: cmdlnopts.c:95 msgid "CMOS gain level" msgstr "" -#: cmdlnopts.c:95 +#: cmdlnopts.c:96 msgid "CMOS brightness level" msgstr "" -#: cmdlnopts.c:97 +#: cmdlnopts.c:98 msgid "logging file name (if run as server)" msgstr "" -#: cmdlnopts.c:98 +#: cmdlnopts.c:99 msgid "UNIX socket name" msgstr "" -#: cmdlnopts.c:99 +#: cmdlnopts.c:100 msgid "local INET socket port" msgstr "" -#: cmdlnopts.c:100 +#: cmdlnopts.c:101 msgid "local INET socket port to send/receive images" msgstr "" -#: cmdlnopts.c:101 +#: cmdlnopts.c:102 msgid "run as client" msgstr "" -#: cmdlnopts.c:102 +#: cmdlnopts.c:103 msgid "passive viewer (only get last images)" msgstr "" -#: cmdlnopts.c:103 +#: cmdlnopts.c:104 msgid "restart image server" msgstr "" #: cmdlnopts.c:106 +msgid "shared memory (with image data) key (default: 7777777" +msgstr "" + +#: cmdlnopts.c:109 msgid "Display image in OpenGL window" msgstr "" @@ -279,291 +283,291 @@ msgstr "" msgid "Can't save file with prefix %s" msgstr "" -#: ccdfunc.c:357 +#: ccdfunc.c:359 #, c-format msgid "File saved as '%s'" msgstr "" -#: ccdfunc.c:366 +#: ccdfunc.c:368 msgid "Error saving file" msgstr "" -#: ccdfunc.c:406 +#: ccdfunc.c:445 #, c-format msgid "Image stat:\n" msgstr "" -#: ccdfunc.c:414 +#: ccdfunc.c:453 msgid "Focuser device not pointed" msgstr "" -#: ccdfunc.c:421 +#: ccdfunc.c:460 msgid "No focusers found" msgstr "" -#: ccdfunc.c:452 -#, c-format -msgid "Found %d focusers, you point number %d" -msgstr "" - -#: ccdfunc.c:456 -msgid "Can't set active focuser number" -msgstr "" - -#: ccdfunc.c:470 -msgid "Can't get focuser limit positions" -msgstr "" - -#: ccdfunc.c:477 -msgid "Can't get current focuser position" -msgstr "" - #: ccdfunc.c:491 #, c-format -msgid "Can't set position %g: out of limits [%g, %g]" +msgid "Found %d focusers, you point number %d" msgstr "" #: ccdfunc.c:495 +msgid "Can't set active focuser number" +msgstr "" + +#: ccdfunc.c:509 +msgid "Can't get focuser limit positions" +msgstr "" + +#: ccdfunc.c:516 +msgid "Can't get current focuser position" +msgstr "" + +#: ccdfunc.c:530 +#, c-format +msgid "Can't set position %g: out of limits [%g, %g]" +msgstr "" + +#: ccdfunc.c:534 msgid "Can't home focuser" msgstr "" -#: ccdfunc.c:497 +#: ccdfunc.c:536 #, c-format msgid "Can't set position %g" msgstr "" -#: ccdfunc.c:505 +#: ccdfunc.c:544 msgid "Wheel device not pointed" msgstr "" -#: ccdfunc.c:512 +#: ccdfunc.c:551 msgid "No wheels found" msgstr "" -#: ccdfunc.c:543 +#: ccdfunc.c:582 #, c-format msgid "Found %d wheels, you point number %d" msgstr "" -#: ccdfunc.c:547 +#: ccdfunc.c:586 msgid "Can't set active wheel number" msgstr "" -#: ccdfunc.c:563 +#: ccdfunc.c:602 msgid "Can't get max wheel position" msgstr "" -#: ccdfunc.c:570 +#: ccdfunc.c:609 #, c-format msgid "Wheel position should be from 0 to %d" msgstr "" -#: ccdfunc.c:574 +#: ccdfunc.c:613 #, c-format msgid "Can't set wheel position %d" msgstr "" -#: ccdfunc.c:591 +#: ccdfunc.c:630 #, c-format msgid "%.1f seconds till exposition ends" msgstr "" -#: ccdfunc.c:606 +#: ccdfunc.c:645 msgid "Camera device not pointed" msgstr "" -#: ccdfunc.c:613 ccdfunc.c:614 +#: ccdfunc.c:652 ccdfunc.c:653 msgid "No cameras found" msgstr "" -#: ccdfunc.c:644 +#: ccdfunc.c:683 #, c-format msgid "Found %d cameras, you point number %d" msgstr "" -#: ccdfunc.c:648 +#: ccdfunc.c:687 msgid "Can't set active camera number" msgstr "" -#: ccdfunc.c:654 +#: ccdfunc.c:693 msgid "Can't set fan speed" msgstr "" -#: ccdfunc.c:655 +#: ccdfunc.c:694 #, c-format msgid "Set fan speed to %d" msgstr "" -#: ccdfunc.c:660 +#: ccdfunc.c:699 #, c-format msgid "Camera model: %s" msgstr "" -#: ccdfunc.c:661 +#: ccdfunc.c:700 #, c-format msgid "Pixel size: %g x %g" msgstr "" -#: ccdfunc.c:667 +#: ccdfunc.c:706 #, c-format msgid "Full array: %s" msgstr "" -#: ccdfunc.c:670 +#: ccdfunc.c:709 #, c-format msgid "Field of view: %s" msgstr "" -#: ccdfunc.c:673 +#: ccdfunc.c:712 #, c-format msgid "Current format: %s" msgstr "" -#: ccdfunc.c:676 +#: ccdfunc.c:715 #, c-format msgid "Can't set T to %g degC" msgstr "" -#: ccdfunc.c:684 +#: ccdfunc.c:723 #, c-format msgid "Shutter command: %s\n" msgstr "" -#: ccdfunc.c:686 +#: ccdfunc.c:725 #, c-format msgid "Can't run shutter command %s (unsupported?)" msgstr "" #. "Попытка сконфигурировать порт I/O как %d\n" -#: ccdfunc.c:690 +#: ccdfunc.c:729 #, c-format msgid "Try to configure I/O port as %d" msgstr "" -#: ccdfunc.c:692 +#: ccdfunc.c:731 msgid "Can't configure (unsupported?)" msgstr "" -#: ccdfunc.c:699 +#: ccdfunc.c:738 msgid "Can't get IOport state (unsupported?)" msgstr "" #. "Попытка записи %d в порт I/O\n" -#: ccdfunc.c:703 +#: ccdfunc.c:742 #, c-format msgid "Try to write %d to I/O port" msgstr "" -#: ccdfunc.c:705 +#: ccdfunc.c:744 msgid "Can't set IOport" msgstr "" -#: ccdfunc.c:712 +#: ccdfunc.c:751 #, c-format msgid "Set gain to %g" msgstr "" -#: ccdfunc.c:713 +#: ccdfunc.c:752 #, c-format msgid "Can't set gain to %g" msgstr "" -#: ccdfunc.c:718 +#: ccdfunc.c:757 #, c-format msgid "Set brightness to %g" msgstr "" -#: ccdfunc.c:719 +#: ccdfunc.c:758 #, c-format msgid "Can't set brightness to %g" msgstr "" -#: ccdfunc.c:725 server.c:251 +#: ccdfunc.c:764 server.c:312 #, c-format msgid "Can't set binning %dx%d" msgstr "" -#: ccdfunc.c:737 server.c:252 +#: ccdfunc.c:776 server.c:313 msgid "Can't set given geometry" msgstr "" -#: ccdfunc.c:741 +#: ccdfunc.c:780 #, c-format msgid "Can't set %d flushes" msgstr "" -#: ccdfunc.c:745 +#: ccdfunc.c:784 #, c-format msgid "Can't set exposure time to %f seconds" msgstr "" -#: ccdfunc.c:748 +#: ccdfunc.c:787 msgid "Can't change frame type" msgstr "" -#: ccdfunc.c:751 +#: ccdfunc.c:790 msgid "Can't set bit depth" msgstr "" -#: ccdfunc.c:753 +#: ccdfunc.c:792 msgid "Can't set readout speed" msgstr "" -#: ccdfunc.c:754 +#: ccdfunc.c:793 #, c-format msgid "Readout mode: %s" msgstr "" -#: ccdfunc.c:755 +#: ccdfunc.c:794 msgid "Only show statistics" msgstr "" #. GET binning should be AFTER setgeometry! -#: ccdfunc.c:757 +#: ccdfunc.c:796 msgid "Can't get current binning" msgstr "" #. Захват кадра %d\n -#: ccdfunc.c:781 +#: ccdfunc.c:821 #, c-format msgid "Capture frame %d" msgstr "" -#: ccdfunc.c:783 ccdfunc.c:857 server.c:137 +#: ccdfunc.c:823 ccdfunc.c:908 server.c:198 msgid "Can't start exposition" msgstr "" -#: ccdfunc.c:788 +#: ccdfunc.c:828 msgid "Can't capture image" msgstr "" -#: ccdfunc.c:791 +#: ccdfunc.c:831 msgid "Read grabbed image" msgstr "" -#: ccdfunc.c:795 ccdfunc.c:870 +#: ccdfunc.c:835 ccdfunc.c:921 msgid "Can't grab image" msgstr "" #. %d секунд до окончания паузы\n -#: ccdfunc.c:807 client.c:288 +#: ccdfunc.c:847 client.c:291 #, c-format msgid "%d seconds till pause ends\n" msgstr "" -#: ccdfunc.c:868 +#: ccdfunc.c:919 msgid "Some error when capture" msgstr "" -#: server.c:185 +#: server.c:246 msgid "No camera device" msgstr "" -#: client.c:275 +#: client.c:278 msgid "Can't make exposition" msgstr "" -#: client.c:304 +#: client.c:307 msgid "Server timeout" msgstr "" @@ -580,19 +584,19 @@ msgstr "" msgid "Histogram conversion: %s" msgstr "" -#: imageview.c:640 +#: imageview.c:689 msgid "Can't open OpenGL window, image preview will be inaccessible" msgstr "" -#: imageview.c:682 +#: imageview.c:731 #, c-format msgid "Equalization of histogram: %s" msgstr "" -#: imageview.c:682 +#: imageview.c:731 msgid "on" msgstr "" -#: imageview.c:682 +#: imageview.c:731 msgid "off" msgstr "" diff --git a/locale/ru/ru.po b/locale/ru/ru.po index 9f8b9e1..d5dc058 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-31 16:14+0300\n" + "POT-Creation-Date: 2023-12-14 16:52+0300\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -16,13 +16,13 @@ msgstr "Project-Id-Version: PACKAGE VERSION\n" "Content-Type: text/plain; charset=koi8-r\n" "Content-Transfer-Encoding: 8bit\n" -#: ccdfunc.c:591 +#: ccdfunc.c:630 #, c-format msgid "%.1f seconds till exposition ends" msgstr "%.1f " #. %d секунд до окончания паузы\n -#: ccdfunc.c:807 client.c:288 +#: ccdfunc.c:847 client.c:291 #, c-format msgid "%d seconds till pause ends\n" msgstr "%d \n" @@ -31,15 +31,15 @@ msgstr "%d msgid "Already initialized!" msgstr " !" -#: cmdlnopts.c:95 +#: cmdlnopts.c:96 msgid "CMOS brightness level" msgstr " CMOS" -#: cmdlnopts.c:94 +#: cmdlnopts.c:95 msgid "CMOS gain level" msgstr " Gain CMOS" -#: ccdfunc.c:606 +#: ccdfunc.c:645 msgid "Camera device not pointed" msgstr " " @@ -47,20 +47,20 @@ msgstr " msgid "Camera device unknown" msgstr " " -#: ccdfunc.c:660 +#: ccdfunc.c:699 #, c-format msgid "Camera model: %s" msgstr " : %s" -#: ccdfunc.c:788 +#: ccdfunc.c:828 msgid "Can't capture image" msgstr " " -#: ccdfunc.c:748 +#: ccdfunc.c:787 msgid "Can't change frame type" msgstr " " -#: ccdfunc.c:692 +#: ccdfunc.c:731 msgid "Can't configure (unsupported?)" msgstr " ( ?)" @@ -84,32 +84,32 @@ msgstr " msgid "Can't find wheel in plugin %s: %s" msgstr " %s: %s" -#: ccdfunc.c:699 +#: ccdfunc.c:738 msgid "Can't get IOport state (unsupported?)" msgstr " I/O ( ?)" #. GET binning should be AFTER setgeometry! -#: ccdfunc.c:757 +#: ccdfunc.c:796 msgid "Can't get current binning" msgstr " " -#: ccdfunc.c:477 +#: ccdfunc.c:516 msgid "Can't get current focuser position" msgstr " " -#: ccdfunc.c:470 +#: ccdfunc.c:509 msgid "Can't get focuser limit positions" msgstr " " -#: ccdfunc.c:563 +#: ccdfunc.c:602 msgid "Can't get max wheel position" msgstr " " -#: ccdfunc.c:795 ccdfunc.c:870 +#: ccdfunc.c:835 ccdfunc.c:921 msgid "Can't grab image" msgstr " " -#: ccdfunc.c:495 +#: ccdfunc.c:534 msgid "Can't home focuser" msgstr " " @@ -117,15 +117,15 @@ msgstr " msgid "Can't init mutex!" msgstr " !" -#: client.c:275 +#: client.c:278 msgid "Can't make exposition" msgstr " " -#: imageview.c:640 +#: imageview.c:689 msgid "Can't open OpenGL window, image preview will be inaccessible" msgstr " OpenGL, " -#: ccdfunc.c:686 +#: ccdfunc.c:725 #, c-format msgid "Can't run shutter command %s (unsupported?)" msgstr " %s ( ?)" @@ -136,141 +136,141 @@ msgstr " msgid "Can't save file with prefix %s" msgstr " %s" -#: ccdfunc.c:741 +#: ccdfunc.c:780 #, c-format msgid "Can't set %d flushes" msgstr " %d " -#: ccdfunc.c:705 +#: ccdfunc.c:744 msgid "Can't set IOport" msgstr " I/O" -#: ccdfunc.c:676 +#: ccdfunc.c:715 #, c-format msgid "Can't set T to %g degC" msgstr " %g " -#: ccdfunc.c:648 +#: ccdfunc.c:687 msgid "Can't set active camera number" msgstr " " -#: ccdfunc.c:456 +#: ccdfunc.c:495 msgid "Can't set active focuser number" msgstr " " -#: ccdfunc.c:547 +#: ccdfunc.c:586 msgid "Can't set active wheel number" msgstr " " -#: ccdfunc.c:725 server.c:251 +#: ccdfunc.c:764 server.c:312 #, c-format msgid "Can't set binning %dx%d" msgstr " %dx%d" -#: ccdfunc.c:751 +#: ccdfunc.c:790 msgid "Can't set bit depth" msgstr " " -#: ccdfunc.c:719 +#: ccdfunc.c:758 #, c-format msgid "Can't set brightness to %g" msgstr " %g" -#: ccdfunc.c:745 +#: ccdfunc.c:784 #, c-format msgid "Can't set exposure time to %f seconds" msgstr " %f " -#: ccdfunc.c:654 +#: ccdfunc.c:693 msgid "Can't set fan speed" msgstr " " -#: ccdfunc.c:713 +#: ccdfunc.c:752 #, c-format msgid "Can't set gain to %g" msgstr " Gain %g" -#: ccdfunc.c:737 server.c:252 +#: ccdfunc.c:776 server.c:313 msgid "Can't set given geometry" msgstr " " -#: ccdfunc.c:497 +#: ccdfunc.c:536 #, c-format msgid "Can't set position %g" msgstr " %g" -#: ccdfunc.c:491 +#: ccdfunc.c:530 #, c-format msgid "Can't set position %g: out of limits [%g, %g]" msgstr " %g: [%g, %g]" -#: ccdfunc.c:753 +#: ccdfunc.c:792 msgid "Can't set readout speed" msgstr " " -#: ccdfunc.c:574 +#: ccdfunc.c:613 #, c-format msgid "Can't set wheel position %d" msgstr " %d" -#: ccdfunc.c:783 ccdfunc.c:857 server.c:137 +#: ccdfunc.c:823 ccdfunc.c:908 server.c:198 msgid "Can't start exposition" msgstr " " #. Захват кадра %d\n -#: ccdfunc.c:781 +#: ccdfunc.c:821 #, c-format msgid "Capture frame %d" msgstr " %d" -#: ccdfunc.c:673 +#: ccdfunc.c:712 #, c-format msgid "Current format: %s" msgstr "" -#: cmdlnopts.c:106 +#: cmdlnopts.c:109 msgid "Display image in OpenGL window" msgstr " OpenGL" -#: imageview.c:682 +#: imageview.c:731 #, c-format msgid "Equalization of histogram: %s" msgstr " : %s" -#: ccdfunc.c:366 +#: ccdfunc.c:368 msgid "Error saving file" msgstr " " -#: ccdfunc.c:670 +#: ccdfunc.c:709 #, c-format msgid "Field of view: %s" msgstr " : %s" -#: ccdfunc.c:357 +#: ccdfunc.c:359 #, c-format msgid "File saved as '%s'" msgstr " '%s'" -#: ccdfunc.c:414 +#: ccdfunc.c:453 msgid "Focuser device not pointed" msgstr " " -#: ccdfunc.c:644 +#: ccdfunc.c:683 #, c-format msgid "Found %d cameras, you point number %d" msgstr " %d , %d" -#: ccdfunc.c:452 +#: ccdfunc.c:491 #, c-format msgid "Found %d focusers, you point number %d" msgstr " %d , %d" -#: ccdfunc.c:543 +#: ccdfunc.c:582 #, c-format msgid "Found %d wheels, you point number %d" msgstr " %d , %d" -#: ccdfunc.c:667 +#: ccdfunc.c:706 #, c-format msgid "Full array: %s" msgstr " : %s" @@ -280,321 +280,325 @@ msgstr " msgid "Histogram conversion: %s" msgstr " : %s" -#: ccdfunc.c:406 +#: ccdfunc.c:445 #, c-format msgid "Image stat:\n" msgstr " : \n" -#: cmdlnopts.c:67 +#: cmdlnopts.c:68 msgid "N flushes before exposing (default: 1)" msgstr "N ( : 1)" -#: server.c:185 +#: server.c:246 msgid "No camera device" msgstr " " -#: ccdfunc.c:613 ccdfunc.c:614 +#: ccdfunc.c:652 ccdfunc.c:653 msgid "No cameras found" msgstr " " -#: ccdfunc.c:421 +#: ccdfunc.c:460 msgid "No focusers found" msgstr " " -#: ccdfunc.c:512 +#: ccdfunc.c:551 msgid "No wheels found" msgstr " " -#: ccdfunc.c:755 +#: ccdfunc.c:794 msgid "Only show statistics" msgstr " " -#: ccdfunc.c:661 +#: ccdfunc.c:700 #, c-format msgid "Pixel size: %g x %g" msgstr " : %g x %g" -#: ccdfunc.c:791 +#: ccdfunc.c:831 msgid "Read grabbed image" msgstr " " -#: ccdfunc.c:754 +#: ccdfunc.c:793 #, c-format msgid "Readout mode: %s" msgstr " : %s" -#: client.c:304 +#: client.c:307 msgid "Server timeout" msgstr " " -#: ccdfunc.c:718 +#: ccdfunc.c:757 #, c-format msgid "Set brightness to %g" msgstr " %g" -#: ccdfunc.c:655 +#: ccdfunc.c:694 #, c-format msgid "Set fan speed to %d" msgstr " %d" -#: ccdfunc.c:712 +#: ccdfunc.c:751 #, c-format msgid "Set gain to %g" msgstr " Gain %g" -#: ccdfunc.c:684 +#: ccdfunc.c:723 #, c-format msgid "Shutter command: %s\n" msgstr " : %s\n" -#: ccdfunc.c:868 +#: ccdfunc.c:919 msgid "Some error when capture" msgstr "" #. "Попытка сконфигурировать порт I/O как %d\n" -#: ccdfunc.c:690 +#: ccdfunc.c:729 #, c-format msgid "Try to configure I/O port as %d" msgstr " I/O %d" #. "Попытка записи %d в порт I/O\n" -#: ccdfunc.c:703 +#: ccdfunc.c:742 #, c-format msgid "Try to write %d to I/O port" msgstr " %d I/O" -#: cmdlnopts.c:98 +#: cmdlnopts.c:99 msgid "UNIX socket name" msgstr " UNIX-" -#: ccdfunc.c:505 +#: ccdfunc.c:544 msgid "Wheel device not pointed" msgstr " " -#: ccdfunc.c:570 +#: ccdfunc.c:609 #, c-format msgid "Wheel position should be from 0 to %d" msgstr " 0 %d" -#: cmdlnopts.c:74 +#: cmdlnopts.c:75 msgid "absolute (not divided by binning!) frame X0 coordinate (-1 - all " "with overscan)" msgstr " ( !) X0 (-1 - " ")" -#: cmdlnopts.c:76 +#: cmdlnopts.c:77 msgid "absolute frame X1 coordinate (-1 - all with overscan)" msgstr " X1 (-1 - )" -#: cmdlnopts.c:75 +#: cmdlnopts.c:76 msgid "absolute frame Y0 coordinate (-1 - all with overscan)" msgstr " Y0 (-1 - )" -#: cmdlnopts.c:77 +#: cmdlnopts.c:78 msgid "absolute frame Y1 coordinate (-1 - all with overscan)" msgstr " Y1 (-1 - )" -#: cmdlnopts.c:63 +#: cmdlnopts.c:64 msgid "add records to header from given file[s]" msgstr " FITS- " -#: cmdlnopts.c:45 +#: cmdlnopts.c:46 msgid "camera device number (if many: 0, 1, 2 etc)" msgstr " " -#: cmdlnopts.c:41 +#: cmdlnopts.c:42 msgid "camera device plugin (e.g. devfli.so)" msgstr " (, devfli.so)" -#: cmdlnopts.c:73 +#: cmdlnopts.c:74 msgid "cancel current exposition" msgstr " " -#: cmdlnopts.c:80 +#: cmdlnopts.c:81 msgid "close shutter" msgstr " " -#: cmdlnopts.c:40 +#: cmdlnopts.c:41 msgid "common device plugin (e.g devfli.so)" msgstr " (, devfli.so)" -#: cmdlnopts.c:87 +#: cmdlnopts.c:88 msgid "configure I/O port pins to given value (decimal number, pin1 is LSB, " "1 == output, 0 == input)" msgstr " I/O ( , " "pin1 - , 1 - , 0 - )" -#: cmdlnopts.c:53 +#: cmdlnopts.c:54 msgid "fast readout mode" msgstr " " -#: cmdlnopts.c:46 +#: cmdlnopts.c:47 msgid "filter wheel device number (if many: 0, 1, 2 etc)" msgstr " " -#: cmdlnopts.c:47 +#: cmdlnopts.c:48 msgid "focuser device number (if many: 0, 1, 2 etc)" msgstr " " -#: cmdlnopts.c:42 +#: cmdlnopts.c:43 msgid "focuser device plugin (e.g. devzwo.so)" msgstr " (, devzwo.so)" -#: cmdlnopts.c:83 +#: cmdlnopts.c:84 msgid "get value of I/O port pins" msgstr " I/O" -#: cmdlnopts.c:68 +#: cmdlnopts.c:69 msgid "horizontal binning to N pixels" msgstr " N " -#: cmdlnopts.c:59 +#: cmdlnopts.c:60 msgid "instrument name" msgstr " " -#: cmdlnopts.c:44 +#: cmdlnopts.c:45 msgid "list connected devices" msgstr " " -#: cmdlnopts.c:99 +#: cmdlnopts.c:100 msgid "local INET socket port" msgstr " " -#: cmdlnopts.c:100 +#: cmdlnopts.c:101 #, fuzzy msgid "local INET socket port to send/receive images" msgstr " " -#: cmdlnopts.c:97 +#: cmdlnopts.c:98 msgid "logging file name (if run as server)" msgstr " ( )" -#: cmdlnopts.c:71 +#: cmdlnopts.c:72 msgid "make pause for N seconds between expositions" msgstr " N " -#: cmdlnopts.c:70 +#: cmdlnopts.c:71 msgid "make series of N frames" msgstr " N " -#: cmdlnopts.c:89 +#: cmdlnopts.c:90 msgid "move focuser to absolute position, mm" msgstr " , " -#: cmdlnopts.c:90 +#: cmdlnopts.c:91 msgid "move focuser to relative position, mm (only for standalone)" msgstr " , ( /" ")" -#: cmdlnopts.c:84 +#: cmdlnopts.c:85 msgid "move stepper motor asynchronous" msgstr " " -#: cmdlnopts.c:51 +#: cmdlnopts.c:52 msgid "not open shutter, when exposing (\"dark frames\")" msgstr " (\"\")" -#: cmdlnopts.c:60 +#: cmdlnopts.c:61 msgid "object name" msgstr " " -#: cmdlnopts.c:58 +#: cmdlnopts.c:59 msgid "object type (neon, object, flat etc)" msgstr " (neon, object, flat ..)" -#: cmdlnopts.c:61 +#: cmdlnopts.c:62 msgid "observers' names" msgstr " " -#: cmdlnopts.c:62 +#: cmdlnopts.c:63 msgid "observing program name" msgstr " " -#: imageview.c:682 +#: imageview.c:731 msgid "off" msgstr "" -#: imageview.c:682 +#: imageview.c:731 msgid "on" msgstr "" -#: cmdlnopts.c:79 +#: cmdlnopts.c:80 msgid "open shutter" msgstr " " -#: cmdlnopts.c:64 +#: cmdlnopts.c:65 msgid "output file name" msgstr " " -#: cmdlnopts.c:102 +#: cmdlnopts.c:103 msgid "passive viewer (only get last images)" msgstr "" -#: cmdlnopts.c:57 +#: cmdlnopts.c:58 msgid "program author" msgstr " " -#: cmdlnopts.c:103 +#: cmdlnopts.c:104 msgid "restart image server" msgstr " " -#: cmdlnopts.c:49 +#: cmdlnopts.c:50 msgid "rewrite output file if exists" msgstr " " -#: cmdlnopts.c:101 +#: cmdlnopts.c:102 msgid "run as client" msgstr " " -#: cmdlnopts.c:82 +#: cmdlnopts.c:83 msgid "run exposition on HIGH @ pin5 I/O port" msgstr "" -#: cmdlnopts.c:81 +#: cmdlnopts.c:82 msgid "run exposition on LOW @ pin5 I/O port" msgstr "" -#: cmdlnopts.c:52 +#: cmdlnopts.c:53 msgid "run in 8-bit mode" msgstr "8- " -#: cmdlnopts.c:54 +#: cmdlnopts.c:55 msgid "set CCD temperature to given value (degr C)" msgstr " ()" -#: cmdlnopts.c:86 +#: cmdlnopts.c:87 msgid "set I/O port pins to given value (decimal number, pin1 is LSB)" msgstr " I/O ( , pin1 - )" -#: cmdlnopts.c:72 +#: cmdlnopts.c:73 msgid "set exposure time to given value (seconds!)" msgstr " (!)" -#: cmdlnopts.c:55 +#: cmdlnopts.c:56 msgid "set fan speed (0 - off, 1 - low, 2 - high)" msgstr " (0 - , 1 - , 2 - )" -#: cmdlnopts.c:92 +#: cmdlnopts.c:93 msgid "set wheel position" msgstr " " -#: cmdlnopts.c:48 +#: cmdlnopts.c:106 +msgid "shared memory (with image data) key (default: 7777777" +msgstr "" + +#: cmdlnopts.c:49 msgid "show this help" msgstr " " -#: cmdlnopts.c:50 +#: cmdlnopts.c:51 msgid "verbose level (-V - messages, -VV - debug, -VVV - all shit)" msgstr " (-V - , -VV - , -VVV - )" -#: cmdlnopts.c:69 +#: cmdlnopts.c:70 msgid "vertical binning to N pixels" msgstr " N " -#: cmdlnopts.c:65 +#: cmdlnopts.c:66 msgid "wait while exposition ends" msgstr ", " -#: cmdlnopts.c:43 +#: cmdlnopts.c:44 msgid "wheel device plugin (e.g. devdummy.so)" msgstr " (, devdummy.so)" diff --git a/server.c b/server.c index 09df7a2..3ea18b2 100644 --- a/server.c +++ b/server.c @@ -22,6 +22,8 @@ #include #include #include +#include +#include #include #include @@ -46,6 +48,9 @@ static float focmaxpos = 0., focminpos = 0.; // focuser extremal positions static int wmaxpos = 0.; // wheel max pos static float tremain = 0.; // time when capture done +// IPC key for shared memory +static key_t shmkey = IPC_PRIVATE; + typedef struct{ const char *key; const char *help; @@ -88,6 +93,7 @@ strpair allcommands[] = { { CMD_PROGRAM, "FITS 'PROG-ID' field" }, { CMD_RESTART, "restart server" }, { CMD_REWRITE, "rewrite file (if give `filename`, not `filenameprefix`" }, + { CMD_SHMEMKEY, "get shared memory key" }, { CMD_SHUTTER, "camera shutter's operations" }, { CMD_CAMTEMPER, "camera chip temperature" }, { CMD_TREMAIN, "time (in seconds) of exposition remained" }, @@ -112,16 +118,71 @@ static void unlock(){ if(pthread_mutex_unlock(&locmutex)) ERR("Can't unlock mutex"); } -static IMG ima = {0}; +static IMG *ima = NULL; + +/** + * @brief getshm - get shared memory segment for image + * @param imsize - size of image data (in bytes) + * @return + */ +static IMG *getshm(key_t key, size_t imsize){ + size_t shmsize = sizeof(IMG) + imsize; + shmsize = 1024 * (1 + shmsize / 1024); + DBG("Allocate %zd bytes in shared memory", shmsize); + int shmid = -1; + int flags = (imsize) ? IPC_CREAT | 0666 : 0; + shmid = shmget(key, 0, flags); + if(shmid < 0){ + WARN("Can't get shared memory segment %d", key); + return NULL; + } + if(imsize){ // check if segment exists and its size equal to needs + struct shmid_ds buf; + if(shmctl(shmid, IPC_STAT, &buf) > -1 && shmsize != buf.shm_segsz){ // remove already existing segment + DBG("Need to remove already existing segment"); + shmctl(shmid, IPC_RMID, NULL); + } + shmid = shmget(key, shmsize, flags); + if(shmid < 0){ + WARN("Can't create shared memory segment %d", key); + return NULL; + } + } + flags = (imsize) ? 0 : SHM_RDONLY; // client opens memory in readonly mode + IMG *ptr = shmat(shmid, NULL, flags); + if(ptr == (void*)-1){ + WARN("Can't attach SHM segment %d", key); + return NULL; + } + if(!imsize){ + if(ptr->MAGICK != SHM_MAGIC){ + WARNX("Shared memory %d isn't belongs to image server", key); + shmdt(ptr); + return NULL; + } + return ptr; + } + bzero(ptr, sizeof(IMG)); + ptr->data = (void*)((uint8_t*)ptr + sizeof(IMG)); + ptr->MAGICK = SHM_MAGIC; + shmkey = key; + return ptr; +} + static void fixima(){ FNAME(); if(!camera) return; int raw_width = curformat.w / GP->hbin, raw_height = curformat.h / GP->vbin; - if(!ima.data) ima.data = MALLOC(uint16_t, camera->array.h * camera->array.w); - if(ima.data && raw_width == ima.w && raw_height == ima.h) return; // all OK + // allocate memory for largest possible image + if(!ima) ima = getshm(GP->shmkey, camera->array.h * camera->array.w * 2); + if(!ima) ERRX("Can't allocate memory for image"); + if(raw_width == ima->w && raw_height == ima->h) return; // all OK DBG("curformat: %dx%d", curformat.w, curformat.h); - ima.h = raw_height; - ima.w = raw_width; + ima->h = raw_height; + ima->w = raw_width; + if(!camera->getbitpix(&ima->bitpix)) ima->bitpix = 16; + if(ima->bitpix < 8 || ima->bitpix > 16) ima->bitpix = 16; // use maximum in any strange cases + ima->bytelen = raw_height * raw_width * getNbytes(ima); DBG("new image: %dx%d", raw_width, raw_height); } @@ -155,19 +216,19 @@ static inline void cameracapturestate(){ // capturing - wait for exposition ends TIMESTAMP("Capture ready"); tremain = 0.; // now save frame - if(!ima.data) LOGERR("Can't save image: not initialized"); + if(!ima->data) LOGERR("Can't save image: not initialized"); else{ TIMESTAMP("start capture"); - if(!camera->capture(&ima)){ + if(!camera->capture(ima)){ LOGERR("Can't capture image"); camstate = CAMERA_ERROR; return; }else{ if(lastfile){ TIMESTAMP("Calc stat"); - calculate_stat(&ima); + calculate_stat(ima); } - if(saveFITS(&ima, &lastfile)){ + if(saveFITS(ima, &lastfile)){ DBG("LAST file name changed"); } TIMESTAMP("Image saved"); @@ -287,6 +348,15 @@ static hresult restarthandler(_U_ int fd, _U_ const char *key, _U_ const char *v /******************************************************************************* *************************** CCD/CMOS handlers ********************************* ******************************************************************************/ +// image size +static hresult imsizehandler(int fd, const char *key, _U_ const char *val){ + char buf[64]; + // send image width/height in pixels + if(0 == strcmp(key, CMD_IMHEIGHT)) snprintf(buf, 63, CMD_IMHEIGHT "=%d", ima->h); + else snprintf(buf, 63, CMD_IMWIDTH "=%d", ima->w); + if(!sendstrmessage(fd, buf)) return RESULT_DISCONNECTED; + return RESULT_SILENCE; +} static hresult camlisthandler(int fd, _U_ const char *key, _U_ const char *val){ char buf[BUFSIZ], modname[256]; for(int i = 0; i < camera->Ndevices; ++i){ @@ -910,11 +980,11 @@ static hresult helphandler(int fd, _U_ const char *key, _U_ const char *val){ return RESULT_SILENCE; } -static hresult imsizehandler(int fd, const char *key, _U_ const char *val){ +// shared memory key +static hresult shmemkeyhandler(int fd, _U_ const char *key, _U_ const char *val){ char buf[64]; - // send image width/height in pixels - if(0 == strcmp(key, CMD_IMHEIGHT)) snprintf(buf, 63, CMD_IMHEIGHT "=%d", ima.h); - else snprintf(buf, 63, CMD_IMWIDTH "=%d", ima.w); + if(shmkey == IPC_PRIVATE) return RESULT_FAIL; + snprintf(buf, 63, CMD_SHMEMKEY "=%d", shmkey); if(!sendstrmessage(fd, buf)) return RESULT_DISCONNECTED; return RESULT_SILENCE; } @@ -971,6 +1041,7 @@ static handleritem items[] = { {chkcc, formathandler, CMD_FRAMEMAX}, {chkcc, nflusheshandler, CMD_NFLUSHES}, {chkcam, expstatehandler, CMD_EXPSTATE}, + {chktrue,shmemkeyhandler, CMD_SHMEMKEY}, {chktrue,imsizehandler, CMD_IMWIDTH}, {chktrue,imsizehandler, CMD_IMHEIGHT}, {chkcc, nameprefixhandler, CMD_FILENAMEPREFIX}, @@ -998,6 +1069,17 @@ static handleritem items[] = { #define CLBUFSZ BUFSIZ +// send image as raw data +static void sendimage(int client){ + if(ima->h < 1 || ima->w < 1) return; + senddata(client, ima, sizeof(IMG)); + senddata(client, ima->data, ima->bytelen); + /*void *mem = malloc(ima->bytelen); + memcpy(mem, ima->data, ima->bytelen); + senddata(client, mem, ima->bytelen); + FREE(mem);*/ +} + void server(int sock, int imsock){ DBG("sockfd=%d, imsockfd=%d", sock, imsock); if(sock < 0) ERRX("server(): need at least command socket fd"); @@ -1046,9 +1128,7 @@ void server(int sock, int imsock){ DBG("client=%d", client); if(client > -1){ DBG("client fd: %d", client); - // send image as raw data w*h*2 - if(ima.data && ima.h > 0 && ima.w > 0) - sendimage(client, ima.data, 2*ima.h*ima.w); + sendimage(client); close(client); DBG("%d closed", client); }else{WARN("accept()"); DBG("disconnected");} @@ -1075,6 +1155,7 @@ void server(int sock, int imsock){ } // process some data & send messages to ALL if(camstate == CAMERA_FRAMERDY || camstate == CAMERA_ERROR){ + if(camstate == CAMERA_FRAMERDY) ima->timestamp = time(NULL); // set timestamp char buff[PATH_MAX+32]; snprintf(buff, PATH_MAX, CMD_EXPSTATE "=%d", camstate); DBG("Send %s to %d clients", buff, nfd - 2); diff --git a/server.h b/server.h index 97bad25..a2ba9d9 100644 --- a/server.h +++ b/server.h @@ -40,6 +40,8 @@ char *makeabspath(const char *path, int shouldbe); // get image size in pixels #define CMD_IMWIDTH "imwidth" #define CMD_IMHEIGHT "imheight" +// get shared memory key +#define CMD_SHMEMKEY "shmemkey" // CCD/CMOS #define CMD_CAMLIST "camlist" diff --git a/socket.c b/socket.c index cbb22ac..253ea4f 100644 --- a/socket.c +++ b/socket.c @@ -161,13 +161,13 @@ int start_socket(int isserver){ } // send image data to client -int sendimage(int fd, uint16_t *data, int l){ - DBG("fd=%d, l=%d", fd, l); +int senddata(int fd, void *data, size_t l){ + DBG("fd=%d, l=%zd", fd, l); if(fd < 1 || !data || l < 1) return TRUE; // empty message - DBG("send new image (size=%d) to fd %d", l, fd); + DBG("send new data (size=%zd) to fd %d", l, fd); //strncpy((char*)data, "TEST image data\n", 17); //l = 16; - if(l != send(fd, data, l, MSG_NOSIGNAL)){ + if(l != (size_t)send(fd, data, l, MSG_NOSIGNAL)){ WARN("write()"); LOGWARN("write()"); return FALSE; @@ -183,7 +183,7 @@ int sendmessage(int fd, const char *msg, int l){ static char *tmpbuf = NULL; static int buflen = 0; if(l + 1 > buflen){ - buflen += 1024; + buflen = 1024 * (1 + l/1024); tmpbuf = realloc(tmpbuf, buflen); } DBG("send to fd %d: %s [%d]", fd, msg, l); diff --git a/socket.h b/socket.h index ff759d4..0d7764b 100644 --- a/socket.h +++ b/socket.h @@ -71,7 +71,7 @@ typedef struct{ int open_socket(int isserver, char *path, int isnet); int start_socket(int server); -int sendimage(int fd, uint16_t *data, int l); +int senddata(int fd, void *data, size_t l); int sendmessage(int fd, const char *msg, int l); int sendstrmessage(int fd, const char *msg); char *get_keyval(char *keyval);