comparison OrthancFramework/UnitTestsSources/DicomMapTests.cpp @ 4216:61585d8a9faf

fix
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 29 Sep 2020 19:44:38 +0200
parents 28e9457dc7ab
children 78c8b4a18619
comparison
equal deleted inserted replaced
4215:28e9457dc7ab 4216:61585d8a9faf
807 enum State 807 enum State
808 { 808 {
809 State_Preamble, 809 State_Preamble,
810 State_MetaHeader, 810 State_MetaHeader,
811 State_DatasetTag, 811 State_DatasetTag,
812 State_SequenceExplicitLength,
813 State_SequenceExplicitValue,
812 State_DatasetExplicitLength, 814 State_DatasetExplicitLength,
813 State_DatasetValue, 815 State_DatasetValue,
814 State_Done 816 State_Done
815 }; 817 };
816 818
817 StreamBlockReader reader_; 819 StreamBlockReader reader_;
818 State state_; 820 State state_;
819 DicomTransferSyntax transferSyntax_; 821 DicomTransferSyntax transferSyntax_;
820 DicomTag previousTag_;
821 DicomTag danglingTag_; 822 DicomTag danglingTag_;
822 ValueRepresentation danglingVR_; 823 ValueRepresentation danglingVR_;
823 unsigned int sequenceDepth_; 824 unsigned int sequenceDepth_;
824 825
825 static uint16_t ReadUnsignedInteger16(const char* dicom, 826 static uint16_t ReadUnsignedInteger16(const char* dicom,
920 } 921 }
921 922
922 void HandlePreamble(IVisitor& visitor, 923 void HandlePreamble(IVisitor& visitor,
923 const std::string& block) 924 const std::string& block)
924 { 925 {
925 printf("PREAMBLE:\n"); 926 //printf("PREAMBLE:\n");
926 PrintBlock(block); 927 //PrintBlock(block);
927 928
928 assert(block.size() == 144u); 929 assert(block.size() == 144u);
929 assert(reader_.GetProcessedBytes() == 144u); 930 assert(reader_.GetProcessedBytes() == 144u);
930 931
931 /** 932 /**
953 954
954 955
955 void HandleMetaHeader(IVisitor& visitor, 956 void HandleMetaHeader(IVisitor& visitor,
956 const std::string& block) 957 const std::string& block)
957 { 958 {
958 printf("META-HEADER:\n"); 959 //printf("META-HEADER:\n");
959 PrintBlock(block); 960 //PrintBlock(block);
960 961
961 size_t pos = 0; 962 size_t pos = 0;
962 const char* p = block.c_str(); 963 const char* p = block.c_str();
963 964
964 bool hasTransferSyntax = false; 965 bool hasTransferSyntax = false;
1037 reader_.Schedule(8); 1038 reader_.Schedule(8);
1038 state_ = State_DatasetTag; 1039 state_ = State_DatasetTag;
1039 } 1040 }
1040 1041
1041 1042
1042 void HandleDatasetTag(IVisitor& visitor, 1043 void HandleDatasetTag(const std::string& block)
1043 const std::string& block)
1044 { 1044 {
1045 static const DicomTag DICOM_TAG_SEQUENCE_ITEM(0xfffe, 0xe000); 1045 static const DicomTag DICOM_TAG_SEQUENCE_ITEM(0xfffe, 0xe000);
1046 static const DicomTag DICOM_TAG_SEQUENCE_DELIMITATION_ITEM(0xfffe, 0xe00d); 1046 static const DicomTag DICOM_TAG_SEQUENCE_DELIMITATION_ITEM(0xfffe, 0xe00d);
1047 static const DicomTag DICOM_TAG_SEQUENCE_DELIMITATION_SEQUENCE(0xfffe, 0xe0dd); 1047 static const DicomTag DICOM_TAG_SEQUENCE_DELIMITATION_SEQUENCE(0xfffe, 0xe0dd);
1048 1048
1049 //printf("DATASET TAG:\n");
1050 //PrintBlock(block);
1051
1052 assert(block.size() == 8u); 1049 assert(block.size() == 8u);
1053 1050
1054 const bool littleEndian = IsLittleEndian(); 1051 const bool littleEndian = IsLittleEndian();
1055 DicomTag tag = ReadTag(block.c_str(), littleEndian); 1052 DicomTag tag = ReadTag(block.c_str(), littleEndian);
1056 1053
1057 if (tag == DICOM_TAG_SEQUENCE_ITEM || 1054 if (tag == DICOM_TAG_SEQUENCE_ITEM ||
1058 tag == DICOM_TAG_SEQUENCE_DELIMITATION_ITEM || 1055 tag == DICOM_TAG_SEQUENCE_DELIMITATION_ITEM ||
1059 tag == DICOM_TAG_SEQUENCE_DELIMITATION_SEQUENCE) 1056 tag == DICOM_TAG_SEQUENCE_DELIMITATION_SEQUENCE)
1060 { 1057 {
1061 printf("SEQUENCE TAG:\n"); 1058 //printf("SEQUENCE TAG:\n");
1062 PrintBlock(block); 1059 //PrintBlock(block);
1063 1060
1064 // The special sequence items are encoded like "Implicit VR" 1061 // The special sequence items are encoded like "Implicit VR"
1065 uint32_t length = ReadUnsignedInteger32(block.c_str() + 4, littleEndian); 1062 uint32_t length = ReadUnsignedInteger32(block.c_str() + 4, littleEndian);
1066 1063
1067 if (tag == DICOM_TAG_SEQUENCE_ITEM) 1064 if (tag == DICOM_TAG_SEQUENCE_ITEM)
1092 throw OrthancException(ErrorCode_BadFileFormat); 1089 throw OrthancException(ErrorCode_BadFileFormat);
1093 } 1090 }
1094 1091
1095 if (tag == DICOM_TAG_SEQUENCE_DELIMITATION_SEQUENCE) 1092 if (tag == DICOM_TAG_SEQUENCE_DELIMITATION_SEQUENCE)
1096 { 1093 {
1097 sequenceDepth_ --; 1094 for (unsigned int i = 0; i < sequenceDepth_; i++)
1098
1099 for (unsigned int i = 0; i <= sequenceDepth_; i++)
1100 printf(" "); 1095 printf(" ");
1101 printf("...leaving sequence...\n"); 1096 printf("...leaving sequence...\n");
1097
1098 sequenceDepth_ --;
1099 }
1100 else
1101 {
1102 if (sequenceDepth_ == 0)
1103 {
1104 throw OrthancException(ErrorCode_BadFileFormat);
1105 }
1102 } 1106 }
1103 1107
1104 reader_.Schedule(8); 1108 reader_.Schedule(8);
1105 state_ = State_DatasetTag; 1109 state_ = State_DatasetTag;
1106 } 1110 }
1109 throw OrthancException(ErrorCode_InternalError); 1113 throw OrthancException(ErrorCode_InternalError);
1110 } 1114 }
1111 } 1115 }
1112 else 1116 else
1113 { 1117 {
1118 //printf("DATASET TAG:\n");
1119 //PrintBlock(block);
1120
1114 ValueRepresentation vr = ValueRepresentation_Unknown; 1121 ValueRepresentation vr = ValueRepresentation_Unknown;
1115 1122
1116 if (transferSyntax_ == DicomTransferSyntax_LittleEndianImplicit) 1123 if (transferSyntax_ == DicomTransferSyntax_LittleEndianImplicit)
1117 { 1124 {
1118 uint32_t length = ReadUnsignedInteger32(block.c_str() + 4, true /* little endian */); 1125 uint32_t length = ReadUnsignedInteger32(block.c_str() + 4, true /* little endian */);
1121 state_ = State_DatasetValue; 1128 state_ = State_DatasetValue;
1122 } 1129 }
1123 else 1130 else
1124 { 1131 {
1125 // This in an explicit transfer syntax 1132 // This in an explicit transfer syntax
1126 1133
1127 vr = StringToValueRepresentation( 1134 vr = StringToValueRepresentation(
1128 std::string(block.c_str() + 4, 2), false /* ignore unknown VR */); 1135 std::string(block.c_str() + 4, 2), false /* ignore unknown VR */);
1129 1136
1130 if (vr == ValueRepresentation_Sequence) 1137 if (vr != ValueRepresentation_Sequence &&
1138 sequenceDepth_ > 0)
1131 { 1139 {
1132 for (unsigned int i = 0; i <= sequenceDepth_; i++) 1140 for (unsigned int i = 0; i <= sequenceDepth_; i++)
1133 printf(" "); 1141 printf(" ");
1134 printf("...entering sequence... %s\n", previousTag_.Format().c_str()); 1142 printf("%s\n", tag.Format().c_str());
1143 }
1144
1145 if (vr == ValueRepresentation_Sequence)
1146 {
1147 for (unsigned int i = 0; i <= sequenceDepth_; i++)
1148 printf(" ");
1149 printf("...entering sequence... %s\n", tag.Format().c_str());
1135 sequenceDepth_ ++; 1150 sequenceDepth_ ++;
1136 reader_.Schedule(4); 1151 reader_.Schedule(4);
1137 state_ = State_DatasetExplicitLength; 1152 state_ = State_SequenceExplicitLength;
1138 } 1153 }
1139 else if (IsShortExplicitTag(vr)) 1154 else if (IsShortExplicitTag(vr))
1140 { 1155 {
1141 uint16_t length = ReadUnsignedInteger16(block.c_str() + 6, littleEndian); 1156 uint16_t length = ReadUnsignedInteger16(block.c_str() + 6, littleEndian);
1142 1157
1154 reader_.Schedule(4); 1169 reader_.Schedule(4);
1155 state_ = State_DatasetExplicitLength; 1170 state_ = State_DatasetExplicitLength;
1156 } 1171 }
1157 } 1172 }
1158 1173
1159 previousTag_ = tag;
1160
1161 if (sequenceDepth_ == 0) 1174 if (sequenceDepth_ == 0)
1162 { 1175 {
1163 danglingTag_ = tag; 1176 danglingTag_ = tag;
1164 danglingVR_ = vr; 1177 danglingVR_ = vr;
1165 } 1178 }
1166 else 1179 }
1167 { 1180 }
1168 for (unsigned int i = 0; i <= sequenceDepth_; i++) 1181
1169 printf(" "); 1182
1170 printf(" %s\n", tag.Format().c_str()); 1183 void HandleDatasetExplicitLength(const std::string& block)
1171 }
1172 }
1173 }
1174
1175
1176 void HandleDatasetExplicitLength(IVisitor& visitor,
1177 const std::string& block)
1178 { 1184 {
1179 //printf("DATASET TAG LENGTH:\n"); 1185 //printf("DATASET TAG LENGTH:\n");
1180 //PrintBlock(block); 1186 //PrintBlock(block);
1181 1187
1182 assert(block.size() == 4); 1188 assert(block.size() == 4);
1183 1189
1184 uint32_t length = ReadUnsignedInteger32(block.c_str(), IsLittleEndian()); 1190 uint32_t length = ReadUnsignedInteger32(block.c_str(), IsLittleEndian());
1191
1185 if (length == 0xffffffffu) 1192 if (length == 0xffffffffu)
1186 { 1193 {
1187 /** 1194 /**
1188 * This is the case of sequences, or pixel data with 1195 * This is the case of pixel data with compressed transfer
1189 * compressed transfer syntaxes. Schedule the reading of the 1196 * syntaxes. Schedule the reading of the first tag of the
1190 * first tag of the nested dataset. 1197 * nested dataset.
1191 * http://dicom.nema.org/medical/dicom/current/output/chtml/part05/sect_7.5.html 1198 * http://dicom.nema.org/medical/dicom/current/output/chtml/part05/sect_7.5.html
1192 **/ 1199 **/
1193 1200
1201 if (sequenceDepth_ != 0)
1202 {
1203 throw OrthancException(ErrorCode_BadFileFormat);
1204 }
1205
1206 printf(" ...entering sequence... %s\n", danglingTag_.Format().c_str());
1194 state_ = State_DatasetTag; 1207 state_ = State_DatasetTag;
1195 reader_.Schedule(8); 1208 reader_.Schedule(8);
1209 sequenceDepth_ ++;
1196 } 1210 }
1197 else 1211 else
1198 { 1212 {
1199 reader_.Schedule(length); 1213 reader_.Schedule(length);
1200 state_ = State_DatasetValue; 1214 state_ = State_DatasetValue;
1201 } 1215 }
1216 }
1217
1218
1219 void HandleSequenceExplicitLength(const std::string& block)
1220 {
1221 //printf("DATASET TAG LENGTH:\n");
1222 //PrintBlock(block);
1223
1224 assert(block.size() == 4);
1225
1226 uint32_t length = ReadUnsignedInteger32(block.c_str(), IsLittleEndian());
1227 if (length == 0xffffffffu)
1228 {
1229 state_ = State_DatasetTag;
1230 reader_.Schedule(8);
1231 }
1232 else
1233 {
1234 for (unsigned int i = 0; i <= sequenceDepth_; i++)
1235 printf(" ");
1236 printf("...skipping sequence thanks to explicit length... %d\n", length);
1237
1238 reader_.Schedule(length);
1239 state_ = State_SequenceExplicitValue;
1240 }
1241 }
1242
1243 void HandleSequenceExplicitValue()
1244 {
1245 if (sequenceDepth_ == 0)
1246 {
1247 throw OrthancException(ErrorCode_InternalError);
1248 }
1249
1250 sequenceDepth_ --;
1251
1252 state_ = State_DatasetTag;
1253 reader_.Schedule(8);
1254 }
1255
1256
1257 void HandleDatasetValue(IVisitor& visitor,
1258 const std::string& block)
1259 {
1260 if (sequenceDepth_ == 0)
1261 {
1262 bool c;
1263
1264 if (!block.empty() &&
1265 (block[block.size() - 1] == ' ' ||
1266 block[block.size() - 1] == '\0') &&
1267 (danglingVR_ == ValueRepresentation_ApplicationEntity ||
1268 danglingVR_ == ValueRepresentation_AgeString ||
1269 danglingVR_ == ValueRepresentation_CodeString ||
1270 danglingVR_ == ValueRepresentation_DecimalString ||
1271 danglingVR_ == ValueRepresentation_IntegerString ||
1272 danglingVR_ == ValueRepresentation_LongString ||
1273 danglingVR_ == ValueRepresentation_LongText ||
1274 danglingVR_ == ValueRepresentation_PersonName ||
1275 danglingVR_ == ValueRepresentation_ShortString ||
1276 danglingVR_ == ValueRepresentation_ShortText ||
1277 danglingVR_ == ValueRepresentation_UniqueIdentifier ||
1278 danglingVR_ == ValueRepresentation_UnlimitedText))
1279 {
1280 std::string s(block.begin(), block.end() - 1);
1281 c = visitor.VisitDatasetTag(danglingTag_, danglingVR_, transferSyntax_, s, IsLittleEndian());
1282 }
1283 else
1284 {
1285 c = visitor.VisitDatasetTag(danglingTag_, danglingVR_, transferSyntax_, block, IsLittleEndian());
1286 }
1287
1288 if (!c)
1289 {
1290 state_ = State_Done;
1291 return;
1292 }
1293 }
1294
1295 reader_.Schedule(8);
1296 state_ = State_DatasetTag;
1202 } 1297 }
1203 1298
1204 1299
1205 public: 1300 public:
1206 DicomStreamReader(std::istream& stream) : 1301 DicomStreamReader(std::istream& stream) :
1207 reader_(stream), 1302 reader_(stream),
1208 state_(State_Preamble), 1303 state_(State_Preamble),
1209 transferSyntax_(DicomTransferSyntax_LittleEndianImplicit), // Dummy 1304 transferSyntax_(DicomTransferSyntax_LittleEndianImplicit), // Dummy
1210 previousTag_(0x0000, 0x0000), // Dummy
1211 danglingTag_(0x0000, 0x0000), // Dummy 1305 danglingTag_(0x0000, 0x0000), // Dummy
1212 danglingVR_(ValueRepresentation_Unknown), // Dummy 1306 danglingVR_(ValueRepresentation_Unknown), // Dummy
1213 sequenceDepth_(0) 1307 sequenceDepth_(0)
1214 { 1308 {
1215 reader_.Schedule(128 /* empty header */ + 1309 reader_.Schedule(128 /* empty header */ +
1236 case State_MetaHeader: 1330 case State_MetaHeader:
1237 HandleMetaHeader(visitor, block); 1331 HandleMetaHeader(visitor, block);
1238 break; 1332 break;
1239 1333
1240 case State_DatasetTag: 1334 case State_DatasetTag:
1241 HandleDatasetTag(visitor, block); 1335 HandleDatasetTag(block);
1242 break; 1336 break;
1243 1337
1244 case State_DatasetExplicitLength: 1338 case State_DatasetExplicitLength:
1245 HandleDatasetExplicitLength(visitor, block); 1339 HandleDatasetExplicitLength(block);
1246 break; 1340 break;
1247 1341
1342 case State_SequenceExplicitLength:
1343 HandleSequenceExplicitLength(block);
1344 break;
1345
1346 case State_SequenceExplicitValue:
1347 HandleSequenceExplicitValue();
1348 break;
1349
1248 case State_DatasetValue: 1350 case State_DatasetValue:
1249 if (sequenceDepth_ == 0 && 1351 HandleDatasetValue(visitor, block);
1250 !visitor.VisitDatasetTag(danglingTag_, danglingVR_, transferSyntax_, block, IsLittleEndian()))
1251 {
1252 state_ = State_Done;
1253 }
1254 else
1255 {
1256 reader_.Schedule(8);
1257 state_ = State_DatasetTag;
1258 }
1259
1260 break; 1352 break;
1261 1353
1262 default: 1354 default:
1263 throw OrthancException(ErrorCode_InternalError); 1355 throw OrthancException(ErrorCode_InternalError);
1264 } 1356 }
1300 bool isLittleEndian) ORTHANC_OVERRIDE 1392 bool isLittleEndian) ORTHANC_OVERRIDE
1301 { 1393 {
1302 if (!isLittleEndian) 1394 if (!isLittleEndian)
1303 printf("** "); 1395 printf("** ");
1304 if (tag.GetGroup() < 0x7f00) 1396 if (tag.GetGroup() < 0x7f00)
1305 std::cout << "Dataset: " << tag.Format() << " [" << Toolbox::ConvertToAscii(value).c_str() << "] (" << value.size() << ")" << std::endl; 1397 std::cout << "Dataset: " << tag.Format() << " " << EnumerationToString(vr)
1398 << " [" << Toolbox::ConvertToAscii(value).c_str() << "] (" << value.size() << ")" << std::endl;
1306 else 1399 else
1307 std::cout << "Dataset: " << tag.Format() << " [PIXEL] (" << value.size() << ")" << std::endl; 1400 std::cout << "Dataset: " << tag.Format() << " " << EnumerationToString(vr)
1401 << " [PIXEL] (" << value.size() << ")" << std::endl;
1308 1402
1309 return true; 1403 return true;
1310 } 1404 }
1311 }; 1405 };
1312 } 1406 }
1316 TEST(DicomStreamReader, DISABLED_Tutu) 1410 TEST(DicomStreamReader, DISABLED_Tutu)
1317 { 1411 {
1318 static const std::string PATH = "/home/jodogne/Subversion/orthanc-tests/Database/TransferSyntaxes/"; 1412 static const std::string PATH = "/home/jodogne/Subversion/orthanc-tests/Database/TransferSyntaxes/";
1319 1413
1320 std::string dicom; 1414 std::string dicom;
1321 //SystemToolbox::ReadFile(dicom, PATH + "../ColorTestMalaterre.dcm", false); 1415 SystemToolbox::ReadFile(dicom, PATH + "../ColorTestMalaterre.dcm", false);
1322 //SystemToolbox::ReadFile(dicom, PATH + "1.2.840.10008.1.2.1.dcm", false); 1416 //SystemToolbox::ReadFile(dicom, PATH + "1.2.840.10008.1.2.1.dcm", false);
1323 //SystemToolbox::ReadFile(dicom, PATH + "1.2.840.10008.1.2.2.dcm", false); // Big Endian 1417 //SystemToolbox::ReadFile(dicom, PATH + "1.2.840.10008.1.2.2.dcm", false); // Big Endian
1324 //SystemToolbox::ReadFile(dicom, PATH + "1.2.840.10008.1.2.4.50.dcm", false); 1418 //SystemToolbox::ReadFile(dicom, PATH + "1.2.840.10008.1.2.4.50.dcm", false);
1325 //SystemToolbox::ReadFile(dicom, PATH + "1.2.840.10008.1.2.4.51.dcm", false); 1419 //SystemToolbox::ReadFile(dicom, PATH + "1.2.840.10008.1.2.4.51.dcm", false);
1326 //SystemToolbox::ReadFile(dicom, PATH + "1.2.840.10008.1.2.4.57.dcm", false); 1420 //SystemToolbox::ReadFile(dicom, PATH + "1.2.840.10008.1.2.4.57.dcm", false);
1327 //SystemToolbox::ReadFile(dicom, PATH + "1.2.840.10008.1.2.4.70.dcm", false); 1421 //SystemToolbox::ReadFile(dicom, PATH + "1.2.840.10008.1.2.4.70.dcm", false);
1328 //SystemToolbox::ReadFile(dicom, PATH + "1.2.840.10008.1.2.4.80.dcm", false); 1422 //SystemToolbox::ReadFile(dicom, PATH + "1.2.840.10008.1.2.4.80.dcm", false);
1329 //SystemToolbox::ReadFile(dicom, PATH + "1.2.840.10008.1.2.4.81.dcm", false); 1423 //SystemToolbox::ReadFile(dicom, PATH + "1.2.840.10008.1.2.4.81.dcm", false);
1330 //SystemToolbox::ReadFile(dicom, PATH + "1.2.840.10008.1.2.4.90.dcm", false); 1424 //SystemToolbox::ReadFile(dicom, PATH + "1.2.840.10008.1.2.4.90.dcm", false);
1331 //SystemToolbox::ReadFile(dicom, PATH + "1.2.840.10008.1.2.4.91.dcm", false); 1425 //SystemToolbox::ReadFile(dicom, PATH + "1.2.840.10008.1.2.4.91.dcm", false);
1332 SystemToolbox::ReadFile(dicom, PATH + "1.2.840.10008.1.2.5.dcm", false); 1426 //SystemToolbox::ReadFile(dicom, PATH + "1.2.840.10008.1.2.5.dcm", false);
1333 1427
1334 std::stringstream stream; 1428 std::stringstream stream;
1335 size_t pos = 0; 1429 size_t pos = 0;
1336 1430
1337 DicomStreamReader r(stream); 1431 DicomStreamReader r(stream);
1338 V visitor; 1432 V visitor;