Mercurial > hg > orthanc
comparison Core/Images/ImageProcessing.cpp @ 3499:d8f7c3970e25
more tolerance in ImageProcessing::Set()
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Fri, 23 Aug 2019 17:31:43 +0200 |
parents | e0841192d7d0 |
children | c160eafc42a9 |
comparison
equal
deleted
inserted
replaced
3498:957e06cbe76a | 3499:d8f7c3970e25 |
---|---|
153 | 153 |
154 for (unsigned int x = 0; x < width; x++, t++, s += 3) | 154 for (unsigned int x = 0; x < width; x++, t++, s += 3) |
155 { | 155 { |
156 // Y = 0.2126 R + 0.7152 G + 0.0722 B | 156 // Y = 0.2126 R + 0.7152 G + 0.0722 B |
157 int32_t v = (2126 * static_cast<int32_t>(s[0]) + | 157 int32_t v = (2126 * static_cast<int32_t>(s[0]) + |
158 7152 * static_cast<int32_t>(s[1]) + | 158 7152 * static_cast<int32_t>(s[1]) + |
159 0722 * static_cast<int32_t>(s[2])) / 10000; | 159 0722 * static_cast<int32_t>(s[2])) / 10000; |
160 | 160 |
161 if (static_cast<int32_t>(v) < static_cast<int32_t>(minValue)) | 161 if (static_cast<int32_t>(v) < static_cast<int32_t>(minValue)) |
162 { | 162 { |
163 *t = minValue; | 163 *t = minValue; |
164 } | 164 } |
541 const uint8_t* p = reinterpret_cast<const uint8_t*>(source.GetConstRow(y)); | 541 const uint8_t* p = reinterpret_cast<const uint8_t*>(source.GetConstRow(y)); |
542 uint8_t* q = reinterpret_cast<uint8_t*>(target.GetRow(y)); | 542 uint8_t* q = reinterpret_cast<uint8_t*>(target.GetRow(y)); |
543 for (unsigned int x = 0; x < width; x++, q++) | 543 for (unsigned int x = 0; x < width; x++, q++) |
544 { | 544 { |
545 *q = static_cast<uint8_t>((2126 * static_cast<uint32_t>(p[0]) + | 545 *q = static_cast<uint8_t>((2126 * static_cast<uint32_t>(p[0]) + |
546 7152 * static_cast<uint32_t>(p[1]) + | 546 7152 * static_cast<uint32_t>(p[1]) + |
547 0722 * static_cast<uint32_t>(p[2])) / 10000); | 547 0722 * static_cast<uint32_t>(p[2])) / 10000); |
548 p += 4; | 548 p += 4; |
549 } | 549 } |
550 } | 550 } |
551 | 551 |
552 return; | 552 return; |
560 const uint8_t* p = reinterpret_cast<const uint8_t*>(source.GetConstRow(y)); | 560 const uint8_t* p = reinterpret_cast<const uint8_t*>(source.GetConstRow(y)); |
561 uint8_t* q = reinterpret_cast<uint8_t*>(target.GetRow(y)); | 561 uint8_t* q = reinterpret_cast<uint8_t*>(target.GetRow(y)); |
562 for (unsigned int x = 0; x < width; x++, q++) | 562 for (unsigned int x = 0; x < width; x++, q++) |
563 { | 563 { |
564 *q = static_cast<uint8_t>((2126 * static_cast<uint32_t>(p[2]) + | 564 *q = static_cast<uint8_t>((2126 * static_cast<uint32_t>(p[2]) + |
565 7152 * static_cast<uint32_t>(p[1]) + | 565 7152 * static_cast<uint32_t>(p[1]) + |
566 0722 * static_cast<uint32_t>(p[0])) / 10000); | 566 0722 * static_cast<uint32_t>(p[0])) / 10000); |
567 p += 4; | 567 p += 4; |
568 } | 568 } |
569 } | 569 } |
570 | 570 |
571 return; | 571 return; |
794 void ImageProcessing::Set(ImageAccessor& image, | 794 void ImageProcessing::Set(ImageAccessor& image, |
795 int64_t value) | 795 int64_t value) |
796 { | 796 { |
797 switch (image.GetFormat()) | 797 switch (image.GetFormat()) |
798 { | 798 { |
799 case PixelFormat_Grayscale8: | 799 case PixelFormat_Grayscale8: |
800 SetInternal<uint8_t>(image, value); | 800 SetInternal<uint8_t>(image, value); |
801 return; | 801 return; |
802 | 802 |
803 case PixelFormat_Grayscale16: | 803 case PixelFormat_Grayscale16: |
804 SetInternal<uint16_t>(image, value); | 804 SetInternal<uint16_t>(image, value); |
805 return; | 805 return; |
806 | 806 |
807 case PixelFormat_Grayscale32: | 807 case PixelFormat_Grayscale32: |
808 SetInternal<uint32_t>(image, value); | 808 SetInternal<uint32_t>(image, value); |
809 return; | 809 return; |
810 | 810 |
811 case PixelFormat_Grayscale64: | 811 case PixelFormat_Grayscale64: |
812 SetInternal<uint64_t>(image, value); | 812 SetInternal<uint64_t>(image, value); |
813 return; | 813 return; |
814 | 814 |
815 case PixelFormat_SignedGrayscale16: | 815 case PixelFormat_SignedGrayscale16: |
816 SetInternal<int16_t>(image, value); | 816 SetInternal<int16_t>(image, value); |
817 return; | 817 return; |
818 | 818 |
819 case PixelFormat_Float32: | 819 case PixelFormat_Float32: |
820 assert(sizeof(float) == 4); | 820 assert(sizeof(float) == 4); |
821 SetInternal<float>(image, value); | 821 SetInternal<float>(image, value); |
822 return; | 822 return; |
823 | 823 |
824 default: | 824 case PixelFormat_RGBA32: |
825 throw OrthancException(ErrorCode_NotImplemented); | 825 case PixelFormat_BGRA32: |
826 case PixelFormat_RGB24: | |
827 { | |
828 uint8_t v = static_cast<uint8_t>(value); | |
829 Set(image, v, v, v, v); // Use the color version | |
830 return; | |
831 } | |
832 | |
833 default: | |
834 throw OrthancException(ErrorCode_NotImplemented); | |
826 } | 835 } |
827 } | 836 } |
828 | 837 |
829 | 838 |
830 void ImageProcessing::Set(ImageAccessor& image, | 839 void ImageProcessing::Set(ImageAccessor& image, |
836 uint8_t p[4]; | 845 uint8_t p[4]; |
837 unsigned int size; | 846 unsigned int size; |
838 | 847 |
839 switch (image.GetFormat()) | 848 switch (image.GetFormat()) |
840 { | 849 { |
841 case PixelFormat_RGBA32: | 850 case PixelFormat_RGBA32: |
842 p[0] = red; | 851 p[0] = red; |
843 p[1] = green; | 852 p[1] = green; |
844 p[2] = blue; | 853 p[2] = blue; |
845 p[3] = alpha; | 854 p[3] = alpha; |
846 size = 4; | 855 size = 4; |
847 break; | 856 break; |
848 | 857 |
849 case PixelFormat_BGRA32: | 858 case PixelFormat_BGRA32: |
850 p[0] = blue; | 859 p[0] = blue; |
851 p[1] = green; | 860 p[1] = green; |
852 p[2] = red; | 861 p[2] = red; |
853 p[3] = alpha; | 862 p[3] = alpha; |
854 size = 4; | 863 size = 4; |
855 break; | 864 break; |
856 | 865 |
857 case PixelFormat_RGB24: | 866 case PixelFormat_RGB24: |
858 p[0] = red; | 867 p[0] = red; |
859 p[1] = green; | 868 p[1] = green; |
860 p[2] = blue; | 869 p[2] = blue; |
861 size = 3; | 870 size = 3; |
862 break; | 871 break; |
863 | 872 |
864 default: | 873 default: |
865 throw OrthancException(ErrorCode_NotImplemented); | 874 throw OrthancException(ErrorCode_NotImplemented); |
866 } | 875 } |
867 | 876 |
868 const unsigned int width = image.GetWidth(); | 877 const unsigned int width = image.GetWidth(); |
869 const unsigned int height = image.GetHeight(); | 878 const unsigned int height = image.GetHeight(); |
870 | 879 |
904 int64_t& maxValue, | 913 int64_t& maxValue, |
905 const ImageAccessor& image) | 914 const ImageAccessor& image) |
906 { | 915 { |
907 switch (image.GetFormat()) | 916 switch (image.GetFormat()) |
908 { | 917 { |
909 case PixelFormat_Grayscale8: | 918 case PixelFormat_Grayscale8: |
910 { | 919 { |
911 uint8_t a, b; | 920 uint8_t a, b; |
912 GetMinMaxValueInternal<uint8_t>(a, b, image); | 921 GetMinMaxValueInternal<uint8_t>(a, b, image); |
913 minValue = a; | 922 minValue = a; |
914 maxValue = b; | 923 maxValue = b; |
915 break; | 924 break; |
916 } | 925 } |
917 | 926 |
918 case PixelFormat_Grayscale16: | 927 case PixelFormat_Grayscale16: |
919 { | 928 { |
920 uint16_t a, b; | 929 uint16_t a, b; |
921 GetMinMaxValueInternal<uint16_t>(a, b, image); | 930 GetMinMaxValueInternal<uint16_t>(a, b, image); |
922 minValue = a; | 931 minValue = a; |
923 maxValue = b; | 932 maxValue = b; |
924 break; | 933 break; |
925 } | 934 } |
926 | 935 |
927 case PixelFormat_Grayscale32: | 936 case PixelFormat_Grayscale32: |
928 { | 937 { |
929 uint32_t a, b; | 938 uint32_t a, b; |
930 GetMinMaxValueInternal<uint32_t>(a, b, image); | 939 GetMinMaxValueInternal<uint32_t>(a, b, image); |
931 minValue = a; | 940 minValue = a; |
932 maxValue = b; | 941 maxValue = b; |
933 break; | 942 break; |
934 } | 943 } |
935 | 944 |
936 case PixelFormat_SignedGrayscale16: | 945 case PixelFormat_SignedGrayscale16: |
937 { | 946 { |
938 int16_t a, b; | 947 int16_t a, b; |
939 GetMinMaxValueInternal<int16_t>(a, b, image); | 948 GetMinMaxValueInternal<int16_t>(a, b, image); |
940 minValue = a; | 949 minValue = a; |
941 maxValue = b; | 950 maxValue = b; |
942 break; | 951 break; |
943 } | 952 } |
944 | 953 |
945 default: | 954 default: |
946 throw OrthancException(ErrorCode_NotImplemented); | 955 throw OrthancException(ErrorCode_NotImplemented); |
947 } | 956 } |
948 } | 957 } |
949 | 958 |
950 | 959 |
951 void ImageProcessing::GetMinMaxFloatValue(float& minValue, | 960 void ImageProcessing::GetMinMaxFloatValue(float& minValue, |
952 float& maxValue, | 961 float& maxValue, |
953 const ImageAccessor& image) | 962 const ImageAccessor& image) |
954 { | 963 { |
955 switch (image.GetFormat()) | 964 switch (image.GetFormat()) |
956 { | 965 { |
957 case PixelFormat_Float32: | 966 case PixelFormat_Float32: |
958 { | 967 { |
959 assert(sizeof(float) == 4); | 968 assert(sizeof(float) == 4); |
960 float a, b; | 969 float a, b; |
961 GetMinMaxValueInternal<float>(a, b, image); | 970 GetMinMaxValueInternal<float>(a, b, image); |
962 minValue = a; | 971 minValue = a; |
963 maxValue = b; | 972 maxValue = b; |
964 break; | 973 break; |
965 } | 974 } |
966 | 975 |
967 default: | 976 default: |
968 throw OrthancException(ErrorCode_NotImplemented); | 977 throw OrthancException(ErrorCode_NotImplemented); |
969 } | 978 } |
970 } | 979 } |
971 | 980 |
972 | 981 |
973 | 982 |
974 void ImageProcessing::AddConstant(ImageAccessor& image, | 983 void ImageProcessing::AddConstant(ImageAccessor& image, |
975 int64_t value) | 984 int64_t value) |
976 { | 985 { |
977 switch (image.GetFormat()) | 986 switch (image.GetFormat()) |
978 { | 987 { |
979 case PixelFormat_Grayscale8: | 988 case PixelFormat_Grayscale8: |
980 AddConstantInternal<uint8_t>(image, value); | 989 AddConstantInternal<uint8_t>(image, value); |
981 return; | 990 return; |
982 | 991 |
983 case PixelFormat_Grayscale16: | 992 case PixelFormat_Grayscale16: |
984 AddConstantInternal<uint16_t>(image, value); | 993 AddConstantInternal<uint16_t>(image, value); |
985 return; | 994 return; |
986 | 995 |
987 case PixelFormat_SignedGrayscale16: | 996 case PixelFormat_SignedGrayscale16: |
988 AddConstantInternal<int16_t>(image, value); | 997 AddConstantInternal<int16_t>(image, value); |
989 return; | 998 return; |
990 | 999 |
991 default: | 1000 default: |
992 throw OrthancException(ErrorCode_NotImplemented); | 1001 throw OrthancException(ErrorCode_NotImplemented); |
993 } | 1002 } |
994 } | 1003 } |
995 | 1004 |
996 | 1005 |
997 void ImageProcessing::MultiplyConstant(ImageAccessor& image, | 1006 void ImageProcessing::MultiplyConstant(ImageAccessor& image, |
998 float factor, | 1007 float factor, |
999 bool useRound) | 1008 bool useRound) |
1000 { | 1009 { |
1001 switch (image.GetFormat()) | 1010 switch (image.GetFormat()) |
1002 { | 1011 { |
1003 case PixelFormat_Grayscale8: | 1012 case PixelFormat_Grayscale8: |
1004 if (useRound) | 1013 if (useRound) |
1005 { | 1014 { |
1006 MultiplyConstantInternal<uint8_t, true>(image, factor); | 1015 MultiplyConstantInternal<uint8_t, true>(image, factor); |
1007 } | 1016 } |
1008 else | 1017 else |
1009 { | 1018 { |
1010 MultiplyConstantInternal<uint8_t, false>(image, factor); | 1019 MultiplyConstantInternal<uint8_t, false>(image, factor); |
1011 } | 1020 } |
1012 return; | 1021 return; |
1013 | 1022 |
1014 case PixelFormat_Grayscale16: | 1023 case PixelFormat_Grayscale16: |
1015 if (useRound) | 1024 if (useRound) |
1016 { | 1025 { |
1017 MultiplyConstantInternal<uint16_t, true>(image, factor); | 1026 MultiplyConstantInternal<uint16_t, true>(image, factor); |
1018 } | 1027 } |
1019 else | 1028 else |
1020 { | 1029 { |
1021 MultiplyConstantInternal<uint16_t, false>(image, factor); | 1030 MultiplyConstantInternal<uint16_t, false>(image, factor); |
1022 } | 1031 } |
1023 return; | 1032 return; |
1024 | 1033 |
1025 case PixelFormat_SignedGrayscale16: | 1034 case PixelFormat_SignedGrayscale16: |
1026 if (useRound) | 1035 if (useRound) |
1027 { | 1036 { |
1028 MultiplyConstantInternal<int16_t, true>(image, factor); | 1037 MultiplyConstantInternal<int16_t, true>(image, factor); |
1029 } | 1038 } |
1030 else | 1039 else |
1031 { | 1040 { |
1032 MultiplyConstantInternal<int16_t, false>(image, factor); | 1041 MultiplyConstantInternal<int16_t, false>(image, factor); |
1033 } | 1042 } |
1034 return; | 1043 return; |
1035 | 1044 |
1036 default: | 1045 default: |
1037 throw OrthancException(ErrorCode_NotImplemented); | 1046 throw OrthancException(ErrorCode_NotImplemented); |
1038 } | 1047 } |
1039 } | 1048 } |
1040 | 1049 |
1041 | 1050 |
1042 void ImageProcessing::ShiftScale(ImageAccessor& image, | 1051 void ImageProcessing::ShiftScale(ImageAccessor& image, |
1044 float scaling, | 1053 float scaling, |
1045 bool useRound) | 1054 bool useRound) |
1046 { | 1055 { |
1047 switch (image.GetFormat()) | 1056 switch (image.GetFormat()) |
1048 { | 1057 { |
1049 case PixelFormat_Grayscale8: | 1058 case PixelFormat_Grayscale8: |
1050 if (useRound) | 1059 if (useRound) |
1051 { | 1060 { |
1052 ShiftScaleInternal<uint8_t, true>(image, offset, scaling); | 1061 ShiftScaleInternal<uint8_t, true>(image, offset, scaling); |
1053 } | 1062 } |
1054 else | 1063 else |
1055 { | 1064 { |
1056 ShiftScaleInternal<uint8_t, false>(image, offset, scaling); | 1065 ShiftScaleInternal<uint8_t, false>(image, offset, scaling); |
1057 } | 1066 } |
1058 return; | 1067 return; |
1059 | 1068 |
1060 case PixelFormat_Grayscale16: | 1069 case PixelFormat_Grayscale16: |
1061 if (useRound) | 1070 if (useRound) |
1062 { | 1071 { |
1063 ShiftScaleInternal<uint16_t, true>(image, offset, scaling); | 1072 ShiftScaleInternal<uint16_t, true>(image, offset, scaling); |
1064 } | 1073 } |
1065 else | 1074 else |
1066 { | 1075 { |
1067 ShiftScaleInternal<uint16_t, false>(image, offset, scaling); | 1076 ShiftScaleInternal<uint16_t, false>(image, offset, scaling); |
1068 } | 1077 } |
1069 return; | 1078 return; |
1070 | 1079 |
1071 case PixelFormat_SignedGrayscale16: | 1080 case PixelFormat_SignedGrayscale16: |
1072 if (useRound) | 1081 if (useRound) |
1073 { | 1082 { |
1074 ShiftScaleInternal<int16_t, true>(image, offset, scaling); | 1083 ShiftScaleInternal<int16_t, true>(image, offset, scaling); |
1075 } | 1084 } |
1076 else | 1085 else |
1077 { | 1086 { |
1078 ShiftScaleInternal<int16_t, false>(image, offset, scaling); | 1087 ShiftScaleInternal<int16_t, false>(image, offset, scaling); |
1079 } | 1088 } |
1080 return; | 1089 return; |
1081 | 1090 |
1082 default: | 1091 default: |
1083 throw OrthancException(ErrorCode_NotImplemented); | 1092 throw OrthancException(ErrorCode_NotImplemented); |
1084 } | 1093 } |
1085 } | 1094 } |
1086 | 1095 |
1087 | 1096 |
1088 void ImageProcessing::Invert(ImageAccessor& image, int64_t maxValue) | 1097 void ImageProcessing::Invert(ImageAccessor& image, int64_t maxValue) |
1090 const unsigned int width = image.GetWidth(); | 1099 const unsigned int width = image.GetWidth(); |
1091 const unsigned int height = image.GetHeight(); | 1100 const unsigned int height = image.GetHeight(); |
1092 | 1101 |
1093 switch (image.GetFormat()) | 1102 switch (image.GetFormat()) |
1094 { | 1103 { |
1095 case PixelFormat_Grayscale16: | 1104 case PixelFormat_Grayscale16: |
1096 { | 1105 { |
1097 uint16_t maxValueUint16 = (uint16_t)(std::min(maxValue, static_cast<int64_t>(std::numeric_limits<uint16_t>::max()))); | 1106 uint16_t maxValueUint16 = (uint16_t)(std::min(maxValue, static_cast<int64_t>(std::numeric_limits<uint16_t>::max()))); |
1098 | 1107 |
1099 for (unsigned int y = 0; y < height; y++) | 1108 for (unsigned int y = 0; y < height; y++) |
1100 { | 1109 { |
1101 uint16_t* p = reinterpret_cast<uint16_t*>(image.GetRow(y)); | 1110 uint16_t* p = reinterpret_cast<uint16_t*>(image.GetRow(y)); |
1102 | 1111 |
1103 for (unsigned int x = 0; x < width; x++, p++) | 1112 for (unsigned int x = 0; x < width; x++, p++) |
1104 { | 1113 { |
1105 *p = maxValueUint16 - (*p); | 1114 *p = maxValueUint16 - (*p); |
1106 } | 1115 } |
1107 } | 1116 } |
1108 | 1117 |
1109 return; | 1118 return; |
1110 } | 1119 } |
1111 case PixelFormat_Grayscale8: | 1120 case PixelFormat_Grayscale8: |
1112 { | 1121 { |
1113 uint8_t maxValueUint8 = (uint8_t)(std::min(maxValue, static_cast<int64_t>(std::numeric_limits<uint8_t>::max()))); | 1122 uint8_t maxValueUint8 = (uint8_t)(std::min(maxValue, static_cast<int64_t>(std::numeric_limits<uint8_t>::max()))); |
1114 | 1123 |
1115 for (unsigned int y = 0; y < height; y++) | 1124 for (unsigned int y = 0; y < height; y++) |
1116 { | 1125 { |
1117 uint8_t* p = reinterpret_cast<uint8_t*>(image.GetRow(y)); | 1126 uint8_t* p = reinterpret_cast<uint8_t*>(image.GetRow(y)); |
1118 | 1127 |
1119 for (unsigned int x = 0; x < width; x++, p++) | 1128 for (unsigned int x = 0; x < width; x++, p++) |
1120 { | 1129 { |
1121 *p = maxValueUint8 - (*p); | 1130 *p = maxValueUint8 - (*p); |
1122 } | 1131 } |
1123 } | 1132 } |
1124 | 1133 |
1125 return; | 1134 return; |
1126 } | 1135 } |
1127 | 1136 |
1128 default: | 1137 default: |
1129 throw OrthancException(ErrorCode_NotImplemented); | 1138 throw OrthancException(ErrorCode_NotImplemented); |
1130 } | 1139 } |
1131 | 1140 |
1132 } | 1141 } |
1133 | 1142 |
1134 void ImageProcessing::Invert(ImageAccessor& image) | 1143 void ImageProcessing::Invert(ImageAccessor& image) |
1135 { | 1144 { |
1136 switch (image.GetFormat()) | 1145 switch (image.GetFormat()) |
1137 { | 1146 { |
1138 case PixelFormat_Grayscale8: | 1147 case PixelFormat_Grayscale8: |
1139 return Invert(image, 255); | 1148 return Invert(image, 255); |
1140 default: | 1149 default: |
1141 throw OrthancException(ErrorCode_NotImplemented); // you should use the Invert(image, maxValue) overload | 1150 throw OrthancException(ErrorCode_NotImplemented); // you should use the Invert(image, maxValue) overload |
1142 } | 1151 } |
1143 } | 1152 } |
1144 | 1153 |
1145 | 1154 |
1146 | 1155 |
1289 int y1, | 1298 int y1, |
1290 int64_t value) | 1299 int64_t value) |
1291 { | 1300 { |
1292 switch (image.GetFormat()) | 1301 switch (image.GetFormat()) |
1293 { | 1302 { |
1294 case Orthanc::PixelFormat_Grayscale8: | 1303 case Orthanc::PixelFormat_Grayscale8: |
1295 { | 1304 { |
1296 BresenhamPixelWriter<Orthanc::PixelFormat_Grayscale8> writer(image, value); | 1305 BresenhamPixelWriter<Orthanc::PixelFormat_Grayscale8> writer(image, value); |
1297 writer.DrawSegment(x0, y0, x1, y1); | 1306 writer.DrawSegment(x0, y0, x1, y1); |
1298 break; | 1307 break; |
1299 } | 1308 } |
1300 | 1309 |
1301 case Orthanc::PixelFormat_Grayscale16: | 1310 case Orthanc::PixelFormat_Grayscale16: |
1302 { | 1311 { |
1303 BresenhamPixelWriter<Orthanc::PixelFormat_Grayscale16> writer(image, value); | 1312 BresenhamPixelWriter<Orthanc::PixelFormat_Grayscale16> writer(image, value); |
1304 writer.DrawSegment(x0, y0, x1, y1); | 1313 writer.DrawSegment(x0, y0, x1, y1); |
1305 break; | 1314 break; |
1306 } | 1315 } |
1307 | 1316 |
1308 case Orthanc::PixelFormat_SignedGrayscale16: | 1317 case Orthanc::PixelFormat_SignedGrayscale16: |
1309 { | 1318 { |
1310 BresenhamPixelWriter<Orthanc::PixelFormat_SignedGrayscale16> writer(image, value); | 1319 BresenhamPixelWriter<Orthanc::PixelFormat_SignedGrayscale16> writer(image, value); |
1311 writer.DrawSegment(x0, y0, x1, y1); | 1320 writer.DrawSegment(x0, y0, x1, y1); |
1312 break; | 1321 break; |
1313 } | 1322 } |
1314 | 1323 |
1315 default: | 1324 default: |
1316 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); | 1325 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); |
1317 } | 1326 } |
1318 } | 1327 } |
1319 | 1328 |
1320 | 1329 |
1321 void ImageProcessing::DrawLineSegment(ImageAccessor& image, | 1330 void ImageProcessing::DrawLineSegment(ImageAccessor& image, |
1328 uint8_t blue, | 1337 uint8_t blue, |
1329 uint8_t alpha) | 1338 uint8_t alpha) |
1330 { | 1339 { |
1331 switch (image.GetFormat()) | 1340 switch (image.GetFormat()) |
1332 { | 1341 { |
1333 case Orthanc::PixelFormat_BGRA32: | 1342 case Orthanc::PixelFormat_BGRA32: |
1334 { | 1343 { |
1335 PixelTraits<Orthanc::PixelFormat_BGRA32>::PixelType pixel; | 1344 PixelTraits<Orthanc::PixelFormat_BGRA32>::PixelType pixel; |
1336 pixel.red_ = red; | 1345 pixel.red_ = red; |
1337 pixel.green_ = green; | 1346 pixel.green_ = green; |
1338 pixel.blue_ = blue; | 1347 pixel.blue_ = blue; |
1339 pixel.alpha_ = alpha; | 1348 pixel.alpha_ = alpha; |
1340 | 1349 |
1341 BresenhamPixelWriter<Orthanc::PixelFormat_BGRA32> writer(image, pixel); | 1350 BresenhamPixelWriter<Orthanc::PixelFormat_BGRA32> writer(image, pixel); |
1342 writer.DrawSegment(x0, y0, x1, y1); | 1351 writer.DrawSegment(x0, y0, x1, y1); |
1343 break; | 1352 break; |
1344 } | 1353 } |
1345 | 1354 |
1346 case Orthanc::PixelFormat_RGBA32: | 1355 case Orthanc::PixelFormat_RGBA32: |
1347 { | 1356 { |
1348 PixelTraits<Orthanc::PixelFormat_RGBA32>::PixelType pixel; | 1357 PixelTraits<Orthanc::PixelFormat_RGBA32>::PixelType pixel; |
1349 pixel.red_ = red; | 1358 pixel.red_ = red; |
1350 pixel.green_ = green; | 1359 pixel.green_ = green; |
1351 pixel.blue_ = blue; | 1360 pixel.blue_ = blue; |
1352 pixel.alpha_ = alpha; | 1361 pixel.alpha_ = alpha; |
1353 | 1362 |
1354 BresenhamPixelWriter<Orthanc::PixelFormat_RGBA32> writer(image, pixel); | 1363 BresenhamPixelWriter<Orthanc::PixelFormat_RGBA32> writer(image, pixel); |
1355 writer.DrawSegment(x0, y0, x1, y1); | 1364 writer.DrawSegment(x0, y0, x1, y1); |
1356 break; | 1365 break; |
1357 } | 1366 } |
1358 | 1367 |
1359 case Orthanc::PixelFormat_RGB24: | 1368 case Orthanc::PixelFormat_RGB24: |
1360 { | 1369 { |
1361 PixelTraits<Orthanc::PixelFormat_RGB24>::PixelType pixel; | 1370 PixelTraits<Orthanc::PixelFormat_RGB24>::PixelType pixel; |
1362 pixel.red_ = red; | 1371 pixel.red_ = red; |
1363 pixel.green_ = green; | 1372 pixel.green_ = green; |
1364 pixel.blue_ = blue; | 1373 pixel.blue_ = blue; |
1365 | 1374 |
1366 BresenhamPixelWriter<Orthanc::PixelFormat_RGB24> writer(image, pixel); | 1375 BresenhamPixelWriter<Orthanc::PixelFormat_RGB24> writer(image, pixel); |
1367 writer.DrawSegment(x0, y0, x1, y1); | 1376 writer.DrawSegment(x0, y0, x1, y1); |
1368 break; | 1377 break; |
1369 } | 1378 } |
1370 | 1379 |
1371 default: | 1380 default: |
1372 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); | 1381 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); |
1373 } | 1382 } |
1374 } | 1383 } |
1375 | 1384 |
1376 void ComputePolygonExtent(int32_t& left, int32_t& right, int32_t& top, int32_t& bottom, const std::vector<ImageProcessing::ImagePoint>& points) | 1385 void ComputePolygonExtent(int32_t& left, int32_t& right, int32_t& top, int32_t& bottom, const std::vector<ImageProcessing::ImagePoint>& points) |
1377 { | 1386 { |
1390 } | 1399 } |
1391 } | 1400 } |
1392 | 1401 |
1393 template <PixelFormat TargetFormat> | 1402 template <PixelFormat TargetFormat> |
1394 void FillPolygon_(ImageAccessor& image, | 1403 void FillPolygon_(ImageAccessor& image, |
1395 const std::vector<ImageProcessing::ImagePoint>& points, | 1404 const std::vector<ImageProcessing::ImagePoint>& points, |
1396 int64_t value_) | 1405 int64_t value_) |
1397 { | 1406 { |
1398 typedef typename PixelTraits<TargetFormat>::PixelType TargetType; | 1407 typedef typename PixelTraits<TargetFormat>::PixelType TargetType; |
1399 | 1408 |
1400 TargetType value = PixelTraits<TargetFormat>::IntegerToPixel(value_); | 1409 TargetType value = PixelTraits<TargetFormat>::IntegerToPixel(value_); |
1401 int imageWidth = static_cast<int>(image.GetWidth()); | 1410 int imageWidth = static_cast<int>(image.GetWidth()); |
1522 const std::vector<ImagePoint>& points, | 1531 const std::vector<ImagePoint>& points, |
1523 int64_t value) | 1532 int64_t value) |
1524 { | 1533 { |
1525 switch (image.GetFormat()) | 1534 switch (image.GetFormat()) |
1526 { | 1535 { |
1527 case Orthanc::PixelFormat_Grayscale8: | 1536 case Orthanc::PixelFormat_Grayscale8: |
1528 { | 1537 { |
1529 FillPolygon_<Orthanc::PixelFormat_Grayscale8>(image, points, value); | 1538 FillPolygon_<Orthanc::PixelFormat_Grayscale8>(image, points, value); |
1530 break; | 1539 break; |
1531 } | 1540 } |
1532 case Orthanc::PixelFormat_Grayscale16: | 1541 case Orthanc::PixelFormat_Grayscale16: |
1533 { | 1542 { |
1534 FillPolygon_<Orthanc::PixelFormat_Grayscale16>(image, points, value); | 1543 FillPolygon_<Orthanc::PixelFormat_Grayscale16>(image, points, value); |
1535 break; | 1544 break; |
1536 } | 1545 } |
1537 case Orthanc::PixelFormat_SignedGrayscale16: | 1546 case Orthanc::PixelFormat_SignedGrayscale16: |
1538 { | 1547 { |
1539 FillPolygon_<Orthanc::PixelFormat_SignedGrayscale16>(image, points, value); | 1548 FillPolygon_<Orthanc::PixelFormat_SignedGrayscale16>(image, points, value); |
1540 break; | 1549 break; |
1541 } | 1550 } |
1542 default: | 1551 default: |
1543 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); | 1552 throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); |
1544 } | 1553 } |
1545 } | 1554 } |
1546 | |
1547 } | 1555 } |