Changeset 5516 for trunk/psModules/src/imsubtract
- Timestamp:
- Nov 15, 2005, 10:09:03 AM (20 years ago)
- Location:
- trunk/psModules/src/imsubtract
- Files:
-
- 3 edited
-
pmSubtractBias.c (modified) (11 diffs)
-
pmSubtractBias.h (modified) (2 diffs)
-
pmSubtractSky.c (modified) (11 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psModules/src/imsubtract/pmSubtractBias.c
r5435 r5516 6 6 * @author GLG, MHPCC 7 7 * 8 * @version $Revision: 1. 4$ $Name: not supported by cvs2svn $9 * @date $Date: 2005-1 0-20 23:06:24$8 * @version $Revision: 1.5 $ $Name: not supported by cvs2svn $ 9 * @date $Date: 2005-11-15 20:09:03 $ 10 10 * 11 11 * Copyright 2004 Maui High Performance Computing Center, University of Hawaii 12 12 * 13 13 */ 14 14 /*****************************************************************************/ 15 /* INCLUDE FILES */ 16 /*****************************************************************************/ 17 #include <stdio.h> 18 #include <math.h> 19 #include <string.h> 20 #include "pslib.h" 15 21 #if HAVE_CONFIG_H 16 22 #include <config.h> 17 23 #endif 18 19 24 #include "pmSubtractBias.h" 20 25 21 #define PM_SUBTRACT_BIAS_POLYNOMIAL_ORDER 2 22 #define PM_SUBTRACT_BIAS_SPLINE_ORDER 3 23 26 /*****************************************************************************/ 27 /* DEFINE STATEMENTS */ 28 /*****************************************************************************/ 24 29 // XXX: put these in psConstants.h 25 void PS_POLY1D_PRINT(psPolynomial1D *poly) 30 void PS_POLY1D_PRINT( 31 psPolynomial1D *poly) 26 32 { 27 33 printf("-------------- PS_POLY1D_PRINT() --------------\n"); … … 51 57 }\ 52 58 53 /****************************************************************************** 54 psSubtractFrame(): this routine will take as input a readout for the input 55 image and a readout for the bias image. The bias image is subtracted in 56 place from the input image. 59 /*****************************************************************************/ 60 /* TYPE DEFINITIONS */ 61 /*****************************************************************************/ 62 63 /*****************************************************************************/ 64 /* GLOBAL VARIABLES */ 65 /*****************************************************************************/ 66 psS32 currentId = 0; // XXX: remove 67 psS32 memLeaks = 0; // XXX: remove 68 //PRINT_MEMLEAKS(8); XXX 69 /*****************************************************************************/ 70 /* FILE STATIC VARIABLES */ 71 /*****************************************************************************/ 72 73 /*****************************************************************************/ 74 /* FUNCTION IMPLEMENTATION - LOCAL */ 75 /*****************************************************************************/ 76 77 /****************************************************************************** 78 psSubtractFrame(): this routine will take as input the pmReadout for the input 79 image and a pmReadout for the bias image. The bias image is subtracted in 80 place from the input image. We assume that sizes and types are checked 81 elsewhere. 82 83 XXX: Verify that the image and readout offsets are being used the right way. 84 85 XXX: Ensure that it does the correct thing with image size. 57 86 *****************************************************************************/ 58 static pmReadout *SubtractFrame(pmReadout *in, 59 const pmReadout *bias) 60 { 61 psS32 i; 62 psS32 j; 63 64 if (bias == NULL) { 65 psLogMsg(__func__, PS_LOG_WARN, 66 "WARNING: pmSubtractBias.c: SubtractFrame(): bias frame is NULL. Returning original image.\n"); 67 return(in); 68 } 69 70 71 if ((in->image->numRows + in->row0 - bias->row0) > bias->image->numRows) { 72 psError(PS_ERR_UNKNOWN,true, "bias image does not have enough rows. Returning in image\n"); 73 return(in); 74 } 75 if ((in->image->numCols + in->col0 - bias->col0) > bias->image->numCols) { 76 psError(PS_ERR_UNKNOWN,true, "bias image does not have enough columns. Returning in image\n"); 77 return(in); 78 } 79 80 for (i=0;i<in->image->numRows;i++) { 81 for (j=0;j<in->image->numCols;j++) { 87 static pmReadout *SubtractFrame( 88 pmReadout *in, 89 const pmReadout *bias) 90 { 91 // XXX: When did the ->row0 and ->col0 offsets get coded? 92 for (psS32 i=0;i<in->image->numRows;i++) { 93 for (psS32 j=0;j<in->image->numCols;j++) { 82 94 in->image->data.F32[i][j]-= 83 95 bias->image->data.F32[i+in->row0-bias->row0][j+in->col0-bias->col0]; 96 84 97 if ((in->mask != NULL) && (bias->mask != NULL)) { 85 98 (in->mask->data.U8[i][j])|= … … 92 105 } 93 106 107 108 /****************************************************************************** 109 psSubtractDarkFrame(): this routine will take as input the pmReadout for the 110 input image and a pmReadout for the dark image. The dark image is scaled and 111 subtracted in place from the input image. 112 113 XXX: Verify that the image and readout offsets are being used the right way. 114 115 XXX: Ensure that it does the correct thing with image size. 116 *****************************************************************************/ 117 static pmReadout *SubtractDarkFrame( 118 pmReadout *in, 119 const pmReadout *dark, 120 psF32 scale) 121 { 122 // XXX: When did the ->row0 and ->col0 offsets get coded? 123 if (fabs(scale) > FLT_EPSILON) { 124 for (psS32 i=0;i<in->image->numRows;i++) { 125 for (psS32 j=0;j<in->image->numCols;j++) { 126 in->image->data.F32[i][j]-= 127 (scale * dark->image->data.F32[i+in->row0-dark->row0][j+in->col0-dark->col0]); 128 129 if ((in->mask != NULL) && (dark->mask != NULL)) { 130 (in->mask->data.U8[i][j])|= 131 dark->mask->data.U8[i+in->row0-dark->row0][j+in->col0-dark->col0]; 132 } 133 } 134 } 135 } else { 136 for (psS32 i=0;i<in->image->numRows;i++) { 137 for (psS32 j=0;j<in->image->numCols;j++) { 138 in->image->data.F32[i][j]-= 139 dark->image->data.F32[i+in->row0-dark->row0][j+in->col0-dark->col0]; 140 141 if ((in->mask != NULL) && (dark->mask != NULL)) { 142 (in->mask->data.U8[i][j])|= 143 dark->mask->data.U8[i+in->row0-dark->row0][j+in->col0-dark->col0]; 144 } 145 } 146 } 147 } 148 149 return(in); 150 } 151 94 152 /****************************************************************************** 95 153 ImageSubtractScalar(): subtract a scalar from the input image. 96 154 97 XXX: Use a psLib function for this. 98 99 XXX: This should 100 *****************************************************************************/ 101 static psImage *ImageSubtractScalar(psImage *image, 102 psF32 scalar) 155 XXX: Is there a psLib function for this? 156 *****************************************************************************/ 157 static psImage *ImageSubtractScalar( 158 psImage *image, 159 psF32 scalar) 103 160 { 104 161 for (psS32 i=0;i<image->numRows;i++) { … … 164 221 165 222 if (numOptions == 0) { 166 psError(PS_ERR_UNKNOWN,true, "No statistics options have been specified.\n");223 psError(PS_ERR_UNKNOWN,true, "No allowable statistics options have been specified.\n"); 167 224 } 168 225 if (numOptions != 1) { … … 173 230 } 174 231 175 232 /****************************************************************************** 233 Polynomial1DCopy(): This private function copies the members of the existing 234 psPolynomial1D "in" into the existing psPolynomial1D "out". The previous 235 members of the existing psPolynomial1D "out" are psFree'ed. 236 *****************************************************************************/ 237 static psBool Polynomial1DCopy( 238 psPolynomial1D *out, 239 psPolynomial1D *in) 240 { 241 psFree(out->coeff); 242 psFree(out->coeffErr); 243 psFree(out->mask); 244 245 out->type = in->type; 246 out->nX = in->nX; 247 248 out->coeff = (psF64 *) psAlloc((in->nX + 1) * sizeof(psF64)); 249 // XXX: use memcpy 250 for (psS32 i = 0 ; i < (in->nX + 1) ; i++) { 251 out->coeff[i] = in->coeff[i]; 252 } 253 254 out->coeffErr = (psF64 *) psAlloc((in->nX + 1) * sizeof(psF64)); 255 // XXX: use memcpy 256 for (psS32 i = 0 ; i < (in->nX + 1) ; i++) { 257 out->coeffErr[i] = in->coeffErr[i]; 258 } 259 260 out->mask = (psMaskType *) psAlloc((in->nX + 1) * sizeof(psMaskType)); 261 // XXX: use memcpy 262 for (psS32 i = 0 ; i < (in->nX + 1) ; i++) { 263 out->mask[i] = in->mask[i]; 264 } 265 266 return(true); 267 } 268 269 /****************************************************************************** 270 Polynomial1DDup(): This private function duplicates and then returns the input 271 psPolynomial1D "in". 272 *****************************************************************************/ 273 static psPolynomial1D *Polynomial1DDup( 274 psPolynomial1D *in) 275 { 276 psPolynomial1D *out = psPolynomial1DAlloc(in->nX, in->type); 277 Polynomial1DCopy(out, in); 278 return(out); 279 } 280 281 282 /****************************************************************************** 283 SplineCopy(): This private function copies the members of the existing 284 psSpline in into the existing psSpline out. 285 *****************************************************************************/ 286 static psBool SplineCopy( 287 psSpline1D *out, 288 psSpline1D *in) 289 { 290 PS_ASSERT_PTR_NON_NULL(out, false); 291 PS_ASSERT_PTR_NON_NULL(in, false); 292 293 for (psS32 i = 0 ; i < out->n ; i++) { 294 psFree(out->spline[i]); 295 } 296 psFree(out->spline); 297 psFree(out->knots); 298 psFree(out->p_psDeriv2); 299 300 out->n = in->n; 301 out->spline = (psPolynomial1D **) psAlloc(in->n * sizeof(psPolynomial1D *)); 302 for (psS32 i = 0 ; i < in->n ; i++) { 303 out->spline[i] = Polynomial1DDup(in->spline[i]); 304 } 305 306 out->knots = psVectorCopy(out->knots, in->knots, in->knots->type.type); 307 308 out->p_psDeriv2 = (psF32 *) psAlloc((in->n + 1) * sizeof(psF32)); 309 // XXX: use memcpy 310 for (psS32 i = 0 ; i < (in->n + 1) ; i++) { 311 out->p_psDeriv2[i] = in->p_psDeriv2[i]; 312 } 313 314 return(true); 315 } 176 316 177 317 /****************************************************************************** … … 181 321 PM_FIT_POLYNOMIAL: fit a polynomial to the entire input vector data. 182 322 PM_FIT_SPLINE: fit splines to the input vector data. 183 XXX: Doesn't it make more sense to do polynomial interpolation on a few 184 elements of the input vector, rather than fit a polynomial to the entire 185 vector? 186 *****************************************************************************/ 187 static psVector *ScaleOverscanVector(psVector *overscanVector, 188 psS32 n, 189 void *fitSpec, 190 pmFit fit) 323 The resulting spline or polynomial is set in the fitSpec argument. 324 *****************************************************************************/ 325 static psVector *ScaleOverscanVector( 326 psVector *overscanVector, 327 psS32 n, 328 void *fitSpec, 329 pmFit fit) 191 330 { 192 331 psTrace(".psModule.pmSubtracBias.ScaleOverscanVector", 4, 193 332 "---- ScaleOverscanVector() begin (%d -> %d) ----\n", overscanVector->n, n); 194 // PS_VECTOR_PRINT_F32(overscanVector);195 333 196 334 if (NULL == overscanVector) { … … 205 343 // 206 344 if (n == overscanVector->n) { 207 for (psS32 i = 0 ; i < n ; i++) { 208 newVec->data.F32[i] = overscanVector->data.F32[i]; 209 } 210 return(newVec); 211 } 212 psPolynomial1D *myPoly; 213 psSpline1D *mySpline; 345 return(psVectorCopy(newVec, overscanVector, PS_TYPE_F32)); 346 } 214 347 psF32 x; 215 psS32 i;216 348 217 349 if (fit == PM_FIT_POLYNOMIAL) { 218 350 // Fit a polynomial to the old overscan vector. 219 myPoly = (psPolynomial1D *) fitSpec;351 psPolynomial1D *myPoly = (psPolynomial1D *) fitSpec; 220 352 PS_ASSERT_POLY_NON_NULL(myPoly, NULL); 353 PS_ASSERT_POLY1D(myPoly, NULL); 221 354 myPoly = psVectorFitPolynomial1D(myPoly, NULL, 0, overscanVector, NULL, NULL); 222 355 if (myPoly == NULL) { 223 psError(PS_ERR_UNKNOWN, false, " ScaleOverscanVector()(1):Could not fit a polynomial to the psVector.\n");356 psError(PS_ERR_UNKNOWN, false, "Could not fit a polynomial to the psVector.\n"); 224 357 return(NULL); 225 358 } … … 228 361 // of the old vector, use the fitted polynomial to determine the 229 362 // interpolated value at that point, and set the new vector. 230 for ( i=0;i<n;i++) {363 for (psS32 i=0;i<n;i++) { 231 364 x = ((psF32) i) * ((psF32) overscanVector->n) / ((psF32) n); 232 365 newVec->data.F32[i] = psPolynomial1DEval(myPoly, x); 233 366 } 234 367 } else if (fit == PM_FIT_SPLINE) { 235 psS32 mustFreeSpline = 0;236 // Fit a spline to the old overscan vector.237 mySpline = (psSpline1D *) fitSpec;238 // XXX: Does it make any sense to have a psSpline argument?239 if (mySpline == NULL) {240 mustFreeSpline = 1;241 }242 243 368 // 244 369 // NOTE: Since the X arg in the psVectorFitSpline1D() function is NULL, … … 246 371 // properly when doing the spline eval. 247 372 // 248 // mySpline = psVectorFitSpline1D(mySpline, NULL, overscanVector, NULL); 249 mySpline = psVectorFitSpline1D(NULL, overscanVector); 373 psSpline1D *mySpline = psVectorFitSpline1D(NULL, overscanVector); 250 374 if (mySpline == NULL) { 251 psError(PS_ERR_UNKNOWN, false, " ScaleOverscanVector()(2):Could not fit a spline to the psVector.\n");375 psError(PS_ERR_UNKNOWN, false, "Could not fit a spline to the psVector.\n"); 252 376 return(NULL); 253 377 } 254 // PS_PRINT_SPLINE(mySpline);255 378 256 379 // For each element of the new vector, convert the x-ordinate to that 257 // of the old vector, use the fitted polynomialto determine the380 // of the old vector, use the fitted spline to determine the 258 381 // interpolated value at that point, and set the new vector. 259 for ( i=0;i<n;i++) {382 for (psS32 i=0;i<n;i++) { 260 383 // Scale to [0 : overscanVector->n - 1] 261 384 x = ((psF32) i) * ((psF32) (overscanVector->n-1)) / ((psF32) n); 262 385 newVec->data.F32[i] = psSpline1DEval(mySpline, x); 263 386 } 264 if (mustFreeSpline ==1) { 265 psFree(mySpline); 266 } 267 // PS_VECTOR_PRINT_F32(newVec); 268 269 387 388 psSpline1D *ptrSpline = (psSpline1D *) fitSpec; 389 if (ptrSpline != NULL) { 390 // Copy the resulting spline fit into ptrSpline. 391 PS_ASSERT_SPLINE(ptrSpline, NULL); 392 SplineCopy(ptrSpline, mySpline); 393 } 394 psFree(mySpline); 270 395 } else { 271 396 psError(PS_ERR_UNKNOWN, true, "unknown fit type. Returning NULL.\n"); … … 280 405 281 406 /****************************************************************************** 282 XXX: The SDRS does not specify type support. F32 is implemented here. 407 *****************************************************************************/ 408 static psS32 GetOverscanSize( 409 psImage *inImg, 410 pmOverscanAxis overScanAxis) 411 { 412 if (overScanAxis == PM_OVERSCAN_ROWS) { 413 return(inImg->numCols); 414 } else if (overScanAxis == PM_OVERSCAN_COLUMNS) { 415 return(inImg->numRows); 416 } else if (overScanAxis == PM_OVERSCAN_ALL) { 417 return(1); 418 } 419 return(0); 420 } 421 422 /****************************************************************************** 423 GetOverscanAxis(in) this private routine determines the appropiate overscan 424 axis from the parent cell metadata. 425 426 XXX: Verify the READDIR corresponds with my overscan axis. 427 *****************************************************************************/ 428 static pmOverscanAxis GetOverscanAxis(pmReadout *in) 429 { 430 psBool rc; 431 if ((in->parent != NULL) && (in->parent->concepts)) { 432 psS32 dir = psMetadataLookupS32(&rc, in->parent->concepts, "CELL.READDIR"); 433 if (rc == true) { 434 if (dir == 1) { 435 return(PM_OVERSCAN_ROWS); 436 } else if (dir == 2) { 437 return(PM_OVERSCAN_COLUMNS); 438 } else if (dir == 3) { 439 return(PM_OVERSCAN_ALL); 440 } 441 } 442 } 443 444 psLogMsg(__func__, PS_LOG_WARN, 445 "WARNING: pmSubtractBias.(): could not determine CELL.READDIR from in->parent metadata. Setting overscan axis to PM_OVERSCAN_NONE.\n"); 446 return(PM_OVERSCAN_NONE); 447 } 448 449 /****************************************************************************** 450 psListLength(list): determine the length of a psList. 451 452 XXX: Put this elsewhere. 453 *****************************************************************************/ 454 static psS32 psListLength( 455 psList *list) 456 { 457 psS32 length = 0; 458 psListElem *tmpElem = (psListElem *) list->head; 459 while (NULL != tmpElem) { 460 tmpElem = tmpElem->next; 461 length++; 462 } 463 return(length); 464 } 465 466 /****************************************************************************** 467 Note: this isn't needed anymore as of psModule SDRS 12-09. 468 *****************************************************************************/ 469 static psBool OverscanReducePixel( 470 psImage *in, 471 psList *bias, 472 psStats *myStats) 473 { 474 PS_ASSERT_PTR_NON_NULL(in, NULL); 475 PS_ASSERT_PTR_NON_NULL(bias, NULL); 476 PS_ASSERT_PTR_NON_NULL(bias->head, NULL); 477 PS_ASSERT_PTR_NON_NULL(myStats, NULL); 478 479 // Allocate a psVector with one element per overscan image. 480 psS32 numOverscanImages = psListLength(bias); 481 psVector *statsAll = psVectorAlloc(numOverscanImages, PS_TYPE_F32); 482 psListElem *tmpOverscan = (psListElem *) bias->head; 483 psS32 i = 0; 484 psF64 statValue; 485 // 486 // We loop through each overscan image, calculating the specified 487 // statistic on that image. 488 // 489 while (NULL != tmpOverscan) { 490 psImage *myOverscanImage = (psImage *) tmpOverscan->data; 491 492 PS_ASSERT_IMAGE_TYPE(myOverscanImage, PS_TYPE_F32, NULL); 493 myStats = psImageStats(myStats, myOverscanImage, NULL, (psMaskType)0xffffffff); 494 if (myStats == NULL) { 495 psError(PS_ERR_UNKNOWN, false, "psImageStats(): could not perform requested statistical operation. Returning in image.\n"); 496 psFree(statsAll); 497 return(false); 498 } 499 if (false == p_psGetStatValue(myStats, &statValue)) { 500 psError(PS_ERR_UNKNOWN, false, "p_psGetStatValue(): could not determine result from requested statistical operation. Returning in image.\n"); 501 psFree(statsAll); 502 return(false); 503 } 504 statsAll->data.F32[i] = statValue; 505 i++; 506 tmpOverscan = tmpOverscan->next; 507 } 508 509 // 510 // We reduce the individual stats for each overscan image to 511 // a single psF32. 512 // 513 myStats = psVectorStats(myStats, statsAll, NULL, NULL, 0); 514 if (myStats == NULL) { 515 psError(PS_ERR_UNKNOWN, false, "psImageStats(): could not perform requested statistical operation. Returning in image.\n"); 516 psFree(statsAll); 517 return(false); 518 } 519 if (false == p_psGetStatValue(myStats, &statValue)) { 520 psError(PS_ERR_UNKNOWN, false, "p_psGetStatValue(): could not determine result from requested statistical operation. Returning in image.\n"); 521 psFree(statsAll); 522 return(false); 523 } 524 525 // 526 // Subtract the result and return. 527 // 528 ImageSubtractScalar(in, statValue); 529 psFree(statsAll); 530 return(in); 531 } 532 533 /****************************************************************************** 534 ReduceOverscanImageToCol(overscanImage, myStats): This private routine reduces 535 a single psImage to a column by combining all pixels from each row into a 536 single pixel via requested statistic in myStats. 537 *****************************************************************************/ 538 static psVector *ReduceOverscanImageToCol( 539 psImage *overscanImage, 540 psStats *myStats) 541 { 542 psF64 statValue; 543 psVector *tmpRow = psVectorAlloc(overscanImage->numCols, PS_TYPE_F32); 544 psVector *tmpCol = psVectorAlloc(overscanImage->numRows, PS_TYPE_F32); 545 546 // 547 // For each row, we store all pixels in that row into a temporary psVector, 548 // then we run psVectorStats() on that vector. 549 // 550 for (psS32 i=0;i<overscanImage->numRows;i++) { 551 for (psS32 j=0;j<overscanImage->numCols;j++) { 552 tmpRow->data.F32[j] = overscanImage->data.F32[i][j]; 553 } 554 555 psStats *rc = psVectorStats(myStats, tmpRow, NULL, NULL, 0); 556 if (rc == NULL) { 557 psError(PS_ERR_UNKNOWN, true, "psVectorStats() could not perform requested statistical operation. Returning in image.\n"); 558 return(NULL); 559 } 560 561 if (false == p_psGetStatValue(rc, &statValue)) { 562 psError(PS_ERR_UNKNOWN, true, "p_psGetStatValue() could not determine result from requested statistical operation. Returning in image.\n"); 563 return(NULL); 564 } 565 566 tmpCol->data.F32[i] = (psF32) statValue; 567 } 568 psFree(tmpRow); 569 570 return(tmpCol); 571 } 572 573 /****************************************************************************** 574 ReduceOverscanImageToCol(overscanImage, myStats): This private routine reduces 575 a single psImage to a row by combining all pixels from each column into a 576 single pixel via requested statistic in myStats. 577 *****************************************************************************/ 578 static psVector *ReduceOverscanImageToRow( 579 psImage *overscanImage, 580 psStats *myStats) 581 { 582 psF64 statValue; 583 psVector *tmpRow = psVectorAlloc(overscanImage->numCols, PS_TYPE_F32); 584 psVector *tmpCol = psVectorAlloc(overscanImage->numRows, PS_TYPE_F32); 585 586 // 587 // For each column, we store all pixels in that column into a temporary psVector, 588 // then we run psVectorStats() on that vector. 589 // 590 for (psS32 i=0;i<overscanImage->numCols;i++) { 591 for (psS32 j=0;j<overscanImage->numRows;j++) { 592 tmpCol->data.F32[j] = overscanImage->data.F32[j][i]; 593 } 594 595 psStats *rc = psVectorStats(myStats, tmpCol, NULL, NULL, 0); 596 if (rc == NULL) { 597 psError(PS_ERR_UNKNOWN, true, "psVectorStats() could not perform requested statistical operation. Returning in image.\n"); 598 return(NULL); 599 } 600 601 if (false == p_psGetStatValue(rc, &statValue)) { 602 psError(PS_ERR_UNKNOWN, true, "p_psGetStatValue() could not determine result from requested statistical operation. Returning in image.\n"); 603 return(NULL); 604 } 605 606 tmpRow->data.F32[i] = (psF32) statValue; 607 } 608 psFree(tmpCol); 609 610 return(tmpRow); 611 } 612 613 /****************************************************************************** 614 OverscanReduce(vecSize, bias, myStats): This private routine takes a psList of 615 overscan images (in bias) and reduces them to a single psVector via the 616 specified psStats struct. The vector is then scaled to the length or the 617 row/column in inImg. 618 *****************************************************************************/ 619 static psVector* OverscanReduce( 620 psImage *inImg, 621 pmOverscanAxis overScanAxis, 622 psList *bias, 623 void *fitSpec, 624 pmFit fit, 625 psStats *myStats) 626 { 627 if ((overScanAxis != PM_OVERSCAN_ROWS) && (overScanAxis != PM_OVERSCAN_COLUMNS)) { 628 psError(PS_ERR_UNKNOWN, true, "overScanAxis must be PM_OVERSCAN_ROWS or PM_OVERSCAN_COLUMNS\n"); 629 return(NULL); 630 } 631 PS_ASSERT_PTR_NON_NULL(inImg, NULL); 632 PS_ASSERT_PTR_NON_NULL(bias, NULL); 633 PS_ASSERT_PTR_NON_NULL(bias->head, NULL); 634 PS_ASSERT_PTR_NON_NULL(myStats, NULL); 635 // 636 // Allocate a psVector for the output of this routine. 637 // 638 psS32 vecSize = GetOverscanSize(inImg, overScanAxis); 639 psVector *overscanVector = psVectorAlloc(vecSize, PS_TYPE_F32); 640 641 // 642 // Allocate an array of psVectors with one psVector per element of the 643 // final oversan column vector. These psVectors will be used with 644 // psStats to reduce the multiple elements from each overscan column 645 // vector to a single final column vector. 646 // 647 psS32 numOverscanImages = psListLength(bias); 648 psVector **overscanVectors = (psVector **) psAlloc(numOverscanImages * sizeof(psVector *)); 649 for (psS32 i = 0 ; i < numOverscanImages ; i++) { 650 overscanVectors[i] = NULL; 651 } 652 653 // 654 // We iterate through the list of overscan images. For each image, 655 // we reduce it to a single column or row. Save the overscan vector 656 // in overscanVectors[]. 657 // 658 psListElem *tmpOverscan = (psListElem *) bias->head; 659 psS32 overscanID = 0; 660 while (tmpOverscan != NULL) { 661 psImage *tmpOverscanImage = (psImage *) tmpOverscan->data; 662 if (overScanAxis == PM_OVERSCAN_ROWS) { 663 overscanVectors[overscanID] = ReduceOverscanImageToRow(tmpOverscanImage, myStats); 664 } else if (overScanAxis == PM_OVERSCAN_COLUMNS) { 665 overscanVectors[overscanID] = ReduceOverscanImageToCol(tmpOverscanImage, myStats); 666 } 667 668 tmpOverscan = tmpOverscan->next; 669 overscanID++; 670 } 671 672 // 673 // For each overscan vector, if necessary, we scale that column or 674 // row to vecSize. Note: we should have already ensured that the 675 // fit is poly or spline. 676 // 677 for (psS32 i = 0 ; i < numOverscanImages ; i++) { 678 psVector *tmpOverscanVector = overscanVectors[i]; 679 680 if (tmpOverscanVector->n != vecSize) { 681 overscanVectors[i] = ScaleOverscanVector(tmpOverscanVector, vecSize, fitSpec, fit); 682 if (overscanVectors[i] == NULL) { 683 psError(PS_ERR_UNKNOWN, false, "ScaleOverscanVector(): could not scale the overscan vector.\n"); 684 for (psS32 i = 0 ; i < numOverscanImages ; i++) { 685 psFree(overscanVectors[i]); 686 } 687 psFree(overscanVectors); 688 psFree(tmpOverscanVector); 689 return(NULL); 690 } 691 psFree(tmpOverscanVector); 692 } 693 } 694 695 // 696 // We collect all elements in the overscan vectors for the various 697 // overscan images into a single psVector (tmpVec). Then we call 698 // psStats on that vector to determine the final values for the 699 // overscan vector. 700 // 701 psVector *tmpVec = psVectorAlloc(numOverscanImages, PS_TYPE_F32); 702 psF64 statValue; 703 for (psS32 i = 0 ; i < vecSize ; i++) { 704 // Collect the i-th elements from each overscan vector into a single vector. 705 for (psS32 j = 0 ; j < numOverscanImages ; j++) { 706 tmpVec->data.F32[j] = overscanVectors[j]->data.F32[i]; 707 } 708 709 if (NULL == psVectorStats(myStats, tmpVec, NULL, NULL, 0)) { 710 psError(PS_ERR_UNKNOWN, false, "psVectorStats(): could not perform requested statistical operation. Returning in image.\n"); 711 for (psS32 i = 0 ; i < numOverscanImages ; i++) { 712 psFree(overscanVectors[i]); 713 } 714 psFree(overscanVectors); 715 psFree(tmpVec); 716 return(NULL); 717 } 718 if (false == p_psGetStatValue(myStats, &statValue)) { 719 psError(PS_ERR_UNKNOWN, false, "p_psGetStatValue(): could not determine result from requested statistical operation. Returning in image.\n"); 720 for (psS32 i = 0 ; i < numOverscanImages ; i++) { 721 psFree(overscanVectors[i]); 722 } 723 psFree(overscanVectors); 724 psFree(tmpVec); 725 return(NULL); 726 } 727 728 overscanVector->data.F32[i] = (psF32) statValue; 729 } 730 731 // 732 // We're done. Free the intermediate overscan vectors. 733 // 734 psFree(tmpVec); 735 for (psS32 i = 0 ; i < numOverscanImages ; i++) { 736 psFree(overscanVectors[i]); 737 } 738 psFree(overscanVectors); 739 740 // 741 // Return the computed overscanVector 742 // 743 return(overscanVector); 744 } 745 746 /****************************************************************************** 747 RebinOverscanVector(overscanVector, nBinOrig, myStats): this private routine 748 takes groups of nBinOrig elements in the input vector, combines them into a 749 single pixel via myStats and psVectorStats(), and then outputs a vector of 750 those pixels. 751 *****************************************************************************/ 752 static psS32 RebinOverscanVector( 753 psVector *overscanVector, 754 psS32 nBinOrig, 755 psStats *myStats) 756 { 757 psF64 statValue; 758 psS32 nBin; 759 if ((nBinOrig > 1) && (nBinOrig < overscanVector->n)) { 760 psS32 numBins = 1+((overscanVector->n)/nBinOrig); 761 psVector *myBin = psVectorAlloc(numBins, PS_TYPE_F32); 762 psVector *binVec = psVectorAlloc(nBinOrig, PS_TYPE_F32); 763 764 for (psS32 i=0;i<numBins;i++) { 765 for(psS32 j=0;j<nBinOrig;j++) { 766 if (overscanVector->n > ((i*nBinOrig)+j)) { 767 binVec->data.F32[j] = overscanVector->data.F32[(i*nBinOrig)+j]; 768 } else { 769 // XXX: we get here if nBinOrig does not evenly divide 770 // the overscanVector vector. This is the last bin. Should 771 // we change the binVec->n to acknowledge that? 772 binVec->n = j; 773 } 774 } 775 psStats *rc = psVectorStats(myStats, binVec, NULL, NULL, 0); 776 if (rc == NULL) { 777 psError(PS_ERR_UNKNOWN, false, "psVectorStats(): could not perform requested statistical operation. Returning in image.\n"); 778 return(-1); 779 } 780 if (false == p_psGetStatValue(rc, &statValue)) { 781 psError(PS_ERR_UNKNOWN, false, "p_psGetStatValue(): could not determine result from requested statistical operation. Returning in image.\n"); 782 return(-1); 783 } 784 myBin->data.F32[i] = statValue; 785 } 786 787 // Change the effective size of overscanVector. 788 overscanVector->n = numBins; 789 for (psS32 i=0;i<numBins;i++) { 790 overscanVector->data.F32[i] = myBin->data.F32[i]; 791 } 792 psFree(binVec); 793 psFree(myBin); 794 nBin = nBinOrig; 795 } else { 796 nBin = 1; 797 } 798 799 return(nBin); 800 } 801 802 /****************************************************************************** 803 FitOverscanVectorAndUnbin(inImg, overscanVector, overScanAxis, fitSpec, fit, 804 nBin): this private routine fits a psPolynomial or psSpline to the overscan 805 vector. It then creates a new vector, with a size determined by the input 806 image, evaluates the psPolynomial or psSpline at each element in that vector, 807 then returns that vector. 808 *****************************************************************************/ 809 static psVector *FitOverscanVectorAndUnbin( 810 psImage *inImg, 811 psVector *overscanVector, 812 pmOverscanAxis overScanAxis, 813 void *fitSpec, 814 pmFit fit, 815 psS32 nBin) 816 { 817 psPolynomial1D* myPoly = NULL; 818 psSpline1D *mySpline = NULL; 819 // 820 // Fit a polynomial or spline to the overscan vector. 821 // 822 if (fit == PM_FIT_POLYNOMIAL) { 823 myPoly = (psPolynomial1D *) fitSpec; 824 PS_ASSERT_POLY_NON_NULL(myPoly, NULL); 825 PS_ASSERT_POLY1D(myPoly, NULL); 826 myPoly = psVectorFitPolynomial1D(myPoly, NULL, 0, overscanVector, NULL, NULL); 827 if (myPoly == NULL) { 828 psError(PS_ERR_UNKNOWN, false, "Could not fit a polynomial to overscan vector. Returning NULL.\n"); 829 return(NULL); 830 } 831 } else if (fit == PM_FIT_SPLINE) { 832 mySpline = psVectorFitSpline1D(NULL, overscanVector); 833 if (mySpline == NULL) { 834 psError(PS_ERR_UNKNOWN, false, "Could not fit a spline to overscan vector. Returning NULL.\n"); 835 return(NULL); 836 } 837 if (fitSpec != NULL) { 838 // Copy the resulting spline fit into fitSpec. 839 psSpline1D *ptrSpline = (psSpline1D *) fitSpec; 840 PS_ASSERT_SPLINE(ptrSpline, NULL); 841 SplineCopy(ptrSpline, mySpline); 842 } 843 } 844 845 // 846 // Evaluate the poly/spline at each pixel in the overscan row/column. 847 // 848 psS32 vecSize = GetOverscanSize(inImg, overScanAxis); 849 psVector *newVec = psVectorAlloc(vecSize, PS_TYPE_F32); 850 if ((nBin > 1) && (nBin < overscanVector->n)) { 851 for (psS32 i = 0 ; i < vecSize ; i++) { 852 if (fit == PM_FIT_POLYNOMIAL) { 853 newVec->data.F32[i] = psPolynomial1DEval(myPoly, ((psF32) i) / ((psF32) nBin)); 854 } else if (fit == PM_FIT_SPLINE) { 855 newVec->data.F32[i] = psSpline1DEval(mySpline, ((psF32) i) / ((psF32) nBin)); 856 } 857 } 858 } else { 859 for (psS32 i = 0 ; i < vecSize ; i++) { 860 if (fit == PM_FIT_POLYNOMIAL) { 861 newVec->data.F32[i] = psPolynomial1DEval(myPoly, (psF32) i); 862 } else if (fit == PM_FIT_SPLINE) { 863 newVec->data.F32[i] = psSpline1DEval(mySpline, (psF32) i); 864 } 865 } 866 } 867 868 psFree(mySpline); 869 psFree(overscanVector); 870 return(newVec); 871 } 872 873 874 875 /****************************************************************************** 876 UnbinOverscanVector(inImg, overscanVector, overScanAxis, nBin): this private 877 routine takes a psVector overscanVector that was previously binned by a factor 878 of nBin, and then expands it to its original size, duplicated elements nBin 879 times for each element in the input vector overscanVector. 880 *****************************************************************************/ 881 static psVector *UnbinOverscanVector( 882 psImage *inImg, 883 psVector *overscanVector, 884 pmOverscanAxis overScanAxis, 885 psS32 nBin) 886 { 887 psS32 vecSize; 888 889 if (overScanAxis == PM_OVERSCAN_ROWS) { 890 vecSize = inImg->numCols; 891 } else if (overScanAxis == PM_OVERSCAN_COLUMNS) { 892 vecSize = inImg->numRows; 893 } 894 895 psVector *newVec = psVectorAlloc(vecSize, PS_TYPE_F32); 896 for (psS32 i = 0 ; i < vecSize ; i++) { 897 newVec->data.F32[i] = overscanVector->data.F32[i/nBin]; 898 } 899 900 psFree(overscanVector); 901 return(newVec); 902 } 903 904 905 /****************************************************************************** 906 SubtractVectorFromImage(inImg, overscanVector, overScanAxis): this private 907 routine subtracts the overscanVector column-wise or row-wise from inImg. 908 *****************************************************************************/ 909 static psImage *SubtractVectorFromImage( 910 psImage *inImg, 911 psVector *overscanVector, 912 pmOverscanAxis overScanAxis) 913 { 914 // 915 // Subtract overscan vector row-wise from the image. 916 // 917 if (overScanAxis == PM_OVERSCAN_ROWS) { 918 for (psS32 i=0;i<inImg->numCols;i++) { 919 for (psS32 j=0;j<inImg->numRows;j++) { 920 inImg->data.F32[j][i]-= overscanVector->data.F32[i]; 921 } 922 } 923 } 924 925 // 926 // Subtract overscan vector column-wise from the image. 927 // 928 if (overScanAxis == PM_OVERSCAN_COLUMNS) { 929 for (psS32 i=0;i<inImg->numRows;i++) { 930 for (psS32 j=0;j<inImg->numCols;j++) { 931 inImg->data.F32[i][j]-= overscanVector->data.F32[i]; 932 } 933 } 934 } 935 936 return(inImg); 937 } 938 939 940 941 typedef enum { 942 PM_ERROR_NO_SUBTRACTION, 943 PM_WARNING_NO_SUBTRACTION, 944 PM_ERROR_NO_BIAS_SUBTRACT, 945 PM_WARNING_NO_BIAS_SUBTRACT, 946 PM_ERROR_NO_DARK_SUBTRACT, 947 PM_WARNING_NO_DARK_SUBTRACT, 948 PM_OKAY 949 } pmSubtractBiasAssertStatus; 950 /****************************************************************************** 951 AssertCodeOverscan(....) this private routine verifies that the various input 952 parameters to pmSubtractBias() are correct for overscan subtraction. 953 *****************************************************************************/ 954 pmSubtractBiasAssertStatus AssertCodeOverscan( 955 pmReadout *in, 956 void *fitSpec, 957 pmFit fit, 958 bool overscan, 959 psStats *stat, 960 int nBinOrig, 961 const pmReadout *bias, 962 const pmReadout *dark) 963 { 964 965 PS_ASSERT_READOUT_NON_NULL(in, PM_ERROR_NO_SUBTRACTION); 966 PS_ASSERT_READOUT_NON_EMPTY(in, PM_ERROR_NO_SUBTRACTION); 967 PS_ASSERT_READOUT_TYPE(in, PS_TYPE_F32, PM_ERROR_NO_SUBTRACTION); 968 PS_WARN_PTR_NON_NULL(in->parent); 969 if (in->parent != NULL) { 970 PS_WARN_PTR_NON_NULL(in->parent->concepts); 971 } 972 973 if (overscan == true) { 974 pmOverscanAxis overScanAxis = GetOverscanAxis(in); 975 PS_ASSERT_PTR_NON_NULL(stat, PM_ERROR_NO_SUBTRACTION); 976 PS_ASSERT_PTR_NON_NULL(in->bias, PM_ERROR_NO_SUBTRACTION); 977 PS_ASSERT_PTR_NON_NULL(in->bias->head, PM_ERROR_NO_SUBTRACTION); 978 // 979 // Check the type, size of each bias image. 980 // 981 psListElem *tmpOverscan = (psListElem *) in->bias->head; 982 psS32 numOverscans = 0; 983 while (NULL != tmpOverscan) { 984 numOverscans++; 985 psImage *myOverscanImage = (psImage *) tmpOverscan->data; 986 PS_ASSERT_IMAGE_TYPE(myOverscanImage, PS_TYPE_F32, PM_ERROR_NO_SUBTRACTION); 987 // XXX: Get this right with the rows and columns. 988 if (overScanAxis == PM_OVERSCAN_ROWS) { 989 if (myOverscanImage->numRows != in->image->numRows) { 990 psLogMsg(__func__, PS_LOG_WARN, 991 "WARNING: pmSubtractBias.(): overscan image (# %d) has %d rows, input image has %d rows\n", 992 numOverscans, myOverscanImage->numCols, in->image->numRows); 993 if (fit == PM_FIT_NONE) { 994 psError(PS_ERR_UNKNOWN, true, "Don't know how to scale the overscan vectors. Set fit to PM_FIT_POLYNOMIAL or PM_FIT_SPLINE.\n"); 995 return(PM_ERROR_NO_SUBTRACTION); 996 } 997 } 998 } else if (overScanAxis == PM_OVERSCAN_COLUMNS) { 999 if (myOverscanImage->numCols != in->image->numCols) { 1000 psLogMsg(__func__, PS_LOG_WARN, 1001 "WARNING: pmSubtractBias.(): overscan image (# %d) has %d columns, input image has %d columns\n", 1002 numOverscans, myOverscanImage->numCols, in->image->numCols); 1003 if (fit == PM_FIT_NONE) { 1004 psError(PS_ERR_UNKNOWN, true, "Don't know how to scale the overscan vectors. Set fit to PM_FIT_POLYNOMIAL or PM_FIT_SPLINE.\n"); 1005 return(PM_ERROR_NO_SUBTRACTION); 1006 } 1007 } 1008 } else if (overScanAxis != PM_OVERSCAN_ALL) { 1009 psError(PS_ERR_UNKNOWN, true, "Must specify and overscan axis.\n"); 1010 return(PM_ERROR_NO_SUBTRACTION); 1011 } 1012 tmpOverscan = tmpOverscan->next; 1013 } 1014 } else { 1015 if (fit != PM_FIT_NONE) { 1016 psLogMsg(__func__, PS_LOG_WARN, 1017 "WARNING: pmSubtractBias.(): overscan is FALSE and fit is not PM_FIT_NONE.\n"); 1018 return(PM_WARNING_NO_SUBTRACTION); 1019 } 1020 } 1021 1022 // XXX: I do not like the following spec since it's useless to specify 1023 // a psSpline as the fitSpec. 1024 if (0) { 1025 if ((fitSpec == NULL) && 1026 ((fit != PM_FIT_NONE) || (overscan == true))) { 1027 psError(PS_ERR_UNKNOWN, true, "fitSpec is NULL and fit is not PM_FIT_NONE or overscan is TRUE.\n"); 1028 return(PM_ERROR_NO_SUBTRACTION); 1029 } 1030 } 1031 1032 return(PM_OKAY); 1033 } 1034 1035 /****************************************************************************** 1036 AssertCodeBias(....) this private routine verifies that the various input 1037 parameters to pmSubtractBias() are correct for bias subtraction. 1038 *****************************************************************************/ 1039 static pmSubtractBiasAssertStatus AssertCodeBias( 1040 pmReadout *in, 1041 void *fitSpec, 1042 pmFit fit, 1043 bool overscan, 1044 psStats *stat, 1045 int nBinOrig, 1046 const pmReadout *bias, 1047 const pmReadout *dark) 1048 { 1049 if ((in->image->numRows + in->row0 - bias->row0) > bias->image->numRows) { 1050 psError(PS_ERR_UNKNOWN,true, "bias image does not have enough rows. Returning in image\n"); 1051 return(PM_ERROR_NO_BIAS_SUBTRACT); 1052 } 1053 if ((in->image->numCols + in->col0 - bias->col0) > bias->image->numCols) { 1054 psError(PS_ERR_UNKNOWN,true, "bias image does not have enough columns. Returning in image\n"); 1055 return(PM_ERROR_NO_BIAS_SUBTRACT); 1056 } 1057 1058 if (bias != NULL) { 1059 PS_ASSERT_READOUT_NON_EMPTY(bias, PM_ERROR_NO_BIAS_SUBTRACT); 1060 PS_ASSERT_READOUT_TYPE(bias, PS_TYPE_F32, PM_ERROR_NO_DARK_SUBTRACT); 1061 } 1062 return(PM_OKAY); 1063 } 1064 1065 /****************************************************************************** 1066 AssertCodeDark(....) this private routine verifies that the various input 1067 parameters to pmSubtractBias() are correct for dark subtraction. 1068 *****************************************************************************/ 1069 pmSubtractBiasAssertStatus AssertCodeDark( 1070 pmReadout *in, 1071 void *fitSpec, 1072 pmFit fit, 1073 bool overscan, 1074 psStats *stat, 1075 int nBinOrig, 1076 const pmReadout *bias, 1077 const pmReadout *dark) 1078 { 1079 if ((in->image->numRows + in->row0 - dark->row0) > dark->image->numRows) { 1080 psError(PS_ERR_UNKNOWN, true, "dark image does not have enough rows. Returning in image\n"); 1081 return(PM_ERROR_NO_DARK_SUBTRACT); 1082 } 1083 if ((in->image->numCols + in->col0 - dark->col0) > dark->image->numCols) { 1084 psError(PS_ERR_UNKNOWN, true, "dark image does not have enough columns. Returning in image\n"); 1085 return(PM_ERROR_NO_DARK_SUBTRACT); 1086 } 1087 1088 if (dark != NULL) { 1089 PS_ASSERT_READOUT_NON_EMPTY(dark, PM_ERROR_NO_DARK_SUBTRACT); 1090 PS_ASSERT_READOUT_TYPE(dark, PS_TYPE_F32, PM_ERROR_NO_DARK_SUBTRACT); 1091 } 1092 return(PM_OKAY); 1093 } 1094 1095 /****************************************************************************** 1096 p_psDetermineTrimmedImage(): global routine: determines the region of the 1097 input pmReadout which will be operated on by the various detrend modules. It 1098 does a metadata fetch on "CELL.TRIMSEC" for the parent cell of the pmReadout. 1099 1100 Use it this way: 1101 PS_WARN_PTR_NON_NULL(in->parent); 1102 if (in->parent != NULL) { 1103 PS_WARN_PTR_NON_NULL(in->parent->concepts); 1104 } 1105 // 1106 // Determine trimmed image from metadata. 1107 // 1108 psImage *trimmedImg = p_psDetermineTrimmedImage(in); 1109 1110 XXX: Create a pmUtils.c file and put this routine there. 1111 *****************************************************************************/ 1112 psImage *p_psDetermineTrimmedImage(pmReadout *in) 1113 { 1114 if ((in->parent == NULL) || (in->parent->concepts == NULL)) { 1115 psLogMsg(__func__, PS_LOG_WARN, 1116 "WARNING: could not determine CELL.TRIMSEC from parent cell Metadata (NULL).\n"); 1117 return(in->image); 1118 } 1119 1120 psBool rc = false; 1121 psImage *trimmedImg = NULL; 1122 psRegion *trimRegion = psMetadataLookupPtr(&rc, in->parent->concepts, 1123 "CELL.TRIMSEC"); 1124 if (rc == false) { 1125 psLogMsg(__func__, PS_LOG_WARN, 1126 "WARNING: could not determine CELL.TRIMSEC from parent cell Metadata.\n"); 1127 trimmedImg = in->image; 1128 } else { 1129 trimmedImg = psImageSubset(in->image, *trimRegion); 1130 } 1131 1132 return(trimmedImg); 1133 } 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 /****************************************************************************** 1153 pmSubtractBias(....): see SDRS for complete specification. 1154 1155 XXX: Code and assert type support: U16, S32, F32. 1156 XXX: Add trace messages. 283 1157 *****************************************************************************/ 284 1158 pmReadout *pmSubtractBias( … … 290 1164 int nBin, 291 1165 const pmReadout *bias, 292 const pmReadout *dark 293 ) 1166 const pmReadout *dark) 294 1167 { 295 1168 psTrace(".psModule.pmSubtracBias.pmSubtractBias", 4, 296 1169 "---- pmSubtractBias() begin ----\n"); 297 PS_ASSERT_READOUT_NON_NULL(in, NULL); 298 PS_ASSERT_READOUT_NON_EMPTY(in, NULL); 299 PS_ASSERT_READOUT_TYPE(in, PS_TYPE_F32, NULL); 300 301 // 302 // If the overscans != NULL, then check the type of each image. 303 // 304 if (overscans != NULL) { 305 psListElem *tmpOverscan = (psListElem *) overscans->head; 306 while (NULL != tmpOverscan) { 307 psImage *myOverscanImage = (psImage *) tmpOverscan->data; 308 PS_ASSERT_IMAGE_TYPE(myOverscanImage, PS_TYPE_F32, NULL); 309 tmpOverscan = tmpOverscan->next; 310 } 311 } 312 313 if ((overscans == NULL) && (overScanAxis != PM_OVERSCAN_NONE)) { 314 psError(PS_ERR_UNKNOWN,true, "(overscans == NULL) && (overScanAxis != PM_OVERSCAN_NONE). Returning in image\n"); 1170 // 1171 // Check input parameters, generate warnings and errors. 1172 // 1173 if (PM_OKAY != AssertCodeOverscan(in, fitSpec, fit, overscan, stat, nBin, bias, dark)) { 315 1174 return(in); 316 1175 } 317 318 // Check for an unallowable pmFit. 319 if ((fit != PM_OVERSCAN_NONE) && 320 (fit != PM_OVERSCAN_ROWS) && 321 (fit != PM_OVERSCAN_COLUMNS) && 322 (fit != PM_OVERSCAN_ALL)) { 323 psError(PS_ERR_UNKNOWN, true, "fit is unallowable (%d). Returning in image.\n", fit); 324 return(in); 325 } 326 // Check for an unallowable pmOverscanAxis. 327 if ((overScanAxis != PM_OVERSCAN_NONE) && 328 (overScanAxis != PM_OVERSCAN_ROWS) && 329 (overScanAxis != PM_OVERSCAN_COLUMNS) && 330 (overScanAxis != PM_OVERSCAN_ALL)) { 331 psError(PS_ERR_UNKNOWN, true, "overScanAxis is unallowable (%d). Returning in image.\n", overScanAxis); 332 return(in); 333 } 334 psS32 i; 335 psS32 j; 336 psS32 numBins = 0; 337 static psVector *overscanVector = NULL; 338 psVector *tmpRow = NULL; 339 psVector *tmpCol = NULL; 340 psVector *myBin = NULL; 341 psVector *binVec = NULL; 342 psListElem *tmpOverscan = NULL; 343 double statValue; 344 psImage *myOverscanImage = NULL; 345 psPolynomial1D *myPoly = NULL; 346 psSpline1D *mySpline = NULL; 347 psS32 nBin; 348 349 // 350 // Create a static stats data structure and determine the highest 351 // priority stats option. 352 // 353 static psStats *myStats = NULL; 354 if (myStats == NULL) { 355 myStats = psStatsAlloc(PS_STAT_SAMPLE_MEAN); 356 p_psMemSetPersistent(myStats, true); 357 } 358 if (stat != NULL) { 359 myStats->options = GenNewStatOptions(stat); 360 } 361 362 363 if (overScanAxis == PM_OVERSCAN_NONE) { 364 if (fit != PM_FIT_NONE) { 365 psLogMsg(__func__, PS_LOG_WARN, 366 "WARNING: pmSubtractBias.(): overScanAxis equals NONE, and fit does not equal NONE. Proceeding to full fram subtraction.\n"); 367 } 368 369 if (overscans != NULL) { 370 psLogMsg(__func__, PS_LOG_WARN, 371 "WARNING: pmSubtractBias.(): overScanAxis equals NONE and overscans does not equal NULL. Proceeding to full fram subtraction.\n"); 372 } 373 return(SubtractFrame(in, bias)); 374 } 375 376 if ((overScanAxis == PM_OVERSCAN_ALL) && (fit != PM_FIT_NONE)) { 377 psLogMsg(__func__, PS_LOG_WARN, 378 "WARNING: pmSubtractBias.(): overScanAxis equals ALL, and fit does not equal NONE. Proceeding with the rest of the module.\n"); 379 } 380 381 382 // 383 // We subtract each overscan region from the image data. 384 // If we get here we know that overscans != NULL. 385 // 386 387 if (overScanAxis == PM_OVERSCAN_ALL) { 388 tmpOverscan = (psListElem *) overscans->head; 389 while (NULL != tmpOverscan) { 390 myOverscanImage = (psImage *) tmpOverscan->data; 391 392 PS_ASSERT_IMAGE_TYPE(myOverscanImage, PS_TYPE_F32, NULL); 393 psStats *rc = psImageStats(myStats, myOverscanImage, NULL, (psMaskType)0xffffffff); 394 if (rc == NULL) { 395 psError(PS_ERR_UNKNOWN, false, "psImageStats(): could not perform requested statistical operation. Returning in image.\n"); 1176 // 1177 // Determine trimmed image from metadata. 1178 // 1179 psImage *trimmedImg = p_psDetermineTrimmedImage(in); 1180 1181 // 1182 // Subtract overscan frames if necessary. 1183 // 1184 if (overscan == true) { 1185 pmOverscanAxis overScanAxis = GetOverscanAxis(in); 1186 1187 // 1188 // Create a psStats data structure and determine the highest 1189 // priority stats option. 1190 // 1191 psStats *myStats = psStatsAlloc(PS_STAT_SAMPLE_MEAN); 1192 if (stat != NULL) { 1193 myStats->options = GenNewStatOptions(stat); 1194 } 1195 1196 // 1197 // Reduce overscan images to a single pixel, then subtract. 1198 // This code is no longer required as of SDRS 12-09. 1199 // 1200 if (overScanAxis == PM_OVERSCAN_ALL) { 1201 if (false == OverscanReducePixel(trimmedImg, in->bias, myStats)) { 396 1202 return(in); 397 1203 } 398 if (false == p_psGetStatValue(myStats, &statValue)) { 399 psError(PS_ERR_UNKNOWN, false, "p_psGetStatValue(): could not determine result from requested statistical operation. Returning in image.\n"); 1204 psFree(myStats); 1205 } else { 1206 // 1207 // Reduce the overscan images to a single overscan vector. 1208 // 1209 psVector *overscanVector = OverscanReduce(in->image, overScanAxis, 1210 in->bias, fitSpec, 1211 fit, myStats); 1212 if (overscanVector == NULL) { 1213 psError(PS_ERR_UNKNOWN, false, "Could not reduce overscan images to a single overscan vector. Returning in image\n"); 1214 psFree(myStats); 400 1215 return(in); 401 1216 } 402 ImageSubtractScalar(in->image, statValue); 403 404 tmpOverscan = tmpOverscan->next; 405 } 406 return(in); 407 } 408 409 // This check is redundant with above code. 410 if (!((overScanAxis == PM_OVERSCAN_ROWS) || (overScanAxis == PM_OVERSCAN_COLUMNS))) { 411 psError(PS_ERR_UNKNOWN, true, "overScanAxis is unallowable (%d).\nReturning in image.\n", overScanAxis); 412 return(in); 413 } 414 415 tmpOverscan = (psListElem *) overscans->head; 416 while (NULL != tmpOverscan) { 417 // PS_IMAGE_PRINT_F32_HIDEF(in->image); 418 myOverscanImage = (psImage *) tmpOverscan->data; 419 420 if (overScanAxis == PM_OVERSCAN_ROWS) { 421 if (myOverscanImage->numCols != (in->image)->numCols) { 422 psLogMsg(__func__, PS_LOG_WARN, 423 "WARNING: pmSubtractBias.(): overscan image has %d columns, input image has %d columns\n", 424 myOverscanImage->numCols, in->image->numCols); 425 } 426 427 // We create a row vector and subtract this vector from image. 428 // XXX: Is there a better way to extract a psVector from a psImage without 429 // having to copy every element in that vector? 430 overscanVector = psVectorAlloc(myOverscanImage->numCols, PS_TYPE_F32); 431 for (i=0;i<overscanVector->n;i++) { 432 overscanVector->data.F32[i] = 0.0; 433 } 434 tmpRow = psVectorAlloc(myOverscanImage->numRows, PS_TYPE_F32); 435 436 // For each column of the input image, loop through every row, 437 // collect the pixel in that row, then performed the specified 438 // statistical op on those pixels. Store this in overscanVector. 439 for (i=0;i<myOverscanImage->numCols;i++) { 440 for (j=0;j<myOverscanImage->numRows;j++) { 441 tmpRow->data.F32[j] = myOverscanImage->data.F32[j][i]; 442 } 443 psStats *rc = psVectorStats(myStats, tmpRow, NULL, NULL, 0); 444 if (rc == NULL) { 445 psError(PS_ERR_UNKNOWN, false, "psVectorStats(): could not perform requested statistical operation. Returning in image.\n"); 1217 1218 // 1219 // Rebin the overscan vector if necessary. 1220 // 1221 psS32 newBin = RebinOverscanVector(overscanVector, nBin, myStats); 1222 if (newBin < 0) { 1223 psError(PS_ERR_UNKNOWN, false, "Could rebin the overscan vector. Returning in image\n"); 1224 psFree(myStats); 1225 return(in); 1226 } 1227 1228 // 1229 // If necessary, fit a psPolynomial or psSpline to the overscan vector. 1230 // Then, unbin the overscan vector to appropriate length for the in image. 1231 // 1232 if ((fit == PM_FIT_POLYNOMIAL) || (fit == PM_FIT_SPLINE)) { 1233 overscanVector = FitOverscanVectorAndUnbin(trimmedImg, overscanVector, overScanAxis, fitSpec, fit, newBin); 1234 if (overscanVector == NULL) { 1235 psError(PS_ERR_UNKNOWN, false, "Could not fit the polynomial or spline to the overscan vector. Returning in image\n"); 1236 psFree(myStats); 446 1237 return(in); 447 1238 } 448 if (false == p_psGetStatValue(rc, &statValue)) { 449 psError(PS_ERR_UNKNOWN, false, "p_psGetStatValue(): could not determine result from requested statistical operation. Returning in image.\n"); 450 return(in); 1239 } else { 1240 overscanVector = UnbinOverscanVector(trimmedImg, overscanVector, overScanAxis, newBin); 1241 } 1242 1243 // 1244 // Subtract the overscan vector from the input image. 1245 // 1246 SubtractVectorFromImage(trimmedImg, overscanVector, overScanAxis); 1247 psFree(myStats); 1248 psFree(overscanVector); 1249 } 1250 } 1251 1252 // 1253 // Perform bias subtraction if necessary. 1254 // 1255 if (bias != NULL) { 1256 if (PM_OKAY == AssertCodeBias(in, fitSpec, fit, overscan, stat, nBin, bias, dark)) { 1257 SubtractFrame(in, bias); 1258 } 1259 } 1260 1261 // 1262 // Perform dark subtraction if necessary. 1263 // 1264 if (dark != NULL) { 1265 if (PM_OKAY == AssertCodeDark(in, fitSpec, fit, overscan, stat, nBin, bias, dark)) { 1266 psBool rc; 1267 psF32 scale = 0.0; 1268 if (in->parent != NULL) { 1269 scale = psMetadataLookupS32(&rc, in->parent->concepts, "CELL.DARKTIME"); 1270 if (rc == false) { 1271 psLogMsg(__func__, PS_LOG_WARN, 1272 "WARNING: pmSubtractBias.(): could not determine CELL.FARKTIME from in->parent metadata.\n"); 451 1273 } 452 overscanVector->data.F32[i] = statValue; 453 } 454 psFree(tmpRow); 455 456 // Scale the overscan vector to the size of the input image. 457 if (overscanVector->n != in->image->numCols) { 458 if ((fit == PM_FIT_POLYNOMIAL) || (fit == PM_FIT_SPLINE)) { 459 psVector *newVec = ScaleOverscanVector(overscanVector, 460 in->image->numCols, 461 fitSpec, fit); 462 if (newVec == NULL) { 463 psError(PS_ERR_UNKNOWN, false, "ScaleOverscanVector(): could not scale the overscan vector. Returning in image.\n"); 464 return(in); 465 } 466 psFree(overscanVector); 467 overscanVector = newVec; 468 } else { 469 psError(PS_ERR_UNKNOWN, true, "Don't know how to scale the overscan vector. Set fit to PM_FIT_SPLINE or PM_FIT_POLYNOMIAL. Returning in image.\n"); 470 psFree(overscanVector); 471 return(in); 472 } 473 } 474 } 475 476 if (overScanAxis == PM_OVERSCAN_COLUMNS) { 477 if (myOverscanImage->numRows != (in->image)->numRows) { 478 psLogMsg(__func__, PS_LOG_WARN, 479 "WARNING: pmSubtractBias.(): overscan image has %d rows, input image has %d rows\n", 480 myOverscanImage->numRows, in->image->numRows); 481 } 482 483 // We create a column vector and subtract this vector from image. 484 overscanVector = psVectorAlloc(myOverscanImage->numRows, PS_TYPE_F32); 485 for (i=0;i<overscanVector->n;i++) { 486 overscanVector->data.F32[i] = 0.0; 487 } 488 tmpCol = psVectorAlloc(myOverscanImage->numCols, PS_TYPE_F32); 489 490 // For each row of the input image, loop through every column, 491 // collect the pixel in that row, then performed the specified 492 // statistical op on those pixels. Store this in overscanVector. 493 for (i=0;i<myOverscanImage->numRows;i++) { 494 for (j=0;j<myOverscanImage->numCols;j++) { 495 tmpCol->data.F32[j] = myOverscanImage->data.F32[i][j]; 496 } 497 psStats *rc = psVectorStats(myStats, tmpCol, NULL, NULL, 0); 498 if (rc == NULL) { 499 psError(PS_ERR_UNKNOWN, false, "psVectorStats(): could not perform requested statistical operation. Returning in image.\n"); 500 return(in); 501 } 502 if (false == p_psGetStatValue(rc, &statValue)) { 503 psError(PS_ERR_UNKNOWN, false, "p_psGetStatValue(): could not determine result from requested statistical operation. Returning in image.\n"); 504 return(in); 505 } 506 overscanVector->data.F32[i] = statValue; 507 } 508 psFree(tmpCol); 509 510 // Scale the overscan vector to the size of the input image. 511 if (overscanVector->n != in->image->numRows) { 512 if ((fit == PM_FIT_POLYNOMIAL) || (fit == PM_FIT_SPLINE)) { 513 psVector *newVec = ScaleOverscanVector(overscanVector, 514 in->image->numRows, 515 fitSpec, fit); 516 if (newVec == NULL) { 517 psError(PS_ERR_UNKNOWN, false, "ScaleOverscanVector(): could not scale the overscan vector. Returning in image.\n"); 518 return(in); 519 } 520 psFree(overscanVector); 521 overscanVector = newVec; 522 } else { 523 psError(PS_ERR_UNKNOWN, true, "Don't know how to scale the overscan vector. Set fit to PM_FIT_SPLINE or PM_FIT_POLYNOMIAL. Returning in image.\n"); 524 psFree(overscanVector); 525 return(in); 526 } 527 } 528 } 529 530 // 531 // Re-bin the overscan vector (change its length). 532 // 533 // Only if nBinOrig > 1. 534 if ((nBinOrig > 1) && (nBinOrig < overscanVector->n)) { 535 numBins = 1+((overscanVector->n)/nBinOrig); 536 myBin = psVectorAlloc(numBins, PS_TYPE_F32); 537 binVec = psVectorAlloc(nBinOrig, PS_TYPE_F32); 538 539 for (i=0;i<numBins;i++) { 540 for(j=0;j<nBinOrig;j++) { 541 if (overscanVector->n > ((i*nBinOrig)+j)) { 542 binVec->data.F32[j] = overscanVector->data.F32[(i*nBinOrig)+j]; 543 } else { 544 // XXX: we get here if nBinOrig does not evenly divide 545 // the overscanVector vector. This is the last bin. Should 546 // we change the binVec->n to acknowledge that? 547 binVec->n = j; 548 } 549 } 550 psStats *rc = psVectorStats(myStats, binVec, NULL, NULL, 0); 551 if (rc == NULL) { 552 psError(PS_ERR_UNKNOWN, false, "psVectorStats(): could not perform requested statistical operation. Returning in image.\n"); 553 return(in); 554 } 555 if (false == p_psGetStatValue(rc, &statValue)) { 556 psError(PS_ERR_UNKNOWN, false, "p_psGetStatValue(): could not determine result from requested statistical operation. Returning in image.\n"); 557 return(in); 558 } 559 myBin->data.F32[i] = statValue; 560 } 561 562 // Change the effective size of overscanVector. 563 overscanVector->n = numBins; 564 for (i=0;i<numBins;i++) { 565 overscanVector->data.F32[i] = myBin->data.F32[i]; 566 } 567 psFree(binVec); 568 psFree(myBin); 569 nBin = nBinOrig; 570 } else { 571 nBin = 1; 572 } 573 574 // At this point the number of data points in overscanVector should be 575 // equal to the number of rows/columns (whatever is appropriate) in the 576 // image divided by numBins. 577 // 578 579 580 // 581 // This doesn't seem right. The only way to do a spline fit is if, 582 // by SDRS requirements, fitSpec is not-NULL> But in order for it 583 // to be non-NULL, someone must have called psSpline1DAlloc() with 584 // the min, max, and number of splines. 585 // 586 if (!((fitSpec == NULL) || (fit == PM_FIT_NONE))) { 587 // 588 // Fit a polynomial or spline to the overscan vector. 589 // 590 if (fit == PM_FIT_POLYNOMIAL) { 591 myPoly = (psPolynomial1D *) fitSpec; 592 myPoly = psVectorFitPolynomial1D(myPoly, NULL, 0, overscanVector, NULL, NULL); 593 if (myPoly == NULL) { 594 psError(PS_ERR_UNKNOWN, false, "(3) Could not fit a polynomial to overscan vector. Returning in image.\n"); 595 psFree(overscanVector); 596 return(in); 597 } 598 } else if (fit == PM_FIT_SPLINE) { 599 // XXX: This makes no sense 600 // XXX: must free mySpline? 601 mySpline = (psSpline1D *) fitSpec; 602 mySpline = psVectorFitSpline1D(NULL, overscanVector); 603 if (mySpline == NULL) { 604 psError(PS_ERR_UNKNOWN, false, "Could not fit a spline to overscan vector. Returning in image.\n"); 605 psFree(overscanVector); 606 return(in); 607 } 608 } 609 610 // 611 // Subtract fitted overscan vector row-wise from the image. 612 // 613 if (overScanAxis == PM_OVERSCAN_ROWS) { 614 for (i=0;i<(in->image)->numCols;i++) { 615 psF32 tmpF32 = 0.0; 616 if (fit == PM_FIT_POLYNOMIAL) { 617 tmpF32 = psPolynomial1DEval(myPoly, ((psF32) i) / ((psF32) nBin)); 618 } else if (fit == PM_FIT_SPLINE) { 619 tmpF32 = psSpline1DEval(mySpline, ((psF32) i) / ((psF32) nBin)); 620 } 621 for (j=0;j<(in->image)->numRows;j++) { 622 (in->image)->data.F32[j][i]-= tmpF32; 623 } 624 } 625 } 626 627 // 628 // Subtract fitted overscan vector column-wise from the image. 629 // 630 if (overScanAxis == PM_OVERSCAN_COLUMNS) { 631 for (i=0;i<(in->image)->numRows;i++) { 632 psF32 tmpF32 = 0.0; 633 if (fit == PM_FIT_POLYNOMIAL) { 634 tmpF32 = psPolynomial1DEval(myPoly, ((psF32) i) / ((psF32) nBin)); 635 } else if (fit == PM_FIT_SPLINE) { 636 tmpF32 = psSpline1DEval(mySpline, ((psF32) i) / ((psF32) nBin)); 637 } 638 639 for (j=0;j<(in->image)->numCols;j++) { 640 (in->image)->data.F32[i][j]-= tmpF32; 641 } 642 } 643 } 644 } else { 645 // 646 // If we get here, then no polynomials were fit to the overscan 647 // vector. We simply subtract it, taking into account binning, 648 // from the image. 649 // 650 651 // 652 // Subtract overscan vector row-wise from the image. 653 // 654 if (overScanAxis == PM_OVERSCAN_ROWS) { 655 for (i=0;i<(in->image)->numCols;i++) { 656 for (j=0;j<(in->image)->numRows;j++) { 657 (in->image)->data.F32[j][i]-= overscanVector->data.F32[i/nBin]; 658 } 659 } 660 } 661 662 // 663 // Subtract overscan vector column-wise from the image. 664 // 665 if (overScanAxis == PM_OVERSCAN_COLUMNS) { 666 for (i=0;i<(in->image)->numRows;i++) { 667 for (j=0;j<(in->image)->numCols;j++) { 668 (in->image)->data.F32[i][j]-= overscanVector->data.F32[i/nBin]; 669 } 670 } 671 } 672 } 673 674 psFree(overscanVector); 675 676 tmpOverscan = tmpOverscan->next; 677 } 678 1274 } 1275 SubtractDarkFrame(in, dark, scale); 1276 } 1277 } 1278 1279 // 1280 // All done. 1281 // 679 1282 psTrace(".psModule.pmSubtracBias.pmSubtractBias", 4, 680 1283 "---- pmSubtractBias() exit ----\n"); 681 682 if (bias != NULL) {683 return(SubtractFrame(in, bias));684 }685 1284 return(in); 686 1285 } -
trunk/psModules/src/imsubtract/pmSubtractBias.h
r5435 r5516 6 6 * @author GLG, MHPCC 7 7 * 8 * @version $Revision: 1. 2$ $Name: not supported by cvs2svn $9 * @date $Date: 2005-1 0-20 23:06:24$8 * @version $Revision: 1.3 $ $Name: not supported by cvs2svn $ 9 * @date $Date: 2005-11-15 20:09:03 $ 10 10 * 11 11 * Copyright 2004 Maui High Performance Computing Center, University of Hawaii … … 47 47 const pmReadout *bias, ///< A possibly NULL bias pmReadout which is to be subtracted 48 48 const pmReadout *dark ///< A possibly NULL bias pmReadout which is to be subtracted 49 ) 49 ); 50 50 // OLD: remove this 51 51 // const psList *overscans, ///< A psList of overscan images 52 52 // pmOverscanAxis overScanAxis, ///< Defines how overscans are applied 53 53 54 /****************************************************************************** 55 DetermineTrimmedImageg() This private routine determines the region of the 56 input pmReadout which will be operated on by the various detrend modules. It 57 does a metadata fetch on "CELL.TRIMSEC" for the parent cell of the pmReadout. 58 59 XXX: Consider making a pmUtils.c file and put this routine there. 60 *****************************************************************************/ 61 psImage *p_psDetermineTrimmedImage( 62 pmReadout *in 63 ); 64 54 65 #endif -
trunk/psModules/src/imsubtract/pmSubtractSky.c
r5294 r5516 6 6 * @author GLG, MHPCC 7 7 * 8 * @version $Revision: 1. 2$ $Name: not supported by cvs2svn $9 * @date $Date: 2005-1 0-12 21:02:04$8 * @version $Revision: 1.3 $ $Name: not supported by cvs2svn $ 9 * @date $Date: 2005-11-15 20:09:03 $ 10 10 * 11 11 * Copyright 2004 Maui High Performance Computing Center, University of Hawaii … … 18 18 #include<math.h> 19 19 #include "pslib.h" 20 #include "psConstants.h"21 20 #include "pmSubtractSky.h" 21 22 // XXX: Get rid of the. Create pmUtils.h 23 psImage *p_psDetermineTrimmedImage( 24 pmReadout *in 25 ); 22 26 23 27 /****************************************************************************** … … 152 156 153 157 XXX: Use your brain and figure out the analytical expression. 158 159 XXX: Why isn't it simply (xOrder+1) * (yOrder+1)? 154 160 *****************************************************************************/ 155 161 static psS32 CalculatePolyTerms(psS32 xOrder, psS32 yOrder) … … 170 176 } 171 177 } 172 173 178 psTrace("SubtractSky.CalculatePolyTerms", 4, 174 179 "Exiting CalculatePolyTerms(%d, %d) -> %d\n", xOrder, yOrder, localPolyTerms); 175 180 return(localPolyTerms); 181 182 // return((xOrder+1) * (yOrder+1)); 176 183 } 177 184 … … 283 290 XXX: Different trace message facilities in use here. 284 291 *****************************************************************************/ 285 static psPolynomial2D *ImageFitPolynomial(psPolynomial2D *myPoly, 286 psImage *dataImage, 287 psImage *maskImage) 292 static psPolynomial2D *ImageFitPolynomial( 293 psPolynomial2D *myPoly, 294 psImage *dataImage, 295 psImage *maskImage) 288 296 { 289 297 psTrace("SubtractSky.ImageFitPolynomial", 4, … … 471 479 PS_ASSERT_READOUT_NON_EMPTY(in, NULL); 472 480 PS_ASSERT_READOUT_TYPE(in, PS_TYPE_F32, NULL); 481 PS_WARN_PTR_NON_NULL(in->parent); 482 if (in->parent != NULL) { 483 PS_WARN_PTR_NON_NULL(in->parent->concepts); 484 } 473 485 psTrace(".psModule.pmSubtractSky", 4, 474 486 "---- pmSubtractSky() begin ----\n"); … … 492 504 return(in); 493 505 } 494 psImage *origImage = in->image; 506 507 // 508 // Determine trimmed image from metadata. 509 // 510 511 psImage *trimmedImg = p_psDetermineTrimmedImage(in); 495 512 psImage *binnedImage = NULL; 496 513 psPolynomial2D *myPoly = NULL; … … 539 556 // No binning is required here. Simply create a copy of the image 540 557 // and a mask. 541 binnedImage = psImageCopy(binnedImage, origImage, PS_TYPE_F32);558 binnedImage = psImageCopy(binnedImage, trimmedImg, PS_TYPE_F32); 542 559 if (binnedImage == NULL) { 543 560 psError(PS_ERR_UNKNOWN, false, "psImageCopy() returned NULL. Returning in image.\n"); … … 559 576 } 560 577 } else { 561 binnedImage = psImageRebin(NULL, origImage, in->mask, 0, binFactor, stats);578 binnedImage = psImageRebin(NULL, trimmedImg, in->mask, 0, binFactor, stats); 562 579 if (binnedImage == NULL) { 563 580 psError(PS_ERR_UNKNOWN, false, "psImageRebin() returned NULL. Returning in image.\n"); … … 677 694 if (binFactor <= 1) { 678 695 // The binned image is the same size as the original image. 679 for (psS32 row = 0; row < origImage->numRows ; row++) {680 for (psS32 col = 0; col < origImage->numCols ; col++) {681 origImage->data.F32[row][col]-= binnedImage->data.F32[row][col];696 for (psS32 row = 0; row < trimmedImg->numRows ; row++) { 697 for (psS32 col = 0; col < trimmedImg->numCols ; col++) { 698 trimmedImg->data.F32[row][col]-= binnedImage->data.F32[row][col]; 682 699 } 683 700 } 684 701 } else { 685 for (psS32 row = 0; row < origImage->numRows ; row++) {686 for (psS32 col = 0; col < origImage->numCols ; col++) {702 for (psS32 row = 0; row < trimmedImg->numRows ; row++) { 703 for (psS32 col = 0; col < trimmedImg->numCols ; col++) { 687 704 // We calculate the F32 value of the pixel coordinates in the 688 705 // binned image and then use a pixel interpolation routine to … … 700 717 binnedImage, binColF64, binRowF64, 701 718 NULL, 0, 0.0, PS_INTERPOLATE_BILINEAR); 702 origImage->data.F32[row][col]-= binPixel;719 trimmedImg->data.F32[row][col]-= binPixel; 703 720 704 721 psTrace(".psModule.pmSubtractSky", 8,
Note:
See TracChangeset
for help on using the changeset viewer.
