Changeset 12589
- Timestamp:
- Mar 26, 2007, 4:44:42 PM (19 years ago)
- Location:
- trunk/psModules/src
- Files:
-
- 3 edited
-
camera/pmFPACopy.c (modified) (14 diffs)
-
camera/pmFPAMosaic.c (modified) (3 diffs)
-
concepts/pmConceptsUpdate.c (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psModules/src/camera/pmFPACopy.c
r12564 r12589 17 17 18 18 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// 19 // File-static functions 20 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// 21 22 // Bin a region down by specified factors in x and y 23 static void binRegion(psRegion *region, // Region to be binned 24 int xBin, int yBin // Binning in x and y 25 ) 26 { 27 assert(region); 28 assert(xBin > 0); 29 assert(yBin > 0); 30 31 // Want to include the lower bound: 1 binned by 4 --> 0; 3 binned by 4 --> 0; 4 binned by 4 --> 1 32 region->x0 = (int)(region->x0 / xBin); 33 region->y0 = (int)(region->y0 / yBin); 34 // Want to exclude the upper bound: 4 binned by 4 --> 1; 5 binned by 4 --> 2; 7 binned by 4 --> 2 35 region->x1 = (int)((region->x1 + xBin - 1) / xBin); 36 region->y1 = (int)((region->y1 + yBin - 1) / yBin); 37 } 38 39 #if 1 19 // File-static functions and macros 20 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// 21 22 // Copy the value for a concept 23 #define COPY_CONCEPT(TARGET, SOURCE, NAME, TYPE) { \ 24 psMetadataItem *targetItem = psMetadataLookup(TARGET, NAME); \ 25 psMetadataItem *sourceItem = psMetadataLookup(SOURCE, NAME); \ 26 targetItem->data.TYPE = sourceItem->data.TYPE; } 27 40 28 // Find the blank (image-less) PHU, given a cell. 41 29 static pmHDU *findBlankPHU(const pmCell *cell // The cell for which to find the PHU … … 58 46 return NULL; 59 47 } 60 #endif 48 49 // copy one of the psImage components of the readout 50 static void readoutCopyComponent (psImage **target, psImage *source, psImageBinning *binning, bool xFlip, bool yFlip, bool pixels) { 51 52 if (!source) return; 53 54 if (*target) { 55 psFree(*target); 56 } 57 if (pixels) { 58 *target = psImageFlip(NULL, source, xFlip, yFlip); 59 return; 60 } 61 62 // I have the fine image size, I know the binning factor, determine the ruff image size 63 binning->nXfine = source->numCols; 64 binning->nYfine = source->numRows; 65 psImageBinningSetRuffSize(binning, PS_IMAGE_BINNING_CENTER); 66 *target = psImageAlloc(binning->nXruff, binning->nYruff, source->type.type); 67 return; 68 } 61 69 62 70 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// … … 77 85 assert(xBin > 0 && yBin > 0); 78 86 87 // XXX this is a programming / config error 88 if (pixels && (xBin != 1 || yBin != 1)) { 89 psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Unable to copy pixels if binning is set\n"); 90 return false; 91 } 92 93 // the binning structure carries the information no how to rebin the images if needed 94 psImageBinning *binning = psImageBinningAlloc(); 95 binning->nXbin = xBin; 96 binning->nYbin = yBin; 97 79 98 psArray *sourceReadouts = source->readouts; // The source readouts 80 99 int numReadouts = sourceReadouts->n; // Number of readouts copied 81 100 82 // Copy the value for a concept83 #define COPY_CONCEPT(TARGET, SOURCE, NAME, TYPE) \84 psMetadataItem *targetItem = psMetadataLookup(TARGET, NAME); \85 psMetadataItem *sourceItem = psMetadataLookup(SOURCE, NAME); \86 targetItem->data.TYPE = sourceItem->data.TYPE;87 88 101 // Need to check/change CELL.XPARITY and CELL.YPARITY 89 bool mdok = true; // Status of MD lookup 102 bool mdokS = true; // Status of MD lookup 103 bool mdokT = true; // Status of MD lookup 90 104 bool xFlip = false; // Switch parity in x? 91 105 bool yFlip = false; // Switch parity in y? 92 { 93 int xParityTarget = psMetadataLookupS32(&mdok, target->concepts, "CELL.XPARITY"); // Target x parity 94 if (mdok && (xParityTarget == 1 || xParityTarget == -1)) 95 { 96 int xParitySource = psMetadataLookupS32(&mdok, source->concepts, "CELL.XPARITY"); // Source parity 97 if (mdok && (xParitySource == 1 || xParitySource == -1) && xParityTarget != xParitySource) { 98 xFlip = true; 99 } 100 } else 101 { 102 // Use the source parity 103 COPY_CONCEPT(target->concepts, source->concepts, "CELL.XPARITY", S32); 104 } 105 int yParityTarget = psMetadataLookupS32(&mdok, target->concepts, "CELL.YPARITY"); // Target y parity 106 if (mdok && (yParityTarget == 1 || yParityTarget == -1)) 107 { 108 int yParitySource = psMetadataLookupS32(&mdok, source->concepts, "CELL.YPARITY"); // Source parity 109 if (mdok && (yParitySource == 1 || yParitySource == -1) && yParityTarget != yParitySource) { 110 yFlip = true; 111 } 112 } else 113 { 114 // Use the source parity 115 COPY_CONCEPT(target->concepts, source->concepts, "CELL.YPARITY", S32); 116 } 117 psTrace("psModules.camera", 3, "xFlip: %d; yFlip: %d\n", xFlip, yFlip); 118 } 119 120 if (pixels && (xBin != 1 || yBin != 1)) { 121 psLogMsg(__func__, PS_LOG_WARN, "Unable to copy pixels if binning is set --- copy turned off.\n"); 122 pixels = false; 123 } 106 107 // enforce the following conditions: 108 // CELL.XPARITY is required 109 // CELL.XPARITY must be +/- 1 110 int xParitySource = psMetadataLookupS32(&mdokS, source->concepts, "CELL.XPARITY"); // Source parity 111 int xParityTarget = psMetadataLookupS32(&mdokT, target->concepts, "CELL.XPARITY"); // Target x parity 112 assert (mdokS && mdokT); 113 assert (abs(xParitySource) == 1); 114 assert (abs(xParityTarget) == 1); 115 if (xParityTarget != xParitySource) { 116 xFlip = true; 117 } else { 118 // Use the source parity 119 COPY_CONCEPT(target->concepts, source->concepts, "CELL.XPARITY", S32); 120 } 121 122 int yParityTarget = psMetadataLookupS32(&mdokT, target->concepts, "CELL.YPARITY"); // Target y parity 123 int yParitySource = psMetadataLookupS32(&mdokS, source->concepts, "CELL.YPARITY"); // Source parity 124 assert (mdokS && mdokT); 125 assert (abs(yParitySource) == 1); 126 assert (abs(yParityTarget) == 1); 127 if (yParityTarget != yParitySource) { 128 yFlip = true; 129 } else { 130 // Use the source parity 131 COPY_CONCEPT(target->concepts, source->concepts, "CELL.YPARITY", S32); 132 } 133 psTrace("psModules.camera", 3, "xFlip: %d; yFlip: %d\n", xFlip, yFlip); 124 134 125 135 // Perform deep copy of the images. I would prefer *not* to do a deep copy, in the interests of speed (we … … 132 142 133 143 // Copy attributes 144 // XXX is this correct under binning? 134 145 targetReadout->col0 = sourceReadout->col0; 135 146 targetReadout->row0 = sourceReadout->row0; … … 138 149 targetReadout->data_exists = sourceReadout->data_exists; 139 150 140 // Copy image 141 if (sourceReadout->image) { 142 if (targetReadout->image) { 143 psFree(targetReadout->image); 144 } 145 if (pixels) { 146 targetReadout->image = psImageFlip(NULL, sourceReadout->image, xFlip, yFlip); 147 } else { 148 psImage *image = sourceReadout->image; // The source image 149 long binnedCols = (image->numCols + xBin - 1) / xBin; 150 long binnedRows = (image->numRows + yBin - 1) / yBin; 151 targetReadout->image = psImageAlloc(binnedCols, binnedRows, image->type.type); 152 } 153 } 154 155 // Copy mask 156 if (sourceReadout->mask) { 157 if (targetReadout->mask) { 158 psFree(targetReadout->mask); 159 } 160 if (pixels) { 161 targetReadout->mask = psImageFlip(NULL, sourceReadout->mask, xFlip, yFlip); 162 } else { 163 psImage *mask = sourceReadout->mask; // The source mask image 164 long binnedCols = (mask->numCols + xBin - 1) / xBin; 165 long binnedRows = (mask->numRows + yBin - 1) / yBin; 166 targetReadout->mask = psImageAlloc(binnedCols, binnedRows, mask->type.type); 167 } 168 } 169 170 // Copy weight 171 if (sourceReadout->weight) { 172 if (targetReadout->weight) { 173 psFree(targetReadout->weight); 174 } 175 if (pixels) { 176 targetReadout->weight = psImageFlip(NULL, sourceReadout->weight, xFlip, yFlip); 177 } else { 178 psImage *weight = sourceReadout->weight; // The source weight image 179 long binnedCols = (weight->numCols + xBin - 1) / xBin; 180 long binnedRows = (weight->numRows + yBin - 1) / yBin; 181 targetReadout->weight = psImageAlloc(binnedCols, binnedRows, weight->type.type); 182 } 183 } 151 // Copy all three image components (image, mask, weight) 152 readoutCopyComponent (&targetReadout->image, sourceReadout->image, binning, xFlip, yFlip, pixels); 153 readoutCopyComponent (&targetReadout->mask, sourceReadout->mask, binning, xFlip, yFlip, pixels); 154 readoutCopyComponent (&targetReadout->weight, sourceReadout->weight, binning, xFlip, yFlip, pixels); 184 155 185 156 // Copy bias … … 187 158 psListRemove(targetReadout->bias, PS_LIST_HEAD); 188 159 } 160 189 161 // Iterate over the biases 190 162 psListIterator *biasIter = psListIteratorAlloc(sourceReadout->bias, PS_LIST_HEAD, false); 191 163 psImage *bias = NULL; // Bias image from iteration 192 164 while ((bias = psListGetAndIncrement(biasIter))) { 193 psImage *biasCopy; // Copy of the bias 194 if (pixels) { 195 biasCopy = psImageFlip(NULL, bias, xFlip, yFlip); 196 } else { 197 long binnedCols = (bias->numCols + xBin - 1) / xBin; 198 long binnedRows = (bias->numRows + yBin - 1) / yBin; 199 biasCopy = psImageAlloc(binnedCols, binnedRows, bias->type.type); 200 } 165 psImage *biasCopy = NULL; // Copy of the bias 166 readoutCopyComponent (&biasCopy, bias, binning, xFlip, yFlip, pixels); 201 167 psListAdd(targetReadout->bias, PS_LIST_TAIL, biasCopy); 202 168 psFree(biasCopy); // Drop reference … … 216 182 while ((conceptItem = psMetadataGetAndIncrement(conceptsIter))) { 217 183 psString name = conceptItem->name; // Name of concept 218 if (strcmp(name, "CELL.TRIMSEC") != 0 && strcmp(name, "CELL.BIASSEC") != 0 && 219 strcmp(name, "CELL.XPARITY") != 0 && strcmp(name, "CELL.YPARITY") != 0 && 220 strcmp(name, "CELL.X0") != 0 && strcmp(name, "CELL.Y0") != 0) { 221 psMetadataItem *copy = psMetadataItemCopy(conceptItem); // Copy of the concept 222 psMetadataAddItem(target->concepts, copy, PS_LIST_TAIL, PS_META_REPLACE); 223 psFree(copy); // Drop reference 224 } 184 if (!strcmp(name, "CELL.TRIMSEC")) continue; 185 if (!strcmp(name, "CELL.BIASSEC")) continue; 186 if (!strcmp(name, "CELL.XPARITY")) continue; 187 if (!strcmp(name, "CELL.YPARITY")) continue; 188 if (!strcmp(name, "CELL.X0")) continue; 189 if (!strcmp(name, "CELL.Y0")) continue; 190 191 psMetadataItem *copy = psMetadataItemCopy(conceptItem); // Copy of the concept 192 psMetadataAddItem(target->concepts, copy, PS_LIST_TAIL, PS_META_REPLACE); 193 psFree(copy); // Drop reference 225 194 } 226 195 psFree(conceptsIter); 227 196 228 197 // Need to update CELL.TRIMSEC and CELL.BIASSEC if we changed the binning and they exist already. 229 if (xBin != 1 || yBin != 1) { 198 // XXX this code seems to be very similar to pmConceptsUpdate 199 if ((binning->nXbin != 1) || (binning->nYbin != 1)) { 200 bool mdok = false; 230 201 psRegion *trimsec = psMetadataLookupPtr(&mdok, target->concepts, "CELL.TRIMSEC"); // The trim section 231 202 if (mdok && trimsec && !psRegionIsNaN(*trimsec)) { 232 binRegion(trimsec, xBin, yBin);203 *trimsec = psImageBinningSetRuffRegion(binning, *trimsec); 233 204 } 234 205 psList *biassecs = psMetadataLookupPtr(&mdok, target->concepts, "CELL.BIASSEC"); // The bias sections … … 238 209 while ((biassec = psListGetAndIncrement(biassecsIter))) { 239 210 if (!psRegionIsNaN(*biassec)) { 240 binRegion(biassec, xBin, yBin);211 *biassec = psImageBinningSetRuffRegion(binning, *biassec); 241 212 } 242 213 } … … 246 217 247 218 // Need to update CELL.X0 and CELL.Y0 if we flipped 219 // XXX this section should probably use a common function consistent with psImageBinning 248 220 if (xFlip) { 249 221 int xZero = psMetadataLookupS32(NULL, source->concepts, "CELL.X0"); // CELL.X0 from source … … 254 226 if (sourceBin == 0) { 255 227 // Don't know the binning; assume it is unity 256 sourceBin = xBin;257 } 258 259 psTrace("psModules.camera", 3, "CELL.X0: Before: %d After: %d\n", xZero, 260 xZero + (xSize - 1) * xParity * sourceBin);228 sourceBin = binning->nXbin; 229 } 230 231 // XXX make sure this is consistent with the psImageBinning 232 psTrace("psModules.camera", 3, "CELL.X0: Before: %d After: %d\n", xZero, xZero + (xSize - 1) * xParity * sourceBin); 261 233 psTrace("psModules.camera", 9, "(xParity: %d xBin: %d numCols: %d)\n", xParity, sourceBin, xSize); 262 234 … … 277 249 if (sourceBin == 0) { 278 250 // Don't know the binning; assume it is unity 279 sourceBin = yBin; 280 } 281 282 psTrace("psModules.camera", 3, "CELL.Y0: Before: %d After: %d\n", yZero, 283 yZero + (ySize - 1) * yParity * sourceBin); 251 sourceBin = binning->nYbin; 252 } 253 254 psTrace("psModules.camera", 3, "CELL.Y0: Before: %d After: %d\n", yZero, yZero + (ySize - 1) * yParity * sourceBin); 284 255 psTrace("psModules.camera", 9, "(yParity: %d yBin: %d numRows: %d)\n", yParity, sourceBin, ySize); 285 256 … … 295 266 296 267 // Update the binning concepts 268 // XXX this should probably be done with a common function using psImageBinning 297 269 psMetadataItem *binItem = psMetadataLookup(target->concepts, "CELL.XBIN"); 298 270 binItem->data.S32 *= xBin; … … 314 286 pmHDU *targetPHU = findBlankPHU(target); // The target PHU 315 287 if (targetPHU && targetPHU != targetHDU) { 316 //pmHDU *sourcePHU = pmHDUGetHighest(source->parent->parent, source->parent, source); // A source HDU288 // pmHDU *sourcePHU = pmHDUGetHighest(source->parent->parent, source->parent, source); // A source HDU 317 289 pmHDU *sourcePHU = findBlankPHU(source); // The target PHU 318 290 if (sourcePHU && sourcePHU->header) { … … 321 293 } 322 294 295 psFree (binning); 323 296 target->data_exists = true; 324 297 return true; -
trunk/psModules/src/camera/pmFPAMosaic.c
r11786 r12589 382 382 } 383 383 384 // Mosaic multiple images, with flips, binning and offsets 385 static psImage *imageMosaic(const psArray *source, // Images to splice in 386 const psVector *xFlip, const psVector *yFlip, // Need to flip x and y? 387 const psVector *xBinSource, // Binning in x of source images 388 const psVector *yBinSource, // Binning in y of source images 389 int xBinTarget, int yBinTarget, // Binning in x and y of target images 390 const psVector *x0, const psVector *y0 // Offsets for source images on target 391 ) 392 { 393 assert(source); 394 assert(xFlip && xFlip->type.type == PS_TYPE_U8); 395 assert(yFlip && yFlip->type.type == PS_TYPE_U8); 396 assert(xBinSource && xBinSource->type.type == PS_TYPE_S32); 397 assert(yBinSource && yBinSource->type.type == PS_TYPE_S32); 398 assert(x0 && x0->type.type == PS_TYPE_S32); 399 assert(y0 && y0->type.type == PS_TYPE_S32); 400 assert(xFlip->n == source->n); 401 assert(yFlip->n == source->n); 402 assert(xBinSource->n == source->n); 403 assert(yBinSource->n == source->n); 404 assert(x0->n == source->n); 405 assert(y0->n == source->n); 406 407 if (source->n == 0) { 408 return NULL; 409 } 410 411 // Get the maximum extent of the mosaic image 412 int xMin = INT_MAX; 413 int xMax = - INT_MAX; 414 int yMin = INT_MAX; 415 int yMax = - INT_MAX; 416 psElemType type = 0; 417 int numImages = 0; // Number of images 418 psTrace("psModules.camera", 3, "Mosaicking %ld cells.\n", source->n); 419 for (int i = 0; i < source->n; i++) { 420 psImage *image = source->data[i]; // The image of interest 421 if (!image) { 422 continue; 423 } 424 numImages++; 425 426 // Only implemented for F32 and U8 images so far. 427 assert(image->type.type == PS_TYPE_F32 || image->type.type == PS_TYPE_U8); 428 // All input types must be the same 429 if (type == 0) { 430 type = image->type.type; 431 } 432 assert(type == image->type.type); 433 434 // Size of cell in x and y 435 int xParity = xFlip->data.U8[i] ? -1 : 1; 436 int yParity = yFlip->data.U8[i] ? -1 : 1; 437 psTrace("psModules.camera", 5, "Extent of cell %d: %d -> %d , %d -> %d\n", i, x0->data.S32[i], 438 x0->data.S32[i] + xParity * xBinSource->data.S32[i] * image->numCols, y0->data.S32[i], 439 y0->data.S32[i] + yParity * yBinSource->data.S32[i] * image->numRows); 440 441 COMPARE(x0->data.S32[i], xMin, xMax); 442 COMPARE(y0->data.S32[i], yMin, yMax); 443 // Subtract the parity to get the inclusive limit (not exclusive) 444 COMPARE(x0->data.S32[i] + xParity * xBinSource->data.S32[i] * image->numCols - xParity, xMin, xMax); 445 COMPARE(y0->data.S32[i] + yParity * yBinSource->data.S32[i] * image->numRows - yParity, yMin, yMax); 446 } 447 if (numImages == 0) { 448 return NULL; 449 } 450 451 // Set up the image 452 // Since both upper and lower values are inclusive, we need to add one to the size 453 float xSize = (float)(xMax - xMin + 1) / (float)xBinTarget; 454 if (xSize - (int)xSize > 0) { 455 xSize += 1; 456 } 457 float ySize = (float)(yMax - yMin + 1) / (float)yBinTarget; 458 if (ySize - (int)ySize > 0) { 459 ySize += 1; 460 } 461 462 psTrace("psModules.camera", 3, "Spliced image will be %dx%d\n", (int)xSize, (int)ySize); 463 psImage *mosaic = psImageAlloc((int)xSize, (int)ySize, type); // The mosaic image 464 psImageInit(mosaic, 0); 465 466 // Next pass through the images to do the mosaicking 467 for (int i = 0; i < source->n; i++) { 468 psImage *image = source->data[i]; // The image of interest 469 if (!image) { 470 continue; 471 } 472 int xParity = xFlip->data.U8[i] ? -1 : 1; // Parity difference, in x 473 int yParity = yFlip->data.U8[i] ? -1 : 1; // Parity difference, in y 474 int xTargetBase = (x0->data.S32[i] - xMin) / xBinTarget; // The base x position in the target frame 475 int yTargetBase = (y0->data.S32[i] - yMin) / yBinTarget; // The base y position in the target frame 476 if (xBinSource->data.S32[i] == xBinTarget && yBinSource->data.S32[i] == yBinTarget && 477 xFlip->data.U8[i] == 0 && yFlip->data.U8[i] == 0) { 478 // Let someone else do the hard work 479 psImageOverlaySection(mosaic, image, xTargetBase, yTargetBase, "+"); 480 } else if (xBinSource->data.S32[i] == xBinTarget && yBinSource->data.S32[i] == yBinTarget) { 481 // There's a difference with the parities, but we don't have to worry about binning 482 483 #define COPY_WITH_PARITY_DIFFERENCE(TYPE) \ 384 // supporting macros used by imageMosaic() 385 // copy pixels without binning 386 #define COPY_WITH_PARITY_DIFFERENCE(TYPE) \ 484 387 case PS_TYPE_##TYPE: { \ 485 388 for (int y = 0; y < image->numRows; y++) { \ … … 493 396 break; 494 397 495 switch (type) { 496 COPY_WITH_PARITY_DIFFERENCE(F32); 497 COPY_WITH_PARITY_DIFFERENCE(U8); 498 default: 499 psAbort("Should never get here.\n"); 500 } 501 502 } else { 503 // We have to do all of the hard work ourself 504 505 // In case the original image is binned but the mosaic is not, we need to fill in the 506 // values in the mosaic. 507 #define FILL_IN(TYPE) \ 398 // In case the original image is binned but the mosaic is not, we need to fill in the values in 399 // the mosaic. this operation should be replaced with a call to one of the functions defined 400 // in psImageBinning 401 #define FILL_IN(TYPE) \ 508 402 case PS_TYPE_##TYPE: \ 509 403 for (int y = 0; y < image->numRows; y++) { \ … … 522 416 break; 523 417 418 // Mosaic multiple images, with flips, binning and offsets 419 static psImage *imageMosaic(const psArray *source, // Images to splice in 420 const psVector *xFlip, const psVector *yFlip, // Need to flip x and y? 421 const psVector *xBinSource, // Binning in x of source images 422 const psVector *yBinSource, // Binning in y of source images 423 int xBinTarget, int yBinTarget, // Binning in x and y of target images 424 const psVector *x0, const psVector *y0 // Offsets for source images on target 425 ) 426 { 427 assert(source); 428 assert(xFlip && xFlip->type.type == PS_TYPE_U8); 429 assert(yFlip && yFlip->type.type == PS_TYPE_U8); 430 assert(xBinSource && xBinSource->type.type == PS_TYPE_S32); 431 assert(yBinSource && yBinSource->type.type == PS_TYPE_S32); 432 assert(x0 && x0->type.type == PS_TYPE_S32); 433 assert(y0 && y0->type.type == PS_TYPE_S32); 434 assert(xFlip->n == source->n); 435 assert(yFlip->n == source->n); 436 assert(xBinSource->n == source->n); 437 assert(yBinSource->n == source->n); 438 assert(x0->n == source->n); 439 assert(y0->n == source->n); 440 441 if (source->n == 0) { 442 return NULL; 443 } 444 445 // Get the maximum extent of the mosaic image 446 int xMin = INT_MAX; 447 int xMax = - INT_MAX; 448 int yMin = INT_MAX; 449 int yMax = - INT_MAX; 450 psElemType type = 0; 451 int numImages = 0; // Number of images 452 psTrace("psModules.camera", 3, "Mosaicking %ld cells.\n", source->n); 453 for (int i = 0; i < source->n; i++) { 454 psImage *image = source->data[i]; // The image of interest 455 if (!image) { 456 continue; 457 } 458 numImages++; 459 460 // Only implemented for F32 and U8 images so far. 461 assert(image->type.type == PS_TYPE_F32 || image->type.type == PS_TYPE_U8); 462 // All input types must be the same 463 if (type == 0) { 464 type = image->type.type; 465 } 466 assert(type == image->type.type); 467 468 // Size of cell in x and y 469 int xParity = xFlip->data.U8[i] ? -1 : 1; 470 int yParity = yFlip->data.U8[i] ? -1 : 1; 471 psTrace("psModules.camera", 5, "Extent of cell %d: %d -> %d , %d -> %d\n", i, x0->data.S32[i], 472 x0->data.S32[i] + xParity * xBinSource->data.S32[i] * image->numCols, y0->data.S32[i], 473 y0->data.S32[i] + yParity * yBinSource->data.S32[i] * image->numRows); 474 475 COMPARE(x0->data.S32[i], xMin, xMax); 476 COMPARE(y0->data.S32[i], yMin, yMax); 477 // Subtract the parity to get the inclusive limit (not exclusive) 478 COMPARE(x0->data.S32[i] + xParity * xBinSource->data.S32[i] * image->numCols - xParity, xMin, xMax); 479 COMPARE(y0->data.S32[i] + yParity * yBinSource->data.S32[i] * image->numRows - yParity, yMin, yMax); 480 } 481 if (numImages == 0) { 482 return NULL; 483 } 484 485 // Set up the image 486 // Since both upper and lower values are inclusive, we need to add one to the size 487 float xSize = (float)(xMax - xMin + 1) / (float)xBinTarget; 488 if (xSize - (int)xSize > 0) { 489 xSize += 1; 490 } 491 float ySize = (float)(yMax - yMin + 1) / (float)yBinTarget; 492 if (ySize - (int)ySize > 0) { 493 ySize += 1; 494 } 495 496 psTrace("psModules.camera", 3, "Spliced image will be %dx%d\n", (int)xSize, (int)ySize); 497 psImage *mosaic = psImageAlloc((int)xSize, (int)ySize, type); // The mosaic image 498 psImageInit(mosaic, 0); 499 500 // Next pass through the images to do the mosaicking 501 // XXX this function uses summing for the output: is this the right choice? 502 for (int i = 0; i < source->n; i++) { 503 psImage *image = source->data[i]; // The image of interest 504 if (!image) { 505 continue; 506 } 507 int xParity = xFlip->data.U8[i] ? -1 : 1; // Parity difference, in x 508 int yParity = yFlip->data.U8[i] ? -1 : 1; // Parity difference, in y 509 int xTargetBase = (x0->data.S32[i] - xMin) / xBinTarget; // The base x position in the target frame 510 int yTargetBase = (y0->data.S32[i] - yMin) / yBinTarget; // The base y position in the target frame 511 512 // in the first case, we are just copy a section pixel-by-pixel 513 if ((xBinSource->data.S32[i] == xBinTarget) && 514 (yBinSource->data.S32[i] == yBinTarget) && 515 (xFlip->data.U8[i] == 0) && 516 (yFlip->data.U8[i] == 0)) { 517 // Let someone else do the hard work 518 psImageOverlaySection(mosaic, image, xTargetBase, yTargetBase, "+"); 519 continue; 520 } 521 522 // in the second case, there's a difference with the parities, but we don't have to 523 // worry about binning 524 if (xBinSource->data.S32[i] == xBinTarget && yBinSource->data.S32[i] == yBinTarget) { 524 525 switch (type) { 525 FILL_IN(F32);526 FILL_IN(U8);527 default:526 COPY_WITH_PARITY_DIFFERENCE(F32); 527 COPY_WITH_PARITY_DIFFERENCE(U8); 528 default: 528 529 psAbort("Should never get here.\n"); 529 530 } 530 531 } // Various difficulty levels 531 continue; 532 } 533 534 // In the third case, the images are flipped and have different binnnig. 535 // We have to do all of the hard work ourselves 536 switch (type) { 537 FILL_IN(F32); 538 FILL_IN(U8); 539 default: 540 psAbort("Should never get here.\n"); 541 } 532 542 } // Iterating over images 533 543 534 544 return mosaic; 535 545 } 536 537 546 538 547 // Add a cell and its various properties to the arrays -
trunk/psModules/src/concepts/pmConceptsUpdate.c
r11749 r12589 25 25 // Check for cell concepts updates 26 26 27 bool xStatus, yStatus; // Status of MD lookups 28 psImageBinning *binning = psImageBinningAlloc(); 29 binning->nXbin = psMetadataLookupS32(&xStatus, cell->concepts, "CELL.XBIN"); 30 binning->nYbin = psMetadataLookupS32(&yStatus, cell->concepts, "CELL.YBIN"); 31 if (!xStatus || !yStatus) { 32 // XXX should this be an error condition? 33 psFree (binning); 34 return true; 35 } 36 if (!binning->nXbin || !binning->nXbin) { 37 // XXX should this be an error condition? 38 psFree (binning); 39 return true; 40 } 41 27 42 // CELL.TRIMSEC needs to be updated for the binning 28 43 if (psMetadataLookup(cell->concepts, "CELL.TRIMSEC.UPDATE")) { 29 bool xStatus, yStatus; // Status of MD lookups 30 int xBin = psMetadataLookupS32(&xStatus, cell->concepts, "CELL.XBIN"); 31 int yBin = psMetadataLookupS32(&yStatus, cell->concepts, "CELL.YBIN"); 32 if (xStatus && yStatus && xBin != 0 && yBin != 0) { 33 psRegion *trimsec = psMetadataLookupPtr(NULL, cell->concepts, "CELL.TRIMSEC"); // Trim section 34 trimsec->x0 /= xBin; 35 trimsec->x1 /= xBin; 36 trimsec->y0 /= yBin; 37 trimsec->y1 /= yBin; 38 39 psMetadataRemoveKey(cell->concepts, "CELL.TRIMSEC.UPDATE"); 40 } 44 psRegion *trimsec = psMetadataLookupPtr(NULL, cell->concepts, "CELL.TRIMSEC"); // Trim section 45 *trimsec = psImageBinningSetRuffRegion (binning, *trimsec); 46 psMetadataRemoveKey(cell->concepts, "CELL.TRIMSEC.UPDATE"); 41 47 } 42 48 43 49 // CELL.BIASSEC needs to be updated for the binning 44 50 if (psMetadataLookup(cell->concepts, "CELL.BIASSEC.UPDATE")) { 45 bool xStatus, yStatus; // Status of MD lookups 46 int xBin = psMetadataLookupS32(&xStatus, cell->concepts, "CELL.XBIN"); 47 int yBin = psMetadataLookupS32(&yStatus, cell->concepts, "CELL.YBIN"); 48 if (xStatus && yStatus && xBin != 0 && yBin != 0) { 49 psList *biassecs = psMetadataLookupPtr(NULL, cell->concepts, "CELL.BIASSEC"); // Bias sections 50 psListIterator *biassecsIter = psListIteratorAlloc(biassecs, PS_LIST_HEAD, true); // Iterator 51 psRegion *bias; // Bias region, from iteration 52 while ((bias = psListGetAndIncrement(biassecsIter))) { 53 bias->x0 /= xBin; 54 bias->x1 /= xBin; 55 bias->y0 /= yBin; 56 bias->y1 /= yBin; 57 } 58 psFree(biassecsIter); 59 60 psMetadataRemoveKey(cell->concepts, "CELL.BIASSEC.UPDATE"); 61 } 51 psList *biassecs = psMetadataLookupPtr(NULL, cell->concepts, "CELL.BIASSEC"); // Bias sections 52 psListIterator *biassecsIter = psListIteratorAlloc(biassecs, PS_LIST_HEAD, true); // Iterator 53 psRegion *biassec; // Bias region, from iteration 54 while ((biassec = psListGetAndIncrement(biassecsIter))) { 55 *biassec = psImageBinningSetRuffRegion (binning, *biassec); 56 } 57 psFree(biassecsIter); 58 psMetadataRemoveKey(cell->concepts, "CELL.BIASSEC.UPDATE"); 62 59 } 63 60 psFree (binning); 64 61 } 65 62
Note:
See TracChangeset
for help on using the changeset viewer.
