comparison OrthancServer/FromDcmtkBridge.cpp @ 1689:26083d84d237

refactoring
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 07 Oct 2015 16:54:05 +0200
parents 27d70e9ee2e4
children ae09132e4237
comparison
equal deleted inserted replaced
1688:27d70e9ee2e4 1689:26083d84d237
93 #include <dcmtk/dcmdata/dcvrat.h> 93 #include <dcmtk/dcmdata/dcvrat.h>
94 94
95 #include <dcmtk/dcmnet/dul.h> 95 #include <dcmtk/dcmnet/dul.h>
96 96
97 #include <boost/math/special_functions/round.hpp> 97 #include <boost/math/special_functions/round.hpp>
98 #include <boost/algorithm/string/predicate.hpp>
98 #include <dcmtk/dcmdata/dcostrmb.h> 99 #include <dcmtk/dcmdata/dcostrmb.h>
99 100
100 101
101 namespace Orthanc 102 namespace Orthanc
102 { 103 {
1021 default: 1022 default:
1022 return ValueRepresentation_Other; 1023 return ValueRepresentation_Other;
1023 } 1024 }
1024 } 1025 }
1025 1026
1027
1028
1029 DcmElement* FromDcmtkBridge::CreateElementForTag(const DicomTag& tag)
1030 {
1031 DcmTag key(tag.GetGroup(), tag.GetElement());
1032
1033 switch (key.getEVR())
1034 {
1035 // http://support.dcmtk.org/docs/dcvr_8h-source.html
1036
1037 /**
1038 * TODO.
1039 **/
1040
1041 case EVR_OB: // other byte
1042 case EVR_OF: // other float
1043 case EVR_OW: // other word
1044 case EVR_AT: // attribute tag
1045 throw OrthancException(ErrorCode_NotImplemented);
1046
1047 case EVR_UN: // unknown value representation
1048 throw OrthancException(ErrorCode_ParameterOutOfRange);
1049
1050
1051 /**
1052 * String types.
1053 * http://support.dcmtk.org/docs/classDcmByteString.html
1054 **/
1055
1056 case EVR_AS: // age string
1057 return new DcmAgeString(key);
1058
1059 case EVR_AE: // application entity title
1060 return new DcmApplicationEntity(key);
1061
1062 case EVR_CS: // code string
1063 return new DcmCodeString(key);
1064
1065 case EVR_DA: // date string
1066 return new DcmDate(key);
1067
1068 case EVR_DT: // date time string
1069 return new DcmDateTime(key);
1070
1071 case EVR_DS: // decimal string
1072 return new DcmDecimalString(key);
1073
1074 case EVR_IS: // integer string
1075 return new DcmIntegerString(key);
1076
1077 case EVR_TM: // time string
1078 return new DcmTime(key);
1079
1080 case EVR_UI: // unique identifier
1081 return new DcmUniqueIdentifier(key);
1082
1083 case EVR_ST: // short text
1084 return new DcmShortText(key);
1085
1086 case EVR_LO: // long string
1087 return new DcmLongString(key);
1088
1089 case EVR_LT: // long text
1090 return new DcmLongText(key);
1091
1092 case EVR_UT: // unlimited text
1093 return new DcmUnlimitedText(key);
1094
1095 case EVR_SH: // short string
1096 return new DcmShortString(key);
1097
1098 case EVR_PN: // person name
1099 return new DcmPersonName(key);
1100
1101
1102 /**
1103 * Numerical types
1104 **/
1105
1106 case EVR_SL: // signed long
1107 return new DcmSignedLong(key);
1108
1109 case EVR_SS: // signed short
1110 return new DcmSignedShort(key);
1111
1112 case EVR_UL: // unsigned long
1113 return new DcmUnsignedLong(key);
1114
1115 case EVR_US: // unsigned short
1116 return new DcmUnsignedShort(key);
1117
1118 case EVR_FL: // float single-precision
1119 return new DcmFloatingPointSingle(key);
1120
1121 case EVR_FD: // float double-precision
1122 return new DcmFloatingPointDouble(key);
1123
1124
1125 /**
1126 * Sequence types, should never occur at this point.
1127 **/
1128
1129 case EVR_SQ: // sequence of items
1130 throw OrthancException(ErrorCode_ParameterOutOfRange);
1131
1132
1133 /**
1134 * Internal to DCMTK.
1135 **/
1136
1137 case EVR_ox: // OB or OW depending on context
1138 case EVR_xs: // SS or US depending on context
1139 case EVR_lt: // US, SS or OW depending on context, used for LUT Data (thus the name)
1140 case EVR_na: // na="not applicable", for data which has no VR
1141 case EVR_up: // up="unsigned pointer", used internally for DICOMDIR suppor
1142 case EVR_item: // used internally for items
1143 case EVR_metainfo: // used internally for meta info datasets
1144 case EVR_dataset: // used internally for datasets
1145 case EVR_fileFormat: // used internally for DICOM files
1146 case EVR_dicomDir: // used internally for DICOMDIR objects
1147 case EVR_dirRecord: // used internally for DICOMDIR records
1148 case EVR_pixelSQ: // used internally for pixel sequences in a compressed image
1149 case EVR_pixelItem: // used internally for pixel items in a compressed image
1150 case EVR_UNKNOWN: // used internally for elements with unknown VR (encoded with 4-byte length field in explicit VR)
1151 case EVR_PixelData: // used internally for uncompressed pixeld data
1152 case EVR_OverlayData: // used internally for overlay data
1153 case EVR_UNKNOWN2B: // used internally for elements with unknown VR with 2-byte length field in explicit VR
1154 default:
1155 break;
1156 }
1157
1158 throw OrthancException(ErrorCode_InternalError);
1159 }
1160
1161
1162
1163 void FromDcmtkBridge::FillElementWithString(DcmElement& element,
1164 const DicomTag& tag,
1165 const std::string& value,
1166 bool decodeBinaryTags)
1167 {
1168 std::string binary;
1169 const std::string* decoded = &value;
1170
1171 if (decodeBinaryTags &&
1172 boost::starts_with(value, "data:application/octet-stream;base64,"))
1173 {
1174 std::string mime;
1175 Toolbox::DecodeDataUriScheme(mime, binary, value);
1176 decoded = &binary;
1177 }
1178
1179
1180 if (FromDcmtkBridge::IsPrivateTag(tag) ||
1181 FromDcmtkBridge::IsUnknownTag(tag))
1182 {
1183 if (element.putUint8Array((const Uint8*) decoded->c_str(), decoded->size()).good())
1184 {
1185 return;
1186 }
1187 else
1188 {
1189 throw OrthancException(ErrorCode_InternalError);
1190 }
1191 }
1192
1193 DcmTag key(tag.GetGroup(), tag.GetElement());
1194 bool ok = false;
1195
1196 try
1197 {
1198 switch (key.getEVR())
1199 {
1200 // http://support.dcmtk.org/docs/dcvr_8h-source.html
1201
1202 /**
1203 * TODO.
1204 **/
1205
1206 case EVR_OB: // other byte
1207 case EVR_OF: // other float
1208 case EVR_OW: // other word
1209 case EVR_AT: // attribute tag
1210 throw OrthancException(ErrorCode_NotImplemented);
1211
1212 case EVR_UN: // unknown value representation
1213 throw OrthancException(ErrorCode_ParameterOutOfRange);
1214
1215
1216 /**
1217 * String types.
1218 **/
1219
1220 case EVR_DS: // decimal string
1221 case EVR_IS: // integer string
1222 case EVR_AS: // age string
1223 case EVR_DA: // date string
1224 case EVR_DT: // date time string
1225 case EVR_TM: // time string
1226 case EVR_AE: // application entity title
1227 case EVR_CS: // code string
1228 case EVR_SH: // short string
1229 case EVR_LO: // long string
1230 case EVR_ST: // short text
1231 case EVR_LT: // long text
1232 case EVR_UT: // unlimited text
1233 case EVR_PN: // person name
1234 case EVR_UI: // unique identifier
1235 {
1236 ok = element.putString(decoded->c_str()).good();
1237 break;
1238 }
1239
1240
1241 /**
1242 * Numerical types
1243 **/
1244
1245 case EVR_SL: // signed long
1246 {
1247 ok = element.putSint32(boost::lexical_cast<Sint32>(*decoded)).good();
1248 break;
1249 }
1250
1251 case EVR_SS: // signed short
1252 {
1253 ok = element.putSint16(boost::lexical_cast<Sint16>(*decoded)).good();
1254 break;
1255 }
1256
1257 case EVR_UL: // unsigned long
1258 {
1259 ok = element.putUint32(boost::lexical_cast<Uint32>(*decoded)).good();
1260 break;
1261 }
1262
1263 case EVR_US: // unsigned short
1264 {
1265 ok = element.putUint16(boost::lexical_cast<Uint16>(*decoded)).good();
1266 break;
1267 }
1268
1269 case EVR_FL: // float single-precision
1270 {
1271 ok = element.putFloat32(boost::lexical_cast<float>(*decoded)).good();
1272 break;
1273 }
1274
1275 case EVR_FD: // float double-precision
1276 {
1277 ok = element.putFloat64(boost::lexical_cast<double>(*decoded)).good();
1278 break;
1279 }
1280
1281
1282 /**
1283 * Sequence types, should never occur at this point.
1284 **/
1285
1286 case EVR_SQ: // sequence of items
1287 {
1288 ok = false;
1289 break;
1290 }
1291
1292
1293 /**
1294 * Internal to DCMTK.
1295 **/
1296
1297 case EVR_ox: // OB or OW depending on context
1298 case EVR_xs: // SS or US depending on context
1299 case EVR_lt: // US, SS or OW depending on context, used for LUT Data (thus the name)
1300 case EVR_na: // na="not applicable", for data which has no VR
1301 case EVR_up: // up="unsigned pointer", used internally for DICOMDIR suppor
1302 case EVR_item: // used internally for items
1303 case EVR_metainfo: // used internally for meta info datasets
1304 case EVR_dataset: // used internally for datasets
1305 case EVR_fileFormat: // used internally for DICOM files
1306 case EVR_dicomDir: // used internally for DICOMDIR objects
1307 case EVR_dirRecord: // used internally for DICOMDIR records
1308 case EVR_pixelSQ: // used internally for pixel sequences in a compressed image
1309 case EVR_pixelItem: // used internally for pixel items in a compressed image
1310 case EVR_UNKNOWN: // used internally for elements with unknown VR (encoded with 4-byte length field in explicit VR)
1311 case EVR_PixelData: // used internally for uncompressed pixeld data
1312 case EVR_OverlayData: // used internally for overlay data
1313 case EVR_UNKNOWN2B: // used internally for elements with unknown VR with 2-byte length field in explicit VR
1314 default:
1315 break;
1316 }
1317 }
1318 catch (boost::bad_lexical_cast&)
1319 {
1320 ok = false;
1321 }
1322
1323 if (!ok)
1324 {
1325 throw OrthancException(ErrorCode_InternalError);
1326 }
1327 }
1328
1329
1330 DcmElement* FromDcmtkBridge::FromJson(const Json::Value& value,
1331 const DicomTag& tag,
1332 bool decodeBinaryTags)
1333 {
1334 std::auto_ptr<DcmElement> element;
1335
1336 if (value.type() == Json::stringValue)
1337 {
1338 element.reset(CreateElementForTag(tag));
1339 FillElementWithString(*element, tag, value.asString(), decodeBinaryTags);
1340 }
1341
1342 return element.release();
1343 }
1026 } 1344 }