Changeset 19140
- Timestamp:
- Aug 20, 2008, 3:12:44 PM (18 years ago)
- Location:
- trunk/psLib/src/imageops
- Files:
-
- 2 edited
-
psImageInterpolate.c (modified) (19 diffs)
-
psImageInterpolate.h (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psLib/src/imageops/psImageInterpolate.c
r19129 r19140 7 7 * @author Paul Price, IfA 8 8 * 9 * @version $Revision: 1.1 7$ $Name: not supported by cvs2svn $10 * @date $Date: 2008-08-2 0 04:06:31$9 * @version $Revision: 1.18 $ $Name: not supported by cvs2svn $ 10 * @date $Date: 2008-08-21 01:12:44 $ 11 11 * 12 12 * Copyright 2004-2007 Institute for Astronomy, University of Hawaii … … 60 60 options->poorMask = poorMask; 61 61 options->poorFrac = poorFrac; 62 options->shifting = true; 62 63 63 64 return options; … … 166 167 static inline void interpolateKernelGenerate(int xNum, int yNum, // Size of interpolation kernel 167 168 double kernel[xNum][yNum], // Kernel, to be set 169 bool *xExact, bool *yExact, // Exact shift? 168 170 int xCentral, int yCentral, // Central pixel of convolution 169 171 float x, float y, // Coordinates of interest 170 psImageInterpolateMode mode // Mode for interpolation 172 psImageInterpolateMode mode, // Mode for interpolation 173 bool allowExact // Allow exact shifts? 171 174 ) 172 175 { 176 double xFrac = x - 0.5 - xCentral; // Fraction of pixel in x 177 double yFrac = y - 0.5 - yCentral; // Fraction of pixel in y 178 *xExact = (allowExact && fabs(xFrac) < DBL_EPSILON); 179 *yExact = (allowExact && fabs(yFrac) < DBL_EPSILON); 180 173 181 switch (mode) { 174 182 case PS_INTERPOLATE_BILINEAR: { 175 double xFrac = x - 0.5 - xCentral; // Fraction of pixel in x176 double yFrac = y - 0.5 - yCentral; // Fraction of pixel in y177 183 kernel[0][0] = (1.0 - xFrac) * (1.0 - yFrac); 178 184 kernel[0][1] = xFrac * (1.0 - yFrac); … … 220 226 psAbort("Invalid interpolation mode."); 221 227 } 222 } 228 return; 229 } 230 231 // Can't interpolate: kernel is off the image 232 #define INTERPOLATE_OFF() { \ 233 *imageValue = options->badImage; \ 234 if (varianceValue) { \ 235 *varianceValue = options->badVariance; \ 236 } \ 237 if (maskValue) { \ 238 *maskValue = options->badMask; \ 239 } \ 240 return PS_INTERPOLATE_STATUS_OFF; \ 241 } 223 242 224 243 // Set up and check interpolation bounds … … 231 250 if (xStart > xLast || xStop < 0 || yStart > yLast || yStop < 0) { \ 232 251 /* Interpolation kernel is entirely off the image */ \ 233 *imageValue = options->badImage; \ 234 if (varianceValue) { \ 235 *varianceValue = options->badVariance; \ 236 } \ 237 if (maskValue) { \ 238 *maskValue = options->badMask; \ 239 } \ 240 return PS_INTERPOLATE_STATUS_OFF; \ 252 INTERPOLATE_OFF(); \ 241 253 } \ 242 254 int xMin, xMax, yMin, yMax; /* Minimum and maximum valid pixels on image */ \ … … 276 288 } 277 289 290 // Refine limits if the interpolation is exact 291 #define INTERPOLATE_EXACT() { \ 292 if (xExact) { \ 293 if (iMin > 0 || iMax < 1) { \ 294 INTERPOLATE_OFF(); /* Returns */ \ 295 } \ 296 iMin = (xNum - 1) / 2; \ 297 iMax = iMin + 1; \ 298 } \ 299 if (yExact) { \ 300 if (jMin > 0 || jMax < 1) { \ 301 INTERPOLATE_OFF(); /* Returns */ \ 302 } \ 303 jMin = (yNum - 1) / 2; \ 304 jMax = jMin + 1; \ 305 } \ 306 if (xExact && yExact) { \ 307 return interpolateFlat(imageValue, varianceValue, maskValue, x, y, options); \ 308 } \ 309 } 310 278 311 // Interpolation engine using interpolation kernel 279 312 static psImageInterpolateStatus interpolateKernel(double *imageValue, double *varianceValue, … … 294 327 295 328 double kernel[yNum][xNum]; // Interpolation kernel for straight interpolation 296 interpolateKernelGenerate(xNum, yNum, kernel, xCentral, yCentral, x, y, options->mode); 329 bool xExact, yExact; // Exact shifts? 330 interpolateKernelGenerate(xNum, yNum, kernel, &xExact, &yExact, xCentral, yCentral, 331 x, y, options->mode, options->shifting); 297 332 298 333 float sumKernel = 0.0; // Sum of the kernel … … 306 341 bool haveMask = mask && maskVal; // Does the user want the variance value? 307 342 343 INTERPOLATE_EXACT(); 344 308 345 // Add contributions in an area outside the image 309 346 #define INTERPOLATE_KERNEL_ADD_OFFIMAGE() { \ … … 316 353 // Measure kernel contribution from outside image 317 354 if (offImage) { 318 // Bottom rows 319 for (int j = 0; j < jMin; j++) { 320 for (int i = 0; i < xNum; i++) { 321 INTERPOLATE_KERNEL_ADD_OFFIMAGE(); 355 if (!yExact) { 356 // Bottom rows 357 for (int j = 0; j < jMin; j++) { 358 for (int i = 0; i < xNum; i++) { 359 INTERPOLATE_KERNEL_ADD_OFFIMAGE(); 360 } 322 361 } 323 362 } 324 // Two sides 325 for (int j = jMin; j < jMax; j++) { 326 for (int i = 0; i < iMin; i++) { 327 INTERPOLATE_KERNEL_ADD_OFFIMAGE(); 363 if (!xExact) { 364 // Two sides 365 for (int j = jMin; j < jMax; j++) { 366 for (int i = 0; i < iMin; i++) { 367 INTERPOLATE_KERNEL_ADD_OFFIMAGE(); 368 } 369 for (int i = iMax + 1; i < xNum; i++) { 370 INTERPOLATE_KERNEL_ADD_OFFIMAGE(); 371 } 328 372 } 329 for (int i = iMax + 1; i < xNum; i++) { 330 INTERPOLATE_KERNEL_ADD_OFFIMAGE(); 331 } 332 } 333 // Top rows 334 for (int j = jMax + 1; j < yNum; j++) { 335 for (int i = 0; i < xNum; i++) { 336 INTERPOLATE_KERNEL_ADD_OFFIMAGE(); 373 } 374 if (!yExact) { 375 // Top rows 376 for (int j = jMax + 1; j < yNum; j++) { 377 for (int i = 0; i < xNum; i++) { 378 INTERPOLATE_KERNEL_ADD_OFFIMAGE(); 379 } 337 380 } 338 381 } … … 445 488 // Generate Lanczos interpolation kernels 446 489 static void lanczos(double values[], // Interpolation kernel to generate 490 bool *exact, // Exact shift? 447 491 int num, // Number of values in the kernel 448 float frac // Sub-pixel position 492 float frac, // Sub-pixel position 493 bool allowExact // Allow exact shift? 449 494 ) 450 495 { 451 // XXX: Instead of generating a convolution kernel that does no shifting, need to set a boolean that says 452 // we can do an exact shift. 453 if (fabs(frac) < DBL_EPSILON) { 496 if (allowExact && fabs(frac) < DBL_EPSILON) { 497 *exact = true; 454 498 // No real shift 455 499 for (int i = 0; i < (num - 1) / 2; i++) { … … 461 505 } 462 506 } else { 463 double norm4 = 0.0; // Normalisation507 *exact = false; 464 508 double norm1 = 2.0 / PS_SQR(M_PI); // Normalisation for laczos 465 509 double norm2 = M_PI * 4.0 / (float)num; // Normalisation for sinc function 1 … … 467 511 double pos = - (num - 1)/2 - frac; // Position of interest 468 512 for (int i = 0; i < num; i++, pos += 1.0) { 469 norm4 += values[i] = norm1 * sin(pos * norm2) * sin(pos * norm3) / PS_SQR(pos);470 }471 norm4 = 1.0 / norm4;472 for (int i = 0; i < num; i++) {473 values[i] *= norm4;513 if (fabs(pos) < DBL_EPSILON) { 514 values[i] = 1.0; 515 } else { 516 values[i] = norm1 * sin(pos * norm2) * sin(pos * norm3) / PS_SQR(pos); 517 } 474 518 } 475 519 } … … 510 554 static inline void interpolateSeparateGenerate(int xNum, int yNum, // Size of interpolation kernel 511 555 double xKernel[xNum], double yKernel[yNum], // Kernels 556 bool *xExact, bool *yExact, // Exact shifts? 512 557 int xCentral, int yCentral, // Central pixel of convolution 513 558 float x, float y, // Coordinates of interest 514 psImageInterpolateMode mode // Mode for interpolation 559 psImageInterpolateMode mode, // Mode for interpolation 560 bool allowExact // Allow an exact shift? 515 561 ) 516 562 { … … 521 567 case PS_INTERPOLATE_LANCZOS4: { 522 568 double xFrac = x - xCentral - 0.5; // Fraction of pixel in x 523 lanczos(xKernel, x Num, xFrac);569 lanczos(xKernel, xExact, xNum, xFrac, allowExact); 524 570 double yFrac = y - yCentral - 0.5; // Fraction of pixel in y 525 lanczos(yKernel, y Num, yFrac);571 lanczos(yKernel, yExact, yNum, yFrac, allowExact); 526 572 break; 527 573 } … … 553 599 554 600 double xKernel[xNum], yKernel[yNum]; // Interpolation kernels 555 interpolateSeparateGenerate(xNum, yNum, xKernel, yKernel, xCentral, yCentral, x, y, options->mode); 601 bool xExact, yExact; // Exact shift? 602 interpolateSeparateGenerate(xNum, yNum, xKernel, yKernel, &xExact, &yExact, 603 xCentral, yCentral, x, y, options->mode, options->shifting); 556 604 557 605 float sumKernel = 0.0; // Sum of the kernel … … 564 612 bool wantVariance = variance && varianceValue; // Does the user want the variance value? 565 613 bool haveMask = mask && maskVal; // Does the user want the variance value? 614 615 INTERPOLATE_EXACT(); 566 616 567 617 // Add contributions in an area outside the image … … 585 635 if (offImage) { 586 636 // Bottom rows 587 for (int j = 0; j < jMin; j++) { 588 INTERPOLATE_SEPARATE_SETUP_OFFIMAGE_COL(); 589 for (int i = 0; i < xNum; i++) { 590 INTERPOLATE_SEPARATE_ADD_OFFIMAGE_COL(); 637 if (!yExact) { 638 for (int j = 0; j < jMin; j++) { 639 INTERPOLATE_SEPARATE_SETUP_OFFIMAGE_COL(); 640 for (int i = 0; i < xNum; i++) { 641 INTERPOLATE_SEPARATE_ADD_OFFIMAGE_COL(); 642 } 643 INTERPOLATE_SEPARATE_ADD_OFFIMAGE_ROW(); 591 644 } 592 INTERPOLATE_SEPARATE_ADD_OFFIMAGE_ROW();593 645 } 594 646 // Two sides 595 for (int j = jMin; j < jMax; j++) { 596 INTERPOLATE_SEPARATE_SETUP_OFFIMAGE_COL(); 597 for (int i = 0; i < iMin; i++) { 598 INTERPOLATE_SEPARATE_ADD_OFFIMAGE_COL(); 647 if (!xExact) { 648 for (int j = jMin; j < jMax; j++) { 649 INTERPOLATE_SEPARATE_SETUP_OFFIMAGE_COL(); 650 for (int i = 0; i < iMin; i++) { 651 INTERPOLATE_SEPARATE_ADD_OFFIMAGE_COL(); 652 } 653 for (int i = iMax + 1; i < xNum; i++) { 654 INTERPOLATE_SEPARATE_ADD_OFFIMAGE_COL(); 655 } 656 INTERPOLATE_SEPARATE_ADD_OFFIMAGE_ROW(); 599 657 } 600 for (int i = iMax + 1; i < xNum; i++) { 601 INTERPOLATE_SEPARATE_ADD_OFFIMAGE_COL(); 658 } 659 // Top rows 660 if (!yExact) { 661 for (int j = jMax + 1; j < yNum; j++) { 662 if (!xExact) { 663 INTERPOLATE_SEPARATE_SETUP_OFFIMAGE_COL(); 664 for (int i = 0; i < xNum; i++) { 665 INTERPOLATE_SEPARATE_ADD_OFFIMAGE_COL(); 666 } 667 INTERPOLATE_SEPARATE_ADD_OFFIMAGE_ROW(); 668 } 602 669 } 603 INTERPOLATE_SEPARATE_ADD_OFFIMAGE_ROW();604 }605 // Top rows606 for (int j = jMax + 1; j < yNum; j++) {607 INTERPOLATE_SEPARATE_SETUP_OFFIMAGE_COL();608 for (int i = 0; i < xNum; i++) {609 INTERPOLATE_SEPARATE_ADD_OFFIMAGE_COL();610 }611 INTERPOLATE_SEPARATE_ADD_OFFIMAGE_ROW();612 670 } 613 671 } … … 826 884 827 885 double kernel[yNum][xNum]; // Interpolation kernel for straight interpolation 828 interpolateKernelGenerate(xNum, yNum, kernel, xCentral, yCentral, x, y, options->mode); 886 bool xExact, yExact; // Exact shift? 887 // Pretend we're not shifting pixels (i.e., we don't care about any exact shifting) because on the off 888 // chance that a shift is integral, we don't want to get a trivial kernel back, but something that sort of 889 // reflects what's going on. 890 interpolateKernelGenerate(xNum, yNum, kernel, &xExact, &yExact, xCentral, yCentral, 891 x, y, options->mode, false); 829 892 830 893 double sumKernel2 = 0.0; // Sum of kernel squares … … 855 918 856 919 double xKernel[xNum], yKernel[yNum]; // Interpolation kernels for separable interpolation 857 interpolateSeparateGenerate(xNum, yNum, xKernel, yKernel, xCentral, yCentral, x, y, options->mode); 920 bool xExact, yExact; // Exact shift? 921 // Pretend we're not shifting pixels (i.e., we don't care about any exact shifting) because on the off 922 // chance that a shift is integral, we don't want to get a trivial kernel back, but something that sort of 923 // reflects what's going on. 924 interpolateSeparateGenerate(xNum, yNum, xKernel, yKernel, &xExact, &yExact, 925 xCentral, yCentral, x, y, options->mode, false); 858 926 859 927 double ySumKernel2 = 0.0; // Sum of kernel squared in y -
trunk/psLib/src/imageops/psImageInterpolate.h
r18162 r19140 7 7 * @author Paul Price, Institute for Astronomy 8 8 * 9 * @version $Revision: 1. 4$ $Name: not supported by cvs2svn $10 * @date $Date: 2008-0 6-17 21:24:58$9 * @version $Revision: 1.5 $ $Name: not supported by cvs2svn $ 10 * @date $Date: 2008-08-21 01:12:44 $ 11 11 * Copyright 2004-2007 Institute for Astronomy, University of Hawaii 12 12 */ … … 53 53 psMaskType poorMask; ///< Mask value to give poor pixels 54 54 float poorFrac; ///< Fraction of flux in bad pixels before output is marked bad 55 bool shifting; ///< Shifting images? Don't interpolate if the shift is exact. 55 56 } psImageInterpolateOptions; 56 57
Note:
See TracChangeset
for help on using the changeset viewer.
