Changeset 6937 for trunk/psLib/src/imageops/psImageConvolve.c
- Timestamp:
- Apr 21, 2006, 10:45:56 AM (20 years ago)
- File:
-
- 1 edited
-
trunk/psLib/src/imageops/psImageConvolve.c (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psLib/src/imageops/psImageConvolve.c
r6226 r6937 5 5 * @author Robert DeSonia, MHPCC 6 6 * 7 * @version $Revision: 1.3 0$ $Name: not supported by cvs2svn $8 * @date $Date: 2006-0 1-27 20:08:58$7 * @version $Revision: 1.31 $ $Name: not supported by cvs2svn $ 8 * @date $Date: 2006-04-21 20:45:56 $ 9 9 * 10 10 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii … … 487 487 } 488 488 489 // XXX this is the old version from MHPCC 490 # if 0 489 491 bool psImageSmooth (psImage *image, 490 492 double sigma, … … 576 578 return true; 577 579 } 578 580 # else 581 582 // XXX EAM : we MUST use this version : it is a factor of >7 faster than the above 583 bool psImageSmooth (psImage *image, 584 double sigma, 585 double Nsigma) 586 { 587 PS_ASSERT_IMAGE_NON_NULL(image, NULL); 588 589 int Nx, Ny, Npixel, Nrange, Nr; 590 double factor, g, s, sum; 591 psVector *temp; 592 593 // relevant terms 594 Nrange = sigma*Nsigma + 0.5; 595 Npixel = 2*Nrange + 1; 596 factor = -0.5/(sigma*sigma); 597 598 Nx = image->numCols; 599 Ny = image->numRows; 600 601 #define IMAGESMOOTH_CASE(TYPE) \ 602 case PS_TYPE_##TYPE: { \ 603 /* generate normalized gaussian */ \ 604 psVector *gaussnorm = psVectorAlloc (Npixel, PS_TYPE_##TYPE); \ 605 sum = 0.0; \ 606 for (int i = -Nrange; i < Nrange + 1; i++) { \ 607 gaussnorm->data.TYPE[i+Nrange] = exp (factor*i*i); \ 608 sum += gaussnorm->data.TYPE[i+Nrange]; \ 609 } \ 610 for (int i = -Nrange; i < Nrange + 1; i++) { \ 611 gaussnorm->data.TYPE[i+Nrange] /= sum; \ 612 } \ 613 ps##TYPE *gauss = &gaussnorm->data.TYPE[Nrange]; \ 614 \ 615 /* smooth in X direction */ \ 616 temp = psVectorAlloc (Nx, PS_TYPE_##TYPE); \ 617 for (int j = 0; j < Ny; j++) { \ 618 ps##TYPE *vi = image->data.TYPE[j]; \ 619 ps##TYPE *vo = temp->data.TYPE; \ 620 /* smooth first Nrange pixels, with renorm */ \ 621 /* XXX need to check that this does not run over end for narrow images */ \ 622 for (int i = 0; i < Nrange; i++, vi++, vo++) { \ 623 ps##TYPE *vr = vi - i; \ 624 ps##TYPE *vg = gauss - i; \ 625 g = s = 0; \ 626 for (int n = -i; n < Nrange + 1; n++, vr++, vg++) { \ 627 s += *vg * *vr; \ 628 g += *vg; \ 629 } \ 630 *vo = s / g; \ 631 } \ 632 /* smooth middle pixels */ \ 633 for (int i = Nrange; i < Nx - Nrange; i++, vi++, vo++) { \ 634 ps##TYPE *vr = vi - Nrange; \ 635 ps##TYPE *vg = gauss - Nrange; \ 636 s = 0; \ 637 for (int n = -Nrange; n < Nrange + 1; n++, vr++, vg++) { \ 638 s += *vg * *vr; \ 639 } \ 640 *vo = s; \ 641 } \ 642 /* smooth last Nrange pixels, with renorm */ \ 643 /* XXX does this miss the last column? */ \ 644 for (int i = Nx - Nrange; i < Nx; i++, vi++, vo++) { \ 645 ps##TYPE *vr = vi - Nrange; \ 646 ps##TYPE *vg = gauss - Nrange; \ 647 g = s = 0; \ 648 for (int n = -Nrange; n < Nx - i - 1; n++, vr++, vg++) { \ 649 s += *vg * *vr; \ 650 g += *vg; \ 651 } \ 652 *vo = s / g; \ 653 } \ 654 memcpy (image->data.TYPE[j], temp->data.TYPE, Nx*sizeof(ps##TYPE)); \ 655 } \ 656 psFree (temp); \ 657 \ 658 /* smooth in Y direction */ \ 659 psArray *temprows = psArrayAlloc (Nrange); \ 660 temprows->n = Nrange; \ 661 for (int j = 0; j < Nrange; j++) { \ 662 temp = psVectorAlloc (Nx, PS_TYPE_##TYPE); \ 663 /* zero the output row */ \ 664 memset (temp->data.TYPE, 0, Nx*sizeof(PS_TYPE_##TYPE)); \ 665 for (int n = -j, sum = 0; n < Nrange + 1; n++) { sum += gauss[n]; } \ 666 for (int n = -j; n < Nrange + 1; n++) { \ 667 ps##TYPE *vi = image->data.TYPE[j+n]; \ 668 ps##TYPE *vo = temp->data.TYPE; \ 669 g = gauss[n]; \ 670 for (int i = 0; i < Nx; i++, vi++, vo++) { \ 671 *vo += *vi * g; \ 672 } \ 673 } \ 674 /* save output rows on temp array */ \ 675 temprows->data[j] = temp; \ 676 } \ 677 for (int j = Nrange; j < Ny - Nrange; j++) { \ 678 /* save the Nrange-offset output row, then zero */ \ 679 Nr = j % Nrange; \ 680 temp = temprows->data[Nr]; \ 681 memcpy (image->data.TYPE[j-Nrange], temp->data.TYPE, Nx*sizeof(ps##TYPE)); \ 682 memset (temp->data.TYPE, 0, Nx*sizeof(PS_TYPE_##TYPE)); \ 683 for (int n = -Nrange; n < Nrange + 1; n++) { \ 684 ps##TYPE *vi = image->data.TYPE[j+n]; \ 685 ps##TYPE *vo = temp->data.TYPE; \ 686 g = gauss[n]; \ 687 for (int i = 0; i < Nx; i++, vi++, vo++) { \ 688 *vo += *vi * g; \ 689 } \ 690 } \ 691 } \ 692 for (int j = Ny - Nrange; j < Ny; j++) { \ 693 /* save the Nrange-offset output row, then zero */ \ 694 Nr = j % Nrange; \ 695 temp = temprows->data[Nr]; \ 696 memcpy (image->data.TYPE[j-Nrange], temp->data.TYPE, Nx*sizeof(ps##TYPE)); \ 697 memset (temp->data.TYPE, 0, Nx*sizeof(PS_TYPE_##TYPE)); \ 698 for (int n = -Nrange, sum = 0; n < Ny - j - 1; n++) { sum += gauss[n]; } \ 699 for (int n = -Nrange; n < Ny - j - 1; n++) { \ 700 ps##TYPE *vi = image->data.TYPE[j+n]; \ 701 ps##TYPE *vo = temp->data.TYPE; \ 702 g = gauss[n]; \ 703 for (int i = 0; i < Nx; i++, vi++, vo++) { \ 704 *vo += *vi * g; \ 705 } \ 706 } \ 707 } \ 708 for (int j = Ny; j < Ny + Nrange; j++) { \ 709 /* save the Nrange-offset output row, then zero */ \ 710 Nr = j % Nrange; \ 711 temp = temprows->data[Nr]; \ 712 memcpy (image->data.TYPE[j-Nrange], temp->data.TYPE, Nx*sizeof(ps##TYPE)); \ 713 } \ 714 psFree (temprows); \ 715 psFree (gaussnorm); \ 716 break; \ 717 } 718 719 switch (image->type.type) { 720 IMAGESMOOTH_CASE(F32); 721 IMAGESMOOTH_CASE(F64); 722 default: { 723 char* typeStr; 724 PS_TYPE_NAME(typeStr,image->type.type); 725 psError(PS_ERR_BAD_PARAMETER_TYPE, true, 726 PS_ERRORTEXT_psImage_IMAGE_TYPE_UNSUPPORTED, 727 typeStr); 728 return false; 729 } 730 } 731 return true; 732 } 733 734 # endif
Note:
See TracChangeset
for help on using the changeset viewer.
