Changeset 1385 for trunk/psLib/src/image/psImageManip.c
- Timestamp:
- Aug 4, 2004, 1:37:39 PM (22 years ago)
- File:
-
- 1 edited
-
trunk/psLib/src/image/psImageManip.c (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psLib/src/image/psImageManip.c
r1319 r1385 10 10 * @author Ross Harman, MHPCC 11 11 * 12 * @version $Revision: 1. 8$ $Name: not supported by cvs2svn $13 * @date $Date: 2004-0 7-29 01:20:10$12 * @version $Revision: 1.9 $ $Name: not supported by cvs2svn $ 13 * @date $Date: 2004-08-04 23:37:39 $ 14 14 * 15 15 * Copyright 2004 Maui High Performance Computing Center, University of Hawaii … … 582 582 return NULL; 583 583 } 584 } else if (fabsf(angle-180.0f) < FLT_EPSILON) { 585 // perform 1/2 rotate 586 int numRows = in->numRows; 587 int lastRow = numRows - 1; 588 int numCols = in->numCols; 589 int lastCol = numCols - 1; 590 psElemType type = in->type.type; 591 out = psImageRecycle(out,numCols,numRows,type); 592 593 #define PSIMAGE_ROTATE_180_CASE(TYPE) \ 594 case PS_TYPE_##TYPE: { \ 595 for (int row=0;row<numRows;row++) { \ 596 ps##TYPE* outRow = out->data.TYPE[row]; \ 597 ps##TYPE* inRow = in->data.TYPE[lastRow-row]; \ 598 for (int col=0;col<numCols;col++) { \ 599 outRow[col] = inRow[lastCol - col]; \ 584 } else 585 if (fabsf(angle-180.0f) < FLT_EPSILON) { 586 // perform 1/2 rotate 587 int numRows = in->numRows; 588 int lastRow = numRows - 1; 589 int numCols = in->numCols; 590 int lastCol = numCols - 1; 591 psElemType type = in->type.type; 592 out = psImageRecycle(out,numCols,numRows,type); 593 594 #define PSIMAGE_ROTATE_180_CASE(TYPE) \ 595 case PS_TYPE_##TYPE: { \ 596 for (int row=0;row<numRows;row++) { \ 597 ps##TYPE* outRow = out->data.TYPE[row]; \ 598 ps##TYPE* inRow = in->data.TYPE[lastRow-row]; \ 599 for (int col=0;col<numCols;col++) { \ 600 outRow[col] = inRow[lastCol - col]; \ 601 } \ 600 602 } \ 601 603 } \ 602 } \ 603 break; 604 605 switch (type) { 606 PSIMAGE_ROTATE_180_CASE(U8); 607 PSIMAGE_ROTATE_180_CASE(U16); 608 PSIMAGE_ROTATE_180_CASE(U32); 609 PSIMAGE_ROTATE_180_CASE(U64); 610 PSIMAGE_ROTATE_180_CASE(S8); 611 PSIMAGE_ROTATE_180_CASE(S16); 612 PSIMAGE_ROTATE_180_CASE(S32); 613 PSIMAGE_ROTATE_180_CASE(S64); 614 PSIMAGE_ROTATE_180_CASE(F32); 615 PSIMAGE_ROTATE_180_CASE(F64); 616 PSIMAGE_ROTATE_180_CASE(C32); 617 PSIMAGE_ROTATE_180_CASE(C64); 618 default: 619 psError(__func__,"Unsupported type (%d)",type); 620 psFree(out); 621 return NULL; 622 } 623 } else if (fabsf(angle-270.0f) < FLT_EPSILON) { 624 // perform 1/4 rotate clockwise 625 int numRows = in->numCols; 626 int lastRow = numRows - 1; 627 int numCols = in->numRows; 628 psElemType type = in->type.type; 629 out = psImageRecycle(out,numCols,numRows,type); 630 631 #define PSIMAGE_ROTATE_RIGHT_90(TYPE) \ 632 case PS_TYPE_##TYPE: { \ 633 ps##TYPE** inData = in->data.TYPE; \ 634 for (int row=0;row<numRows;row++) { \ 635 ps##TYPE* outRow = out->data.TYPE[row]; \ 636 for (int col=0;col<numCols;col++) { \ 637 outRow[col] = inData[col][lastRow-row]; \ 604 break; 605 606 switch (type) { 607 PSIMAGE_ROTATE_180_CASE(U8); 608 PSIMAGE_ROTATE_180_CASE(U16); 609 PSIMAGE_ROTATE_180_CASE(U32); 610 PSIMAGE_ROTATE_180_CASE(U64); 611 PSIMAGE_ROTATE_180_CASE(S8); 612 PSIMAGE_ROTATE_180_CASE(S16); 613 PSIMAGE_ROTATE_180_CASE(S32); 614 PSIMAGE_ROTATE_180_CASE(S64); 615 PSIMAGE_ROTATE_180_CASE(F32); 616 PSIMAGE_ROTATE_180_CASE(F64); 617 PSIMAGE_ROTATE_180_CASE(C32); 618 PSIMAGE_ROTATE_180_CASE(C64); 619 default: 620 psError(__func__,"Unsupported type (%d)",type); 621 psFree(out); 622 return NULL; 623 } 624 } else 625 if (fabsf(angle-270.0f) < FLT_EPSILON) { 626 // perform 1/4 rotate clockwise 627 int numRows = in->numCols; 628 int lastRow = numRows - 1; 629 int numCols = in->numRows; 630 psElemType type = in->type.type; 631 out = psImageRecycle(out,numCols,numRows,type); 632 633 #define PSIMAGE_ROTATE_RIGHT_90(TYPE) \ 634 case PS_TYPE_##TYPE: { \ 635 ps##TYPE** inData = in->data.TYPE; \ 636 for (int row=0;row<numRows;row++) { \ 637 ps##TYPE* outRow = out->data.TYPE[row]; \ 638 for (int col=0;col<numCols;col++) { \ 639 outRow[col] = inData[col][lastRow-row]; \ 640 } \ 641 } \ 638 642 } \ 639 } \ 640 } \ 641 break; 642 643 switch (type) { 644 PSIMAGE_ROTATE_RIGHT_90(U8); 645 PSIMAGE_ROTATE_RIGHT_90(U16); 646 PSIMAGE_ROTATE_RIGHT_90(U32); 647 PSIMAGE_ROTATE_RIGHT_90(U64); 648 PSIMAGE_ROTATE_RIGHT_90(S8); 649 PSIMAGE_ROTATE_RIGHT_90(S16); 650 PSIMAGE_ROTATE_RIGHT_90(S32); 651 PSIMAGE_ROTATE_RIGHT_90(S64); 652 PSIMAGE_ROTATE_RIGHT_90(F32); 653 PSIMAGE_ROTATE_RIGHT_90(F64); 654 PSIMAGE_ROTATE_RIGHT_90(C32); 655 PSIMAGE_ROTATE_RIGHT_90(C64); 656 default: 657 psError(__func__,"Unsupported type (%d)",type); 658 psFree(out); 659 return NULL; 660 } 661 } else if (fabsf(angle) < FLT_EPSILON) { 662 out = psImageCopy(out,in,in->type.type); 663 } else { 664 psElemType type = in->type.type; 665 int numRows = in->numRows; 666 int numCols = in->numCols; 667 double centerX = (float)(numCols) / 2.0f; 668 float centerY = (float)(numRows) / 2.0f; 669 float t = angle*(3.14159265358f/180.0f); 670 float cosT = cosf(t); 671 float sinT = sinf(t); 672 673 // calculate the corners of the rotated image so we know the proper output image size. 674 // x' = x cos(t) + y sin(t); i.e, x' = (x-centerX)*cosT + (y-centerY)*sinT; 675 // y' = y cos(t) - x sin(t); i.e. y' = (y-centerY)*cosT - (x-centerX)*sinT; 676 677 678 int outCols = ceil(abs(numCols*cosT)+abs(numRows*sinT))+1; 679 int outRows = ceil(abs(numCols*sinT)+abs(numRows*cosT))+1; 680 float minX = (float)outCols/-2.0f; 681 int intMinY = outRows/-2; 682 683 out = psImageRecycle(out,outCols,outRows,type); 684 685 /* optimized public domain rotation routine by Karl Lager 686 float cosT,sinT; 687 cosT = cos(t); 688 sinT = sin(t); 689 for (y = min_y; y <= max_y; y++) 690 { x' = min_x * cosT + y * sinT + x1'; 691 y' = y * cosT - min_x * sinT + y1'; 692 for (x = min_x; x <= max_x; x++) 693 { if (x', y') is in the bounds of the bitmap, 694 get pixel(x', y') and plot the pixel to 695 (x, y) on screen. 696 x' += cosT; 697 y' -= sinT; 698 } 699 } 700 */ 701 702 // precalculate some figures that are used within loop 703 float minXTimesCosTPlusCenterX = minX*cosT+centerX; 704 float CenterYMinusminXTimesSinT = centerY-minX*sinT; 705 706 #define PSIMAGE_ROTATE_ARBITRARY_LOOP(TYPE,MODE) { \ 707 if (unexposedValue < PS_MIN_##TYPE || unexposedValue > PS_MAX_##TYPE) { \ 708 psError(__func__,"The given unexposedValue (%g) is outside of the " \ 709 "image type's range (%g->%g).", \ 710 unexposedValue, (double)PS_MIN_##TYPE,(double)PS_MAX_##TYPE); \ 711 psFree(out); \ 712 out = NULL; \ 713 break; \ 714 } \ 715 float inX; \ 716 float inY; \ 717 ps##TYPE* outRow; \ 718 for (int y = 0; y < outRows; y++) { \ 719 inX = minXTimesCosTPlusCenterX + (y+intMinY) * sinT; \ 720 inY = CenterYMinusminXTimesSinT + (y+intMinY) * cosT; \ 721 outRow = out->data.TYPE[y]; \ 722 for (int x = 0; x < outCols; x++) { \ 723 outRow[x] = p_psImagePixelInterpolate##MODE##_##TYPE(in,inX,inY,unexposedValue); \ 724 inX += cosT; \ 725 inY -= sinT; \ 726 } \ 727 } \ 728 } 729 730 #define PSIMAGE_ROTATE_ARBITRARY_CASE(MODE) \ 731 case PS_INTERPOLATE_##MODE: \ 732 switch (type) { \ 733 case PS_TYPE_U8: \ 734 PSIMAGE_ROTATE_ARBITRARY_LOOP(U8,MODE); \ 735 break; \ 736 case PS_TYPE_U16: \ 737 PSIMAGE_ROTATE_ARBITRARY_LOOP(U16,MODE); \ 738 break; \ 739 case PS_TYPE_U32: \ 740 PSIMAGE_ROTATE_ARBITRARY_LOOP(U32,MODE); \ 741 break; \ 742 case PS_TYPE_U64: \ 743 PSIMAGE_ROTATE_ARBITRARY_LOOP(U64,MODE); \ 744 break; \ 745 case PS_TYPE_S8: \ 746 PSIMAGE_ROTATE_ARBITRARY_LOOP(S8,MODE); \ 747 break; \ 748 case PS_TYPE_S16: \ 749 PSIMAGE_ROTATE_ARBITRARY_LOOP(S16,MODE); \ 750 break; \ 751 case PS_TYPE_S32: \ 752 PSIMAGE_ROTATE_ARBITRARY_LOOP(S32,MODE); \ 753 break; \ 754 case PS_TYPE_S64: \ 755 PSIMAGE_ROTATE_ARBITRARY_LOOP(S64,MODE); \ 756 break; \ 757 case PS_TYPE_F32: \ 758 PSIMAGE_ROTATE_ARBITRARY_LOOP(F32,MODE); \ 759 break; \ 760 case PS_TYPE_F64: \ 761 PSIMAGE_ROTATE_ARBITRARY_LOOP(F64,MODE); \ 762 break; \ 763 case PS_TYPE_C32: \ 764 PSIMAGE_ROTATE_ARBITRARY_LOOP(C32,MODE); \ 765 break; \ 766 case PS_TYPE_C64: \ 767 PSIMAGE_ROTATE_ARBITRARY_LOOP(C64,MODE); \ 768 break; \ 769 default: \ 770 psError(__func__,"Image type (%d) not supported",type); \ 771 psFree(out); \ 772 out = NULL; \ 773 } \ 774 break; 775 776 switch (mode) { 777 PSIMAGE_ROTATE_ARBITRARY_CASE(FLAT); 778 PSIMAGE_ROTATE_ARBITRARY_CASE(BILINEAR); 779 default: 780 psError(__func__,"Unsupported interpolation mode (%d)",mode); 781 psFree(out); 782 out = NULL; 783 } 784 } 643 break; 644 645 switch (type) { 646 PSIMAGE_ROTATE_RIGHT_90(U8); 647 PSIMAGE_ROTATE_RIGHT_90(U16); 648 PSIMAGE_ROTATE_RIGHT_90(U32); 649 PSIMAGE_ROTATE_RIGHT_90(U64); 650 PSIMAGE_ROTATE_RIGHT_90(S8); 651 PSIMAGE_ROTATE_RIGHT_90(S16); 652 PSIMAGE_ROTATE_RIGHT_90(S32); 653 PSIMAGE_ROTATE_RIGHT_90(S64); 654 PSIMAGE_ROTATE_RIGHT_90(F32); 655 PSIMAGE_ROTATE_RIGHT_90(F64); 656 PSIMAGE_ROTATE_RIGHT_90(C32); 657 PSIMAGE_ROTATE_RIGHT_90(C64); 658 default: 659 psError(__func__,"Unsupported type (%d)",type); 660 psFree(out); 661 return NULL; 662 } 663 } else 664 if (fabsf(angle) < FLT_EPSILON) { 665 out = psImageCopy(out,in,in->type.type); 666 } else { 667 psElemType type = in->type.type; 668 int numRows = in->numRows; 669 int numCols = in->numCols; 670 double centerX = (float)(numCols) / 2.0f; 671 float centerY = (float)(numRows) / 2.0f; 672 float t = angle*(3.14159265358f/180.0f); 673 float cosT = cosf(t); 674 float sinT = sinf(t); 675 676 // calculate the corners of the rotated image so we know the proper output image size. 677 // x' = x cos(t) + y sin(t); i.e, x' = (x-centerX)*cosT + (y-centerY)*sinT; 678 // y' = y cos(t) - x sin(t); i.e. y' = (y-centerY)*cosT - (x-centerX)*sinT; 679 680 681 int outCols = ceil(abs(numCols*cosT)+abs(numRows*sinT))+1; 682 int outRows = ceil(abs(numCols*sinT)+abs(numRows*cosT))+1; 683 float minX = (float)outCols/-2.0f; 684 int intMinY = outRows/-2; 685 686 out = psImageRecycle(out,outCols,outRows,type); 687 688 /* optimized public domain rotation routine by Karl Lager 689 float cosT,sinT; 690 cosT = cos(t); 691 sinT = sin(t); 692 for (y = min_y; y <= max_y; y++) 693 { x' = min_x * cosT + y * sinT + x1'; 694 y' = y * cosT - min_x * sinT + y1'; 695 for (x = min_x; x <= max_x; x++) 696 { if (x', y') is in the bounds of the bitmap, 697 get pixel(x', y') and plot the pixel to 698 (x, y) on screen. 699 x' += cosT; 700 y' -= sinT; 701 } 702 } 703 */ 704 705 // precalculate some figures that are used within loop 706 float minXTimesCosTPlusCenterX = minX*cosT+centerX; 707 float CenterYMinusminXTimesSinT = centerY-minX*sinT; 708 709 #define PSIMAGE_ROTATE_ARBITRARY_LOOP(TYPE,MODE) { \ 710 if (unexposedValue < PS_MIN_##TYPE || unexposedValue > PS_MAX_##TYPE) { \ 711 psError(__func__,"The given unexposedValue (%g) is outside of the " \ 712 "image type's range (%g->%g).", \ 713 unexposedValue, (double)PS_MIN_##TYPE,(double)PS_MAX_##TYPE); \ 714 psFree(out); \ 715 out = NULL; \ 716 break; \ 717 } \ 718 float inX; \ 719 float inY; \ 720 ps##TYPE* outRow; \ 721 for (int y = 0; y < outRows; y++) { \ 722 inX = minXTimesCosTPlusCenterX + (y+intMinY) * sinT; \ 723 inY = CenterYMinusminXTimesSinT + (y+intMinY) * cosT; \ 724 outRow = out->data.TYPE[y]; \ 725 for (int x = 0; x < outCols; x++) { \ 726 outRow[x] = p_psImagePixelInterpolate##MODE##_##TYPE(in,inX,inY,unexposedValue); \ 727 inX += cosT; \ 728 inY -= sinT; \ 729 } \ 730 } \ 731 } 732 733 #define PSIMAGE_ROTATE_ARBITRARY_CASE(MODE) \ 734 case PS_INTERPOLATE_##MODE: \ 735 switch (type) { \ 736 case PS_TYPE_U8: \ 737 PSIMAGE_ROTATE_ARBITRARY_LOOP(U8,MODE); \ 738 break; \ 739 case PS_TYPE_U16: \ 740 PSIMAGE_ROTATE_ARBITRARY_LOOP(U16,MODE); \ 741 break; \ 742 case PS_TYPE_U32: \ 743 PSIMAGE_ROTATE_ARBITRARY_LOOP(U32,MODE); \ 744 break; \ 745 case PS_TYPE_U64: \ 746 PSIMAGE_ROTATE_ARBITRARY_LOOP(U64,MODE); \ 747 break; \ 748 case PS_TYPE_S8: \ 749 PSIMAGE_ROTATE_ARBITRARY_LOOP(S8,MODE); \ 750 break; \ 751 case PS_TYPE_S16: \ 752 PSIMAGE_ROTATE_ARBITRARY_LOOP(S16,MODE); \ 753 break; \ 754 case PS_TYPE_S32: \ 755 PSIMAGE_ROTATE_ARBITRARY_LOOP(S32,MODE); \ 756 break; \ 757 case PS_TYPE_S64: \ 758 PSIMAGE_ROTATE_ARBITRARY_LOOP(S64,MODE); \ 759 break; \ 760 case PS_TYPE_F32: \ 761 PSIMAGE_ROTATE_ARBITRARY_LOOP(F32,MODE); \ 762 break; \ 763 case PS_TYPE_F64: \ 764 PSIMAGE_ROTATE_ARBITRARY_LOOP(F64,MODE); \ 765 break; \ 766 case PS_TYPE_C32: \ 767 PSIMAGE_ROTATE_ARBITRARY_LOOP(C32,MODE); \ 768 break; \ 769 case PS_TYPE_C64: \ 770 PSIMAGE_ROTATE_ARBITRARY_LOOP(C64,MODE); \ 771 break; \ 772 default: \ 773 psError(__func__,"Image type (%d) not supported",type); \ 774 psFree(out); \ 775 out = NULL; \ 776 } \ 777 break; 778 779 switch (mode) { 780 PSIMAGE_ROTATE_ARBITRARY_CASE(FLAT); 781 PSIMAGE_ROTATE_ARBITRARY_CASE(BILINEAR); 782 default: 783 psError(__func__,"Unsupported interpolation mode (%d)",mode); 784 psFree(out); 785 out = NULL; 786 } 787 } 785 788 786 789 return out;
Note:
See TracChangeset
for help on using the changeset viewer.
