Mercurial > hg > orthanc
comparison Core/Images/ImageProcessing.cpp @ 3227:53bb1f4b3844
added Invert for Grayscale16
author | am@osimis.io |
---|---|
date | Thu, 14 Feb 2019 16:22:52 +0100 |
parents | 4e43e67f8ecf |
children | 3ca924140de6 |
comparison
equal
deleted
inserted
replaced
3226:45e1631febbb | 3227:53bb1f4b3844 |
---|---|
18 * modify file(s) with this exception, you may extend this exception to | 18 * modify file(s) with this exception, you may extend this exception to |
19 * your version of the file(s), but you are not obligated to do so. If | 19 * your version of the file(s), but you are not obligated to do so. If |
20 * you do not wish to do so, delete this exception statement from your | 20 * you do not wish to do so, delete this exception statement from your |
21 * version. If you delete this exception statement from all source files | 21 * version. If you delete this exception statement from all source files |
22 * in the program, then also delete it here. | 22 * in the program, then also delete it here. |
23 * | 23 * |
24 * This program is distributed in the hope that it will be useful, but | 24 * This program is distributed in the hope that it will be useful, but |
25 * WITHOUT ANY WARRANTY; without even the implied warranty of | 25 * WITHOUT ANY WARRANTY; without even the implied warranty of |
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
27 * General Public License for more details. | 27 * General Public License for more details. |
28 * | 28 * |
145 | 145 |
146 for (unsigned int x = 0; x < width; x++, t++, s += 3) | 146 for (unsigned int x = 0; x < width; x++, t++, s += 3) |
147 { | 147 { |
148 // Y = 0.2126 R + 0.7152 G + 0.0722 B | 148 // Y = 0.2126 R + 0.7152 G + 0.0722 B |
149 int32_t v = (2126 * static_cast<int32_t>(s[0]) + | 149 int32_t v = (2126 * static_cast<int32_t>(s[0]) + |
150 7152 * static_cast<int32_t>(s[1]) + | 150 7152 * static_cast<int32_t>(s[1]) + |
151 0722 * static_cast<int32_t>(s[2])) / 10000; | 151 0722 * static_cast<int32_t>(s[2])) / 10000; |
152 | 152 |
153 if (static_cast<int32_t>(v) < static_cast<int32_t>(minValue)) | 153 if (static_cast<int32_t>(v) < static_cast<int32_t>(minValue)) |
154 { | 154 { |
155 *t = minValue; | 155 *t = minValue; |
156 } | 156 } |
166 } | 166 } |
167 } | 167 } |
168 | 168 |
169 | 169 |
170 static void MemsetZeroInternal(ImageAccessor& image) | 170 static void MemsetZeroInternal(ImageAccessor& image) |
171 { | 171 { |
172 const unsigned int height = image.GetHeight(); | 172 const unsigned int height = image.GetHeight(); |
173 const size_t lineSize = image.GetBytesPerPixel() * image.GetWidth(); | 173 const size_t lineSize = image.GetBytesPerPixel() * image.GetWidth(); |
174 const size_t pitch = image.GetPitch(); | 174 const size_t pitch = image.GetPitch(); |
175 | 175 |
176 uint8_t *p = reinterpret_cast<uint8_t*>(image.GetBuffer()); | 176 uint8_t *p = reinterpret_cast<uint8_t*>(image.GetBuffer()); |
533 const uint8_t* p = reinterpret_cast<const uint8_t*>(source.GetConstRow(y)); | 533 const uint8_t* p = reinterpret_cast<const uint8_t*>(source.GetConstRow(y)); |
534 uint8_t* q = reinterpret_cast<uint8_t*>(target.GetRow(y)); | 534 uint8_t* q = reinterpret_cast<uint8_t*>(target.GetRow(y)); |
535 for (unsigned int x = 0; x < width; x++, q++) | 535 for (unsigned int x = 0; x < width; x++, q++) |
536 { | 536 { |
537 *q = static_cast<uint8_t>((2126 * static_cast<uint32_t>(p[0]) + | 537 *q = static_cast<uint8_t>((2126 * static_cast<uint32_t>(p[0]) + |
538 7152 * static_cast<uint32_t>(p[1]) + | 538 7152 * static_cast<uint32_t>(p[1]) + |
539 0722 * static_cast<uint32_t>(p[2])) / 10000); | 539 0722 * static_cast<uint32_t>(p[2])) / 10000); |
540 p += 4; | 540 p += 4; |
541 } | 541 } |
542 } | 542 } |
543 | 543 |
544 return; | 544 return; |
552 const uint8_t* p = reinterpret_cast<const uint8_t*>(source.GetConstRow(y)); | 552 const uint8_t* p = reinterpret_cast<const uint8_t*>(source.GetConstRow(y)); |
553 uint8_t* q = reinterpret_cast<uint8_t*>(target.GetRow(y)); | 553 uint8_t* q = reinterpret_cast<uint8_t*>(target.GetRow(y)); |
554 for (unsigned int x = 0; x < width; x++, q++) | 554 for (unsigned int x = 0; x < width; x++, q++) |
555 { | 555 { |
556 *q = static_cast<uint8_t>((2126 * static_cast<uint32_t>(p[2]) + | 556 *q = static_cast<uint8_t>((2126 * static_cast<uint32_t>(p[2]) + |
557 7152 * static_cast<uint32_t>(p[1]) + | 557 7152 * static_cast<uint32_t>(p[1]) + |
558 0722 * static_cast<uint32_t>(p[0])) / 10000); | 558 0722 * static_cast<uint32_t>(p[0])) / 10000); |
559 p += 4; | 559 p += 4; |
560 } | 560 } |
561 } | 561 } |
562 | 562 |
563 return; | 563 return; |
786 void ImageProcessing::Set(ImageAccessor& image, | 786 void ImageProcessing::Set(ImageAccessor& image, |
787 int64_t value) | 787 int64_t value) |
788 { | 788 { |
789 switch (image.GetFormat()) | 789 switch (image.GetFormat()) |
790 { | 790 { |
791 case PixelFormat_Grayscale8: | 791 case PixelFormat_Grayscale8: |
792 SetInternal<uint8_t>(image, value); | 792 SetInternal<uint8_t>(image, value); |
793 return; | 793 return; |
794 | 794 |
795 case PixelFormat_Grayscale16: | 795 case PixelFormat_Grayscale16: |
796 SetInternal<uint16_t>(image, value); | 796 SetInternal<uint16_t>(image, value); |
797 return; | 797 return; |
798 | 798 |
799 case PixelFormat_Grayscale32: | 799 case PixelFormat_Grayscale32: |
800 SetInternal<uint32_t>(image, value); | 800 SetInternal<uint32_t>(image, value); |
801 return; | 801 return; |
802 | 802 |
803 case PixelFormat_Grayscale64: | 803 case PixelFormat_Grayscale64: |
804 SetInternal<uint64_t>(image, value); | 804 SetInternal<uint64_t>(image, value); |
805 return; | 805 return; |
806 | 806 |
807 case PixelFormat_SignedGrayscale16: | 807 case PixelFormat_SignedGrayscale16: |
808 SetInternal<int16_t>(image, value); | 808 SetInternal<int16_t>(image, value); |
809 return; | 809 return; |
810 | 810 |
811 case PixelFormat_Float32: | 811 case PixelFormat_Float32: |
812 assert(sizeof(float) == 4); | 812 assert(sizeof(float) == 4); |
813 SetInternal<float>(image, value); | 813 SetInternal<float>(image, value); |
814 return; | 814 return; |
815 | 815 |
816 default: | 816 default: |
817 throw OrthancException(ErrorCode_NotImplemented); | 817 throw OrthancException(ErrorCode_NotImplemented); |
818 } | 818 } |
819 } | 819 } |
820 | 820 |
821 | 821 |
822 void ImageProcessing::Set(ImageAccessor& image, | 822 void ImageProcessing::Set(ImageAccessor& image, |
828 uint8_t p[4]; | 828 uint8_t p[4]; |
829 unsigned int size; | 829 unsigned int size; |
830 | 830 |
831 switch (image.GetFormat()) | 831 switch (image.GetFormat()) |
832 { | 832 { |
833 case PixelFormat_RGBA32: | 833 case PixelFormat_RGBA32: |
834 p[0] = red; | 834 p[0] = red; |
835 p[1] = green; | 835 p[1] = green; |
836 p[2] = blue; | 836 p[2] = blue; |
837 p[3] = alpha; | 837 p[3] = alpha; |
838 size = 4; | 838 size = 4; |
839 break; | 839 break; |
840 | 840 |
841 case PixelFormat_BGRA32: | 841 case PixelFormat_BGRA32: |
842 p[0] = blue; | 842 p[0] = blue; |
843 p[1] = green; | 843 p[1] = green; |
844 p[2] = red; | 844 p[2] = red; |
845 p[3] = alpha; | 845 p[3] = alpha; |
846 size = 4; | 846 size = 4; |
847 break; | 847 break; |
848 | 848 |
849 case PixelFormat_RGB24: | 849 case PixelFormat_RGB24: |
850 p[0] = red; | 850 p[0] = red; |
851 p[1] = green; | 851 p[1] = green; |
852 p[2] = blue; | 852 p[2] = blue; |
853 size = 3; | 853 size = 3; |
854 break; | 854 break; |
855 | 855 |
856 default: | 856 default: |
857 throw OrthancException(ErrorCode_NotImplemented); | 857 throw OrthancException(ErrorCode_NotImplemented); |
858 } | 858 } |
859 | 859 |
860 const unsigned int width = image.GetWidth(); | 860 const unsigned int width = image.GetWidth(); |
861 const unsigned int height = image.GetHeight(); | 861 const unsigned int height = image.GetHeight(); |
862 | 862 |
863 for (unsigned int y = 0; y < height; y++) | 863 for (unsigned int y = 0; y < height; y++) |
896 int64_t& maxValue, | 896 int64_t& maxValue, |
897 const ImageAccessor& image) | 897 const ImageAccessor& image) |
898 { | 898 { |
899 switch (image.GetFormat()) | 899 switch (image.GetFormat()) |
900 { | 900 { |
901 case PixelFormat_Grayscale8: | 901 case PixelFormat_Grayscale8: |
902 { | 902 { |
903 uint8_t a, b; | 903 uint8_t a, b; |
904 GetMinMaxValueInternal<uint8_t>(a, b, image); | 904 GetMinMaxValueInternal<uint8_t>(a, b, image); |
905 minValue = a; | 905 minValue = a; |
906 maxValue = b; | 906 maxValue = b; |
907 break; | 907 break; |
908 } | 908 } |
909 | 909 |
910 case PixelFormat_Grayscale16: | 910 case PixelFormat_Grayscale16: |
911 { | 911 { |
912 uint16_t a, b; | 912 uint16_t a, b; |
913 GetMinMaxValueInternal<uint16_t>(a, b, image); | 913 GetMinMaxValueInternal<uint16_t>(a, b, image); |
914 minValue = a; | 914 minValue = a; |
915 maxValue = b; | 915 maxValue = b; |
916 break; | 916 break; |
917 } | 917 } |
918 | 918 |
919 case PixelFormat_Grayscale32: | 919 case PixelFormat_Grayscale32: |
920 { | 920 { |
921 uint32_t a, b; | 921 uint32_t a, b; |
922 GetMinMaxValueInternal<uint32_t>(a, b, image); | 922 GetMinMaxValueInternal<uint32_t>(a, b, image); |
923 minValue = a; | 923 minValue = a; |
924 maxValue = b; | 924 maxValue = b; |
925 break; | 925 break; |
926 } | 926 } |
927 | 927 |
928 case PixelFormat_SignedGrayscale16: | 928 case PixelFormat_SignedGrayscale16: |
929 { | 929 { |
930 int16_t a, b; | 930 int16_t a, b; |
931 GetMinMaxValueInternal<int16_t>(a, b, image); | 931 GetMinMaxValueInternal<int16_t>(a, b, image); |
932 minValue = a; | 932 minValue = a; |
933 maxValue = b; | 933 maxValue = b; |
934 break; | 934 break; |
935 } | 935 } |
936 | 936 |
937 default: | 937 default: |
938 throw OrthancException(ErrorCode_NotImplemented); | 938 throw OrthancException(ErrorCode_NotImplemented); |
939 } | 939 } |
940 } | 940 } |
941 | 941 |
942 | 942 |
943 void ImageProcessing::GetMinMaxFloatValue(float& minValue, | 943 void ImageProcessing::GetMinMaxFloatValue(float& minValue, |
944 float& maxValue, | 944 float& maxValue, |
945 const ImageAccessor& image) | 945 const ImageAccessor& image) |
946 { | 946 { |
947 switch (image.GetFormat()) | 947 switch (image.GetFormat()) |
948 { | 948 { |
949 case PixelFormat_Float32: | 949 case PixelFormat_Float32: |
950 { | 950 { |
951 assert(sizeof(float) == 4); | 951 assert(sizeof(float) == 4); |
952 float a, b; | 952 float a, b; |
953 GetMinMaxValueInternal<float>(a, b, image); | 953 GetMinMaxValueInternal<float>(a, b, image); |
954 minValue = a; | 954 minValue = a; |
955 maxValue = b; | 955 maxValue = b; |
956 break; | 956 break; |
957 } | 957 } |
958 | 958 |
959 default: | 959 default: |
960 throw OrthancException(ErrorCode_NotImplemented); | 960 throw OrthancException(ErrorCode_NotImplemented); |
961 } | 961 } |
962 } | 962 } |
963 | 963 |
964 | 964 |
965 | 965 |
966 void ImageProcessing::AddConstant(ImageAccessor& image, | 966 void ImageProcessing::AddConstant(ImageAccessor& image, |
967 int64_t value) | 967 int64_t value) |
968 { | 968 { |
969 switch (image.GetFormat()) | 969 switch (image.GetFormat()) |
970 { | 970 { |
971 case PixelFormat_Grayscale8: | 971 case PixelFormat_Grayscale8: |
972 AddConstantInternal<uint8_t>(image, value); | 972 AddConstantInternal<uint8_t>(image, value); |
973 return; | 973 return; |
974 | 974 |
975 case PixelFormat_Grayscale16: | 975 case PixelFormat_Grayscale16: |
976 AddConstantInternal<uint16_t>(image, value); | 976 AddConstantInternal<uint16_t>(image, value); |
977 return; | 977 return; |
978 | 978 |
979 case PixelFormat_SignedGrayscale16: | 979 case PixelFormat_SignedGrayscale16: |
980 AddConstantInternal<int16_t>(image, value); | 980 AddConstantInternal<int16_t>(image, value); |
981 return; | 981 return; |
982 | 982 |
983 default: | 983 default: |
984 throw OrthancException(ErrorCode_NotImplemented); | 984 throw OrthancException(ErrorCode_NotImplemented); |
985 } | 985 } |
986 } | 986 } |
987 | 987 |
988 | 988 |
989 void ImageProcessing::MultiplyConstant(ImageAccessor& image, | 989 void ImageProcessing::MultiplyConstant(ImageAccessor& image, |
990 float factor, | 990 float factor, |
991 bool useRound) | 991 bool useRound) |
992 { | 992 { |
993 switch (image.GetFormat()) | 993 switch (image.GetFormat()) |
994 { | 994 { |
995 case PixelFormat_Grayscale8: | 995 case PixelFormat_Grayscale8: |
996 if (useRound) | 996 if (useRound) |
997 { | 997 { |
998 MultiplyConstantInternal<uint8_t, true>(image, factor); | 998 MultiplyConstantInternal<uint8_t, true>(image, factor); |
999 } | 999 } |
1000 else | 1000 else |
1001 { | 1001 { |
1002 MultiplyConstantInternal<uint8_t, false>(image, factor); | 1002 MultiplyConstantInternal<uint8_t, false>(image, factor); |
1003 } | 1003 } |
1004 return; | 1004 return; |
1005 | 1005 |
1006 case PixelFormat_Grayscale16: | 1006 case PixelFormat_Grayscale16: |
1007 if (useRound) | 1007 if (useRound) |
1008 { | 1008 { |
1009 MultiplyConstantInternal<uint16_t, true>(image, factor); | 1009 MultiplyConstantInternal<uint16_t, true>(image, factor); |
1010 } | 1010 } |
1011 else | 1011 else |
1012 { | 1012 { |
1013 MultiplyConstantInternal<uint16_t, false>(image, factor); | 1013 MultiplyConstantInternal<uint16_t, false>(image, factor); |
1014 } | 1014 } |
1015 return; | 1015 return; |
1016 | 1016 |
1017 case PixelFormat_SignedGrayscale16: | 1017 case PixelFormat_SignedGrayscale16: |
1018 if (useRound) | 1018 if (useRound) |
1019 { | 1019 { |
1020 MultiplyConstantInternal<int16_t, true>(image, factor); | 1020 MultiplyConstantInternal<int16_t, true>(image, factor); |
1021 } | 1021 } |
1022 else | 1022 else |
1023 { | 1023 { |
1024 MultiplyConstantInternal<int16_t, false>(image, factor); | 1024 MultiplyConstantInternal<int16_t, false>(image, factor); |
1025 } | 1025 } |
1026 return; | 1026 return; |
1027 | 1027 |
1028 default: | 1028 default: |
1029 throw OrthancException(ErrorCode_NotImplemented); | 1029 throw OrthancException(ErrorCode_NotImplemented); |
1030 } | 1030 } |
1031 } | 1031 } |
1032 | 1032 |
1033 | 1033 |
1034 void ImageProcessing::ShiftScale(ImageAccessor& image, | 1034 void ImageProcessing::ShiftScale(ImageAccessor& image, |
1036 float scaling, | 1036 float scaling, |
1037 bool useRound) | 1037 bool useRound) |
1038 { | 1038 { |
1039 switch (image.GetFormat()) | 1039 switch (image.GetFormat()) |
1040 { | 1040 { |
1041 case PixelFormat_Grayscale8: | 1041 case PixelFormat_Grayscale8: |
1042 if (useRound) | 1042 if (useRound) |
1043 { | 1043 { |
1044 ShiftScaleInternal<uint8_t, true>(image, offset, scaling); | 1044 ShiftScaleInternal<uint8_t, true>(image, offset, scaling); |
1045 } | 1045 } |
1046 else | 1046 else |
1047 { | 1047 { |
1048 ShiftScaleInternal<uint8_t, false>(image, offset, scaling); | 1048 ShiftScaleInternal<uint8_t, false>(image, offset, scaling); |
1049 } | 1049 } |
1050 return; | 1050 return; |
1051 | 1051 |
1052 case PixelFormat_Grayscale16: | 1052 case PixelFormat_Grayscale16: |
1053 if (useRound) | 1053 if (useRound) |
1054 { | 1054 { |
1055 ShiftScaleInternal<uint16_t, true>(image, offset, scaling); | 1055 ShiftScaleInternal<uint16_t, true>(image, offset, scaling); |
1056 } | 1056 } |
1057 else | 1057 else |
1058 { | 1058 { |
1059 ShiftScaleInternal<uint16_t, false>(image, offset, scaling); | 1059 ShiftScaleInternal<uint16_t, false>(image, offset, scaling); |
1060 } | 1060 } |
1061 return; | 1061 return; |
1062 | 1062 |
1063 case PixelFormat_SignedGrayscale16: | 1063 case PixelFormat_SignedGrayscale16: |
1064 if (useRound) | 1064 if (useRound) |
1065 { | 1065 { |
1066 ShiftScaleInternal<int16_t, true>(image, offset, scaling); | 1066 ShiftScaleInternal<int16_t, true>(image, offset, scaling); |
1067 } | 1067 } |
1068 else | 1068 else |
1069 { | 1069 { |
1070 ShiftScaleInternal<int16_t, false>(image, offset, scaling); | 1070 ShiftScaleInternal<int16_t, false>(image, offset, scaling); |
1071 } | 1071 } |
1072 return; | 1072 return; |
1073 | 1073 |
1074 default: | 1074 default: |
1075 throw OrthancException(ErrorCode_NotImplemented); | 1075 throw OrthancException(ErrorCode_NotImplemented); |
1076 } | 1076 } |
1077 } | 1077 } |
1078 | 1078 |
1079 | |
1080 void ImageProcessing::Invert(ImageAccessor& image, int64_t maxValue) | |
1081 { | |
1082 const unsigned int width = image.GetWidth(); | |
1083 const unsigned int height = image.GetHeight(); | |
1084 | |
1085 switch (image.GetFormat()) | |
1086 { | |
1087 case PixelFormat_Grayscale16: | |
1088 { | |
1089 uint16_t maxValueUint16 = (uint16_t)maxValue; | |
1090 | |
1091 for (unsigned int y = 0; y < height; y++) | |
1092 { | |
1093 uint16_t* p = reinterpret_cast<uint16_t*>(image.GetRow(y)); | |
1094 | |
1095 for (unsigned int x = 0; x < width; x++, p++) | |
1096 { | |
1097 *p = maxValueUint16 - (*p); | |
1098 } | |
1099 } | |
1100 | |
1101 return; | |
1102 } | |
1103 | |
1104 default: | |
1105 throw OrthancException(ErrorCode_NotImplemented); | |
1106 } | |
1107 | |
1108 } | |
1079 | 1109 |
1080 void ImageProcessing::Invert(ImageAccessor& image) | 1110 void ImageProcessing::Invert(ImageAccessor& image) |
1081 { | 1111 { |
1082 const unsigned int width = image.GetWidth(); | 1112 const unsigned int width = image.GetWidth(); |
1083 const unsigned int height = image.GetHeight(); | 1113 const unsigned int height = image.GetHeight(); |
1084 | 1114 |
1085 switch (image.GetFormat()) | 1115 switch (image.GetFormat()) |
1086 { | 1116 { |
1087 case PixelFormat_Grayscale8: | 1117 case PixelFormat_Grayscale8: |
1088 { | 1118 { |
1089 for (unsigned int y = 0; y < height; y++) | 1119 for (unsigned int y = 0; y < height; y++) |
1090 { | 1120 { |
1091 uint8_t* p = reinterpret_cast<uint8_t*>(image.GetRow(y)); | 1121 uint8_t* p = reinterpret_cast<uint8_t*>(image.GetRow(y)); |
1092 | 1122 |
1093 for (unsigned int x = 0; x < width; x++, p++) | 1123 for (unsigned int x = 0; x < width; x++, p++) |
1094 { | 1124 { |
1095 *p = 255 - (*p); | 1125 *p = 255 - (*p); |
1096 } | 1126 } |
1097 } | 1127 } |
1098 | 1128 |
1099 return; | 1129 return; |
1100 } | 1130 } |
1101 | 1131 |
1102 default: | 1132 default: |
1103 throw OrthancException(ErrorCode_NotImplemented); | 1133 throw OrthancException(ErrorCode_NotImplemented); |
1104 } | 1134 } |
1105 } | 1135 } |
1106 | 1136 |
1107 | 1137 |
1108 | 1138 |
1109 namespace | 1139 namespace |
1111 template <Orthanc::PixelFormat Format> | 1141 template <Orthanc::PixelFormat Format> |
1112 class BresenhamPixelWriter | 1142 class BresenhamPixelWriter |
1113 { | 1143 { |
1114 private: | 1144 private: |
1115 typedef typename PixelTraits<Format>::PixelType PixelType; | 1145 typedef typename PixelTraits<Format>::PixelType PixelType; |
1116 | 1146 |
1117 Orthanc::ImageAccessor& image_; | 1147 Orthanc::ImageAccessor& image_; |
1118 PixelType value_; | 1148 PixelType value_; |
1119 | 1149 |
1120 void PlotLineLow(int x0, | 1150 void PlotLineLow(int x0, |
1121 int y0, | 1151 int y0, |
1142 if (d > 0) | 1172 if (d > 0) |
1143 { | 1173 { |
1144 y = y + yi; | 1174 y = y + yi; |
1145 d = d - 2 * dx; | 1175 d = d - 2 * dx; |
1146 } | 1176 } |
1147 | 1177 |
1148 d = d + 2*dy; | 1178 d = d + 2*dy; |
1149 } | 1179 } |
1150 } | 1180 } |
1151 | 1181 |
1152 void PlotLineHigh(int x0, | 1182 void PlotLineHigh(int x0, |
1155 int y1) | 1185 int y1) |
1156 { | 1186 { |
1157 int dx = x1 - x0; | 1187 int dx = x1 - x0; |
1158 int dy = y1 - y0; | 1188 int dy = y1 - y0; |
1159 int xi = 1; | 1189 int xi = 1; |
1160 | 1190 |
1161 if (dx < 0) | 1191 if (dx < 0) |
1162 { | 1192 { |
1163 xi = -1; | 1193 xi = -1; |
1164 dx = -dx; | 1194 dx = -dx; |
1165 } | 1195 } |
1166 | 1196 |
1167 int d = 2 * dx - dy; | 1197 int d = 2 * dx - dy; |
1168 int x = x0; | 1198 int x = x0; |
1169 | 1199 |
1170 for (int y = y0; y <= y1; y++) | 1200 for (int y = y0; y <= y1; y++) |
1171 { | 1201 { |
1174 if (d > 0) | 1204 if (d > 0) |
1175 { | 1205 { |
1176 x = x + xi; | 1206 x = x + xi; |
1177 d = d - 2 * dy; | 1207 d = d - 2 * dy; |
1178 } | 1208 } |
1179 | 1209 |
1180 d = d + 2 * dx; | 1210 d = d + 2 * dx; |
1181 } | 1211 } |
1182 } | 1212 } |
1183 | 1213 |
1184 public: | 1214 public: |
1214 int x1, | 1244 int x1, |
1215 int y1) | 1245 int y1) |
1216 { | 1246 { |
1217 // This is an implementation of Bresenham's line algorithm | 1247 // This is an implementation of Bresenham's line algorithm |
1218 // https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm#All_cases | 1248 // https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm#All_cases |
1219 | 1249 |
1220 if (abs(y1 - y0) < abs(x1 - x0)) | 1250 if (abs(y1 - y0) < abs(x1 - x0)) |
1221 { | 1251 { |
1222 if (x0 > x1) | 1252 if (x0 > x1) |
1223 { | 1253 { |
1224 PlotLineLow(x1, y1, x0, y0); | 1254 PlotLineLow(x1, y1, x0, y0); |
1250 int x1, | 1280 int x1, |
1251 int y1, | 1281 int y1, |
1252 int64_t value) | 1282 int64_t value) |
1253 { | 1283 { |
1254 switch (image.GetFormat()) | 1284 switch (image.GetFormat()) |
1255 { | 1285 { |
1256 case Orthanc::PixelFormat_Grayscale8: | 1286 case Orthanc::PixelFormat_Grayscale8: |
1257 { | 1287 { |
1258 BresenhamPixelWriter<Orthanc::PixelFormat_Grayscale8> writer(image, value); | 1288 BresenhamPixelWriter<Orthanc::PixelFormat_Grayscale8> writer(image, value); |
1259 writer.DrawSegment(x0, y0, x1, y1); | 1289 writer.DrawSegment(x0, y0, x1, y1); |
1260 break; | 1290 break; |
1261 } | 1291 } |
1262 | 1292 |
1263 case Orthanc::PixelFormat_Grayscale16: | 1293 case Orthanc::PixelFormat_Grayscale16: |
1264 { | 1294 { |
1265 BresenhamPixelWriter<Orthanc::PixelFormat_Grayscale16> writer(image, value); | 1295 BresenhamPixelWriter<Orthanc::PixelFormat_Grayscale16> writer(image, value); |
1266 writer.DrawSegment(x0, y0, x1, y1); | 1296 writer.DrawSegment(x0, y0, x1, y1); |
1267 break; | 1297 break; |
1268 } | 1298 } |
1269 | 1299 |
1270 case Orthanc::PixelFormat_SignedGrayscale16: | 1300 case Orthanc::PixelFormat_SignedGrayscale16: |
1271 { | 1301 { |
1272 BresenhamPixelWriter<Orthanc::PixelFormat_SignedGrayscale16> writer(image, value); | 1302 BresenhamPixelWriter<Orthanc::PixelFormat_SignedGrayscale16> writer(image, value); |
1273 writer.DrawSegment(x0, y0, x1, y1); | 1303 writer.DrawSegment(x0, y0, x1, y1); |
1274 break; | 1304 break; |
1275 } | 1305 } |
1276 | 1306 |
1277 default: | 1307 default: |
1278 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); | 1308 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); |
1279 } | 1309 } |
1280 } | 1310 } |
1281 | 1311 |
1282 | 1312 |
1283 void ImageProcessing::DrawLineSegment(ImageAccessor& image, | 1313 void ImageProcessing::DrawLineSegment(ImageAccessor& image, |
1290 uint8_t blue, | 1320 uint8_t blue, |
1291 uint8_t alpha) | 1321 uint8_t alpha) |
1292 { | 1322 { |
1293 switch (image.GetFormat()) | 1323 switch (image.GetFormat()) |
1294 { | 1324 { |
1295 case Orthanc::PixelFormat_BGRA32: | 1325 case Orthanc::PixelFormat_BGRA32: |
1296 { | 1326 { |
1297 PixelTraits<Orthanc::PixelFormat_BGRA32>::PixelType pixel; | 1327 PixelTraits<Orthanc::PixelFormat_BGRA32>::PixelType pixel; |
1298 pixel.red_ = red; | 1328 pixel.red_ = red; |
1299 pixel.green_ = green; | 1329 pixel.green_ = green; |
1300 pixel.blue_ = blue; | 1330 pixel.blue_ = blue; |
1301 pixel.alpha_ = alpha; | 1331 pixel.alpha_ = alpha; |
1302 | 1332 |
1303 BresenhamPixelWriter<Orthanc::PixelFormat_BGRA32> writer(image, pixel); | 1333 BresenhamPixelWriter<Orthanc::PixelFormat_BGRA32> writer(image, pixel); |
1304 writer.DrawSegment(x0, y0, x1, y1); | 1334 writer.DrawSegment(x0, y0, x1, y1); |
1305 break; | 1335 break; |
1306 } | 1336 } |
1307 | 1337 |
1308 case Orthanc::PixelFormat_RGBA32: | 1338 case Orthanc::PixelFormat_RGBA32: |
1309 { | 1339 { |
1310 PixelTraits<Orthanc::PixelFormat_RGBA32>::PixelType pixel; | 1340 PixelTraits<Orthanc::PixelFormat_RGBA32>::PixelType pixel; |
1311 pixel.red_ = red; | 1341 pixel.red_ = red; |
1312 pixel.green_ = green; | 1342 pixel.green_ = green; |
1313 pixel.blue_ = blue; | 1343 pixel.blue_ = blue; |
1314 pixel.alpha_ = alpha; | 1344 pixel.alpha_ = alpha; |
1315 | 1345 |
1316 BresenhamPixelWriter<Orthanc::PixelFormat_RGBA32> writer(image, pixel); | 1346 BresenhamPixelWriter<Orthanc::PixelFormat_RGBA32> writer(image, pixel); |
1317 writer.DrawSegment(x0, y0, x1, y1); | 1347 writer.DrawSegment(x0, y0, x1, y1); |
1318 break; | 1348 break; |
1319 } | 1349 } |
1320 | 1350 |
1321 case Orthanc::PixelFormat_RGB24: | 1351 case Orthanc::PixelFormat_RGB24: |
1322 { | 1352 { |
1323 PixelTraits<Orthanc::PixelFormat_RGB24>::PixelType pixel; | 1353 PixelTraits<Orthanc::PixelFormat_RGB24>::PixelType pixel; |
1324 pixel.red_ = red; | 1354 pixel.red_ = red; |
1325 pixel.green_ = green; | 1355 pixel.green_ = green; |
1326 pixel.blue_ = blue; | 1356 pixel.blue_ = blue; |
1327 | 1357 |
1328 BresenhamPixelWriter<Orthanc::PixelFormat_RGB24> writer(image, pixel); | 1358 BresenhamPixelWriter<Orthanc::PixelFormat_RGB24> writer(image, pixel); |
1329 writer.DrawSegment(x0, y0, x1, y1); | 1359 writer.DrawSegment(x0, y0, x1, y1); |
1330 break; | 1360 break; |
1331 } | 1361 } |
1332 | 1362 |
1333 default: | 1363 default: |
1334 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); | 1364 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); |
1335 } | 1365 } |
1336 } | 1366 } |
1337 } | 1367 } |