00001 #include <stdio.h>
00002 #include <stdlib.h>
00003 #include <stdint.h>
00004 #include <endian.h>
00005 #include <string.h>
00006 #include <math.h>
00007 #include <drms_types.h>
00008 #include <printk.h>
00009 #include "imgdecode_iris.h"
00010
00011 #define MASK(n) ((1u << (n)) - 1u)
00012 #define MAX(a,b) ((a) < (b) ? (b) : (a))
00013 #define MIN(a,b) ((a) > (b) ? (b) : (a))
00014
00015 static int IMGX, IMGY, npixels;
00016
00018 int imgstat_iris(IMG *img, STAT *stat)
00020 {
00021 double s = 0.0, s2 = 0.0, s3 = 0.0, s4 = 0.0, t, ss;
00022 unsigned *h = img->hist;
00023 unsigned n = img->datavals;
00024 unsigned u;
00025 int i;
00026
00027 if (n == 0) {
00028 stat->min = DRMS_MISSING_SHORT;
00029 stat->max = DRMS_MISSING_SHORT;
00030 stat->median = DRMS_MISSING_SHORT;
00031 stat->mean = DRMS_MISSING_DOUBLE;
00032 stat->rms = DRMS_MISSING_DOUBLE;
00033 stat->skew = DRMS_MISSING_DOUBLE;
00034 stat->kurt = DRMS_MISSING_DOUBLE;
00035 return 0;
00036 }
00037
00038 if (img->reopened) {
00039
00040
00041
00042 for (i = 0; i < MAXHIST; ++i)
00043 h[i] = 0;
00044 n = 0;
00045 npixels = img->nx * img->ny;
00046 for (i = 0; i < npixels; ++i) {
00047 if (img->dat[i] == BLANK)
00048 continue;
00049 ++h[img->dat[i]];
00050 ++n;
00051 }
00052 img->datavals = n;
00053 }
00054
00055 memset(stat, 0, sizeof(STAT));
00056
00057 while (h[stat->min] == 0)
00058 ++stat->min;
00059
00060 stat->max = MAXHIST - 1;
00061 while (h[stat->max] == 0)
00062 --stat->max;
00063
00064 stat->median = stat->min;
00065 i = h[stat->median];
00066 while (2*i < n)
00067 i += h[++stat->median];
00068
00069 for (i = stat->min; i <= stat->max; ++i) {
00070 double x = i;
00071 s += (t = x*h[i]);
00072 s2 += (t *= x);
00073 s3 += (t *= x);
00074 s4 += (t *= x);
00075 }
00076
00077 s /= n;
00078 ss = s*s;
00079 stat->mean = s;
00080 s2 /= n;
00081 s3 /= n;
00082 s4 /= n;
00083 if (n > 1) {
00084 t = n * (s2 - ss) / (n-1);
00085 stat->rms = sqrt(t);
00086 }
00087 if (stat->rms > 0.0) {
00088 stat->skew = (s3 - s * (3*s2 - 2*ss)) / (t*stat->rms);
00089 stat->kurt = (s4 - 4*s*s3 + 3*ss*(2*s2-ss)) / (t*t) - 3;
00090 }
00091
00092 return 0;
00093 }
00094
00096 static void put(short *dat, int TAP, int r, int c, int n, unsigned short *pix)
00098 {
00099 int i;
00100
00101 switch (TAP) {
00102 case 0:
00103 if (r < IMGY/2)
00104 memcpy(dat+IMGX*r+c, pix, 2*n);
00105 else if (r < IMGY)
00106 for (i=c; i<c+n; ++i)
00107 dat[IMGX*(r-IMGY/2)+IMGX-1-i] = *pix++;
00108 else if (r < IMGY+IMGY/2)
00109 for (i=c; i<c+n; ++i)
00110 dat[IMGX*(2*IMGY-1-r)+IMGX-1-i] = *pix++;
00111 else
00112 memcpy(dat+IMGX*(2*IMGY+IMGY/2-1-r)+c, pix, 2*n);
00113 break;
00114 case 1:
00115 case 9:
00116 if (r < IMGY)
00117 memcpy(dat+IMGX*r+c, pix, 2*n);
00118 else
00119 for (i=c; i<c+n; ++i)
00120 dat[IMGX*(r-IMGY)+IMGX-1-i] = *pix++;
00121 break;
00122 case 2:
00123 if (r < IMGY/2)
00124 for (i=c; i<c+n; ++i)
00125 dat[IMGX*r+IMGX-1-i] = *pix++;
00126 else
00127 for (i=c; i<c+n; ++i)
00128 dat[IMGX*(IMGY+IMGY/2-1-r)+IMGX-1-i] = *pix++;
00129 break;
00130 case 3:
00131 case 10:
00132 if (r < IMGY)
00133 for (i=c; i<c+n; ++i)
00134 dat[IMGX*(IMGY-1-r)+IMGX-1-i] = *pix++;
00135 else
00136 memcpy(dat+IMGX*(2*IMGY-1-r)+c, pix, 2*n);
00137 break;
00138 case 4:
00139 if (r < IMGY/2)
00140 memcpy(dat+IMGX*r+c, pix, 2*n);
00141 else
00142 memcpy(dat+IMGX*(IMGY+IMGY/2-1-r)+c, pix, 2*n);
00143 break;
00144 case 5:
00145 memcpy(dat+IMGX*r+c, pix, 2*n);
00146 break;
00147 case 6:
00148 for (i=c; i<c+n; ++i)
00149 dat[IMGX*r+IMGX-1-i] = *pix++;
00150 break;
00151 case 7:
00152 for (i=c; i<c+n; ++i)
00153 dat[IMGX*(IMGY-1-r)+IMGX-1-i] = *pix++;
00154
00155 break;
00156 case 8:
00157 memcpy(dat+IMGX*(IMGY-1-r)+c, pix, 2*n);
00158 break;
00159 }
00160 }
00161
00163 int imgdecode_iris_init_hack(IMG *img)
00165 {
00166 int i;
00167
00168 img->datavals = 0;
00169 img->npackets = 0;
00170 img->nerrors = 0;
00171 img->last_pix_err = 0;
00172 img->first_packet_time = UINT64_MAX;
00173 for (i = 0; i < MAXPIXELS; ++i)
00174 img->dat[i] = BLANK;
00175 for (i = 0; i < MAXHIST; ++i)
00176 img->hist[i] = 0;
00177 }
00178
00180 int imgdecode_iris(unsigned short *impdu, IMG *img)
00182 {
00183 unsigned short old, final, diff, w, h, skp, tak;
00184 int i, N, K, bits2go, wordcnt, nzero;
00185 unsigned u, bitbuf, sgn, low, fs, kmask, nmask, nmk;
00186 unsigned offset, ndecoded;
00187 uint64_t uu;
00188 const unsigned short *p;
00189 static unsigned short pix[7000];
00190
00191 static unsigned short *lut[256];
00192 static CROPTABLE cropt[4096];
00193 char fname[64];
00194 FILE *fp;
00195
00196
00197
00198
00199 static char nz[256] = {
00200 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
00201 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
00202 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
00203 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
00204 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
00205 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
00206 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
00207 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
00208 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
00209 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
00210 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
00211 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
00212 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
00213 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
00214 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
00215 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
00216 };
00217
00218
00219
00220
00221
00222 IMGX = img->ny;
00223 IMGY = img->nx;
00224 npixels = IMGX * IMGY;
00225
00226
00227
00228
00229 #if __BYTE_ORDER == __LITTLE_ENDIAN
00230 for (i=0; i<PACKETWORDS; ++i)
00231 impdu[i] = (impdu[i]>>8) + (impdu[i]<<8);
00232 #endif
00233
00234
00235
00236
00237 if (img->initialized)
00238 goto ___DECODE_START___;
00239
00240 u = impdu[4] & 0x7ffu;
00241 if ( u != APID_IRIS_SCIENCE) {
00242 return IMGDECODE_BAD_APID;
00243 }
00244 img->apid = u;
00245 img->telnum = impdu[11] >> 14;
00246 img->fsn = ((impdu[11] & 0x3fff) << 16) + impdu[12];
00247 img->isysn = impdu[11] >> 14;
00248
00249 img->fid = ((impdu[14] & 0xff) << 16) + impdu[13];
00250 img->cropid = impdu[15] >> 4;
00251 img->overflow = impdu[15] & 1;
00252 img->headerr = (impdu[15] >> 1) & 1;
00253 img->luid = impdu[17] >> 8;
00254 img->tap = impdu[16] >> 12;
00255 if (img->tap == 0 && img->cropid > 0)
00256 if (img->isysn == 2)
00257 img->tap = 9;
00258 else if (img->isysn == 1)
00259 img->tap = 10;
00260 u = impdu[16] & 0xff;
00261 if (u == 0 || u == 128) {
00262
00263 img->N = 16;
00264 img->K = 0;
00265 img->R = 0;
00266 } else {
00267
00268 img->N = u >> 3;
00269 if (img->N > 14)
00270 return IMGDECODE_BAD_N;
00271 img->K = u & 0x7;
00272 img->R = (impdu[16] >> 8) & 0xf;
00273 }
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284 img->datavals = 0;
00285 img->npackets = 0;
00286 img->nerrors = 0;
00287 img->last_pix_err = 0;
00288 img->first_packet_time = UINT64_MAX;
00289
00290 for (i = 0; i < MAXPIXELS; ++i)
00291 img->dat[i] = BLANK;
00292
00293 for (i = 0; i < MAXHIST; ++i)
00294 img->hist[i] = 0;
00295
00296
00297 img->initialized = 1;
00298
00299 ___DECODE_START___:
00300
00301
00302
00303
00304 if (img->luid && !lut[img->luid]) {
00305 if (isIRIS(img->apid))
00306 snprintf(fname, 64, TABLE_DIR "/lu/iris/ilu%u", img->luid);
00307 else
00308 return IMGDECODE_BAD_APID;
00309 fp = fopen(fname, "r");
00310 if (!fp)
00311 return IMGDECODE_NO_LOOKUP_TABLE;
00312 fscanf(fp, "%u", &u);
00313 if (u != img->luid)
00314 return IMGDECODE_LOOKUP_ID_MISMATCH;
00315 lut[img->luid] = (unsigned short *) malloc(16384*2);
00316 if (!lut[img->luid])
00317 return IMGDECODE_OUT_OF_MEMORY;
00318 for (i=0; i<16384; ++i)
00319 if (1 != fscanf(fp, "%hu", lut[img->luid] + i)) {
00320 fclose(fp);
00321 free(lut[img->luid]);
00322 lut[img->luid] = 0;
00323 return IMGDECODE_BAD_LOOKUP_TABLE;
00324 }
00325 fclose(fp);
00326 }
00327
00328
00329
00330
00331 if (cropt[img->cropid].totalpix)
00332 img->totalvals = cropt[img->cropid].totalpix;
00333 else if (img->cropid) {
00334 if (isIRIS(img->apid))
00335 snprintf(fname, 64, TABLE_DIR "/crop/iris/crop%u", img->cropid);
00336 else
00337 return IMGDECODE_BAD_APID;
00338 fp = fopen(fname, "r");
00339 if (!fp)
00340 return IMGDECODE_NO_CROP_TABLE;
00341 fscanf(fp, "%u", &u);
00342 if (u != img->cropid)
00343 return IMGDECODE_CROP_ID_MISMATCH;
00344 fscanf(fp, "%hu %hu", &w, &h);
00345 if (!(w == IMGX && h == IMGY) && !(w == IMGX/2 && h == IMGY*2)) {
00346 printk("bad_geo: w=%u h=%u IMGX=%d IMGY=%d\n", w, h, IMGX, IMGY);
00347 printk("bad_geo: cropid=%d fsn=%u\n", img->cropid, img->fsn);
00348 return IMGDECODE_BAD_CROP_GEOMETRY;
00349 }
00350 cropt[img->cropid].width = w;
00351 cropt[img->cropid].height = h;
00352 cropt[img->cropid].skip = (unsigned short *) malloc(2*h);
00353 cropt[img->cropid].take = (unsigned short *) malloc(2*h);
00354 cropt[img->cropid].offset = (unsigned *) malloc(4*h);
00355 if (!cropt[img->cropid].offset)
00356 return IMGDECODE_OUT_OF_MEMORY;
00357 offset = 0;
00358 for (i=0; i<h; ++i) {
00359 if (2 != fscanf(fp, "%hu %hu", &skp, &tak)) {
00360 fclose(fp);
00361 free(cropt[img->cropid].skip);
00362 free(cropt[img->cropid].take);
00363 free(cropt[img->cropid].offset);
00364 return IMGDECODE_BAD_CROP_TABLE;
00365 }
00366 if (skp + tak > w)
00367 return IMGDECODE_BAD_CROP_SKIP_TAKE;
00368 cropt[img->cropid].skip[i] = skp;
00369 cropt[img->cropid].take[i] = tak;
00370 cropt[img->cropid].offset[i] = offset;
00371 offset += tak;
00372 }
00373 fclose(fp);
00374 cropt[img->cropid].totalpix = offset;
00375 img->totalvals = cropt[img->cropid].totalpix;
00376 } else
00377 img->totalvals = npixels;
00378
00379
00380
00381
00382 uu = ((uint64_t)impdu[7] << 32) + ((uint64_t)impdu[8] << 16) + impdu[9];
00383 if (uu < img->first_packet_time)
00384 img->first_packet_time = uu;
00385
00386
00387
00388
00389 if (!img->overflow)
00390 img->overflow = impdu[15] & 1;
00391 if (!img->headerr)
00392 img->headerr = (impdu[15] >> 1) & 1;
00393
00394
00395
00396
00397
00398 offset = ((impdu[17] & 0xff) << 16) + impdu[18];
00399 if (offset >= img->totalvals)
00400 return IMGDECODE_BAD_OFFSET;
00401
00402 p = impdu + PACKETHEADERWORDS;
00403
00404
00405
00406
00407 if (img->N == 16) {
00408 for (i = 0; i < PACKETDATAWORDS && img->totalvals > offset+i; ++i)
00409 pix[i] = p[i] & 0x3fff;
00410 ndecoded = i;
00411 }
00412
00413
00414
00415
00416 else {
00417 old = pix[0] = *p++;
00418 ndecoded = 1;
00419 bitbuf = *p++;
00420 bits2go = 16;
00421 K = img->K;
00422 N = img->N;
00423 nmk = N - K;
00424 kmask = MASK(K);
00425 nmask = MASK(nmk);
00426 final = impdu[PACKETWORDS - 1];
00427
00428 wordcnt = PACKETDATAWORDS - 3;
00429 for (i = PACKETWORDS - 2; i > PACKETHEADERWORDS + 1; --i) {
00430 if (impdu[i]) break;
00431 --wordcnt;
00432 }
00433
00434
00435
00436
00437
00438
00439
00440
00441 while (wordcnt > 0 || (bits2go && bitbuf)) {
00442 if (bits2go < 2 + K) {
00443 bitbuf += *p++ << bits2go;
00444 --wordcnt;
00445 bits2go += 16;
00446 }
00447
00448
00449
00450
00451 low = bitbuf & kmask;
00452 bitbuf >>= K;
00453 sgn = bitbuf & 0x1;
00454 bitbuf >>= 1;
00455 bits2go -= 1 + K;
00456
00457
00458
00459
00460 if (bitbuf == 0) {
00461 if (bits2go < 9) {
00462 fs = bits2go;
00463 if (wordcnt > 0) {
00464 bitbuf = *p++;
00465 --wordcnt;
00466 bits2go = 16;
00467 } else
00468 goto __DECOMPRESS_FAILURE__;
00469 if (bitbuf & 0xff) {
00470 nzero = nz[bitbuf & 0xff];
00471 fs += nzero;
00472 if (fs > 8)
00473 goto __DECOMPRESS_FAILURE__;
00474 } else
00475 goto __DECOMPRESS_FAILURE__;
00476 } else
00477 goto __DECOMPRESS_FAILURE__;
00478 } else if (bitbuf & 0xff) {
00479 nzero = nz[bitbuf & 0xff];
00480 fs = nzero;
00481 } else if (bitbuf & 0x1ff) {
00482 nzero = 8;
00483 fs = nzero;
00484 } else
00485 goto __DECOMPRESS_FAILURE__;
00486 bitbuf >>= (nzero + 1);
00487 bits2go -= nzero + 1;
00488
00489
00490
00491
00492 if (fs == 8) {
00493 if (bits2go < nmk) {
00494 u = nmk - bits2go;
00495 fs = bitbuf;
00496
00497
00498
00499 if (wordcnt >= 0) {
00500 bitbuf = *p++;
00501 --wordcnt;
00502 fs += (bitbuf & MASK(u)) << bits2go;
00503 bitbuf >>= u;
00504 bits2go = 16 - u;
00505 } else
00506 goto __DECOMPRESS_FAILURE__;
00507 } else {
00508 fs = bitbuf & nmask;
00509 bitbuf >>= nmk;
00510 bits2go -= nmk;
00511 }
00512 }
00513
00514
00515
00516
00517 diff = (fs << K) + low;
00518 if (sgn)
00519 old -= diff;
00520 else
00521 old += diff;
00522
00523
00524 if (old > 16383)
00525 goto __DECOMPRESS_FAILURE__;
00526
00527 pix[ndecoded++] = old;
00528 }
00529
00530 if (old != final)
00531 goto __DECOMPRESS_FAILURE__;
00532 }
00533
00534 goto __DECOMPRESS_SUCCESS__;
00535
00536 __DECOMPRESS_FAILURE__:
00537
00538 ++img->nerrors;
00539 u = offset + ndecoded;
00540 if (u < img->totalvals && u > img->totalvals - 4) {
00541 img->last_pix_err = 1;
00542 img->datavals += ndecoded;
00543 ++img->npackets;
00544 goto __POST_PROCESSING__;
00545 }
00546 return IMGDECODE_DECOMPRESS_ERROR;
00547
00548 __DECOMPRESS_SUCCESS__:
00549
00550 u = img->datavals + ndecoded;
00551 if (u > img->totalvals && !img->reopened) {
00552 ++img->nerrors;
00553 return IMGDECODE_TOO_MANY_PIXELS;
00554 }
00555 if (offset + ndecoded > img->totalvals) {
00556 ++img->nerrors;
00557 return IMGDECODE_BAD_OFFSET;
00558 }
00559 img->datavals = u;
00560 ++img->npackets;
00561
00562 __POST_PROCESSING__:
00563
00564 for (i = 0; i < ndecoded; ++i) {
00565
00566
00567
00568 if (img->luid)
00569 pix[i] = lut[img->luid][pix[i]];
00570
00571
00572
00573 if (img->R)
00574 pix[i] <<= img->R;
00575
00576
00577
00578 if (img->hist)
00579 ++img->hist[pix[i]];
00580 }
00581
00582
00583
00584
00585 if (img->cropid) {
00586 unsigned *o = cropt[img->cropid].offset;
00587 unsigned short *s = cropt[img->cropid].skip;
00588 unsigned short *t = cropt[img->cropid].take;
00589 int done = 0;
00590 h = cropt[img->cropid].height;
00591 for (i = 0; ndecoded > 0 && i < h; ++i) {
00592 if (o[i] > offset || (h > i+1 && o[i+1] <= offset))
00593 continue;
00594 skp = offset - o[i];
00595 tak = MIN(ndecoded, t[i] - skp);
00596 if (tak) {
00597 skp += s[i];
00598 put(img->dat, img->tap, i, skp, tak, pix+done);
00599 ndecoded -= tak;
00600 offset += tak;
00601 done += tak;
00602 }
00603 }
00604 } else {
00605 int done = 0;
00606 w = IMGX;
00607 h = IMGY;
00608 switch(img->tap) {
00609 case 0:
00610 case 1:
00611 case 3:
00612 case 9:
00613 case 10:
00614 w = IMGX/2; h = IMGY*2;
00615 break;
00616 }
00617 i = offset / w;
00618 while (ndecoded) {
00619 skp = offset % w;
00620 tak = MIN(ndecoded, w - skp);
00621 if (tak) {
00622 put(img->dat, img->tap, i, skp, tak, pix+done);
00623 ndecoded -= tak;
00624 offset += tak;
00625 done += tak;
00626 ++i;
00627 }
00628 }
00629 }
00630
00631 return 0;
00632 }