Changeset 12589 for trunk/psModules/src/camera/pmFPAMosaic.c
- Timestamp:
- Mar 26, 2007, 4:44:42 PM (19 years ago)
- File:
-
- 1 edited
-
trunk/psModules/src/camera/pmFPAMosaic.c (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
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
Note:
See TracChangeset
for help on using the changeset viewer.
