Mercurial > hg > orthanc
comparison OrthancServer/FromDcmtkBridge.cpp @ 306:326d5a4a5af3
modification of instances
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Thu, 20 Dec 2012 16:44:50 +0100 |
parents | 86bb79522f19 |
children | fbf2b2282086 |
comparison
equal
deleted
inserted
replaced
305:86bb79522f19 | 306:326d5a4a5af3 |
---|---|
37 | 37 |
38 #include "ToDcmtkBridge.h" | 38 #include "ToDcmtkBridge.h" |
39 #include "../Core/Toolbox.h" | 39 #include "../Core/Toolbox.h" |
40 #include "../Core/OrthancException.h" | 40 #include "../Core/OrthancException.h" |
41 #include "../Core/PngWriter.h" | 41 #include "../Core/PngWriter.h" |
42 #include "../Core/Uuid.h" | |
42 #include "../Core/DicomFormat/DicomString.h" | 43 #include "../Core/DicomFormat/DicomString.h" |
43 #include "../Core/DicomFormat/DicomNullValue.h" | 44 #include "../Core/DicomFormat/DicomNullValue.h" |
44 #include "../Core/DicomFormat/DicomIntegerPixelAccessor.h" | 45 #include "../Core/DicomFormat/DicomIntegerPixelAccessor.h" |
45 | 46 |
47 #include <list> | |
46 #include <limits> | 48 #include <limits> |
47 | 49 |
48 #include <boost/lexical_cast.hpp> | 50 #include <boost/lexical_cast.hpp> |
49 | 51 |
50 #include <dcmtk/dcmdata/dcchrstr.h> | 52 #include <dcmtk/dcmdata/dcchrstr.h> |
548 | 550 |
549 | 551 |
550 void ParsedDicomFile::Remove(const DicomTag& tag) | 552 void ParsedDicomFile::Remove(const DicomTag& tag) |
551 { | 553 { |
552 DcmTagKey key(tag.GetGroup(), tag.GetElement()); | 554 DcmTagKey key(tag.GetGroup(), tag.GetElement()); |
553 | 555 DcmElement* element = file_->getDataset()->remove(key); |
554 // TODO This call results in memory leaks inside DCMTK | 556 if (element != NULL) |
555 file_->getDataset()->remove(key); | 557 { |
558 delete element; | |
559 } | |
560 } | |
561 | |
562 | |
563 | |
564 void ParsedDicomFile::RemovePrivateTags() | |
565 { | |
566 typedef std::list<DcmElement*> Tags; | |
567 | |
568 Tags privateTags; | |
569 | |
570 DcmDataset& dataset = *file_->getDataset(); | |
571 for (unsigned long i = 0; i < dataset.card(); i++) | |
572 { | |
573 DcmElement* element = dataset.getElement(i); | |
574 DcmTag tag(element->getTag()); | |
575 if (tag.getPrivateCreator() != NULL) | |
576 { | |
577 privateTags.push_back(element); | |
578 } | |
579 } | |
580 | |
581 for (Tags::iterator it = privateTags.begin(); | |
582 it != privateTags.end(); it++) | |
583 { | |
584 DcmElement* tmp = dataset.remove(*it); | |
585 if (tmp != NULL) | |
586 { | |
587 delete tmp; | |
588 } | |
589 } | |
556 } | 590 } |
557 | 591 |
558 | 592 |
559 | 593 |
560 void ParsedDicomFile::Insert(const DicomTag& tag, | 594 void ParsedDicomFile::Insert(const DicomTag& tag, |
679 { | 713 { |
680 | 714 |
681 /** | 715 /** |
682 * TODO. | 716 * TODO. |
683 **/ | 717 **/ |
684 | 718 |
685 case EVR_DS: // decimal string | |
686 case EVR_IS: // integer string | |
687 case EVR_OB: // other byte | 719 case EVR_OB: // other byte |
688 case EVR_OF: // other float | 720 case EVR_OF: // other float |
689 case EVR_OW: // other word | 721 case EVR_OW: // other word |
690 case EVR_AS: // age string | |
691 case EVR_AT: // attribute tag | 722 case EVR_AT: // attribute tag |
692 case EVR_DA: // date string | |
693 case EVR_DT: // date time string | |
694 case EVR_TM: // time string | |
695 case EVR_UN: // unknown value representation | 723 case EVR_UN: // unknown value representation |
696 return new DicomNullValue(); | 724 return new DicomNullValue(); |
697 | 725 |
698 | |
699 /** | 726 /** |
700 * String types, should never happen at this point because of | 727 * String types, should never happen at this point because of |
701 * "element.isaString()". | 728 * "element.isaString()". |
702 **/ | 729 **/ |
703 | 730 |
731 case EVR_DS: // decimal string | |
732 case EVR_IS: // integer string | |
733 case EVR_AS: // age string | |
734 case EVR_DA: // date string | |
735 case EVR_DT: // date time string | |
736 case EVR_TM: // time string | |
704 case EVR_AE: // application entity title | 737 case EVR_AE: // application entity title |
705 case EVR_CS: // code string | 738 case EVR_CS: // code string |
706 case EVR_SH: // short string | 739 case EVR_SH: // short string |
707 case EVR_LO: // long string | 740 case EVR_LO: // long string |
708 case EVR_ST: // short text | 741 case EVR_ST: // short text |
719 | 752 |
720 case EVR_SL: // signed long | 753 case EVR_SL: // signed long |
721 { | 754 { |
722 Sint32 f; | 755 Sint32 f; |
723 if (dynamic_cast<DcmSignedLong&>(element).getSint32(f).good()) | 756 if (dynamic_cast<DcmSignedLong&>(element).getSint32(f).good()) |
724 { | |
725 return new DicomString(boost::lexical_cast<std::string>(f)); | 757 return new DicomString(boost::lexical_cast<std::string>(f)); |
726 } | |
727 else | 758 else |
728 { | |
729 return new DicomNullValue(); | 759 return new DicomNullValue(); |
730 } | |
731 } | 760 } |
732 | 761 |
733 case EVR_SS: // signed short | 762 case EVR_SS: // signed short |
734 { | 763 { |
735 Sint16 f; | 764 Sint16 f; |
736 if (dynamic_cast<DcmSignedShort&>(element).getSint16(f).good()) | 765 if (dynamic_cast<DcmSignedShort&>(element).getSint16(f).good()) |
737 { | |
738 return new DicomString(boost::lexical_cast<std::string>(f)); | 766 return new DicomString(boost::lexical_cast<std::string>(f)); |
739 } | |
740 else | 767 else |
741 { | |
742 return new DicomNullValue(); | 768 return new DicomNullValue(); |
743 } | |
744 } | 769 } |
745 | 770 |
746 case EVR_UL: // unsigned long | 771 case EVR_UL: // unsigned long |
747 { | 772 { |
748 Uint32 f; | 773 Uint32 f; |
749 if (dynamic_cast<DcmUnsignedLong&>(element).getUint32(f).good()) | 774 if (dynamic_cast<DcmUnsignedLong&>(element).getUint32(f).good()) |
750 { | |
751 return new DicomString(boost::lexical_cast<std::string>(f)); | 775 return new DicomString(boost::lexical_cast<std::string>(f)); |
752 } | |
753 else | 776 else |
754 { | |
755 return new DicomNullValue(); | 777 return new DicomNullValue(); |
756 } | |
757 } | 778 } |
758 | 779 |
759 case EVR_US: // unsigned short | 780 case EVR_US: // unsigned short |
760 { | 781 { |
761 Uint16 f; | 782 Uint16 f; |
762 if (dynamic_cast<DcmUnsignedShort&>(element).getUint16(f).good()) | 783 if (dynamic_cast<DcmUnsignedShort&>(element).getUint16(f).good()) |
763 { | |
764 return new DicomString(boost::lexical_cast<std::string>(f)); | 784 return new DicomString(boost::lexical_cast<std::string>(f)); |
765 } | |
766 else | 785 else |
767 { | |
768 return new DicomNullValue(); | 786 return new DicomNullValue(); |
769 } | |
770 } | 787 } |
771 | 788 |
772 case EVR_FL: // float single-precision | 789 case EVR_FL: // float single-precision |
773 { | 790 { |
774 Float32 f; | 791 Float32 f; |
775 if (dynamic_cast<DcmFloatingPointSingle&>(element).getFloat32(f).good()) | 792 if (dynamic_cast<DcmFloatingPointSingle&>(element).getFloat32(f).good()) |
776 { | |
777 return new DicomString(boost::lexical_cast<std::string>(f)); | 793 return new DicomString(boost::lexical_cast<std::string>(f)); |
778 } | |
779 else | 794 else |
780 { | |
781 return new DicomNullValue(); | 795 return new DicomNullValue(); |
782 } | |
783 } | 796 } |
784 | 797 |
785 case EVR_FD: // float double-precision | 798 case EVR_FD: // float double-precision |
786 { | 799 { |
787 Float64 f; | 800 Float64 f; |
788 if (dynamic_cast<DcmFloatingPointDouble&>(element).getFloat64(f).good()) | 801 if (dynamic_cast<DcmFloatingPointDouble&>(element).getFloat64(f).good()) |
789 { | |
790 return new DicomString(boost::lexical_cast<std::string>(f)); | 802 return new DicomString(boost::lexical_cast<std::string>(f)); |
791 } | |
792 else | 803 else |
793 { | |
794 return new DicomNullValue(); | 804 return new DicomNullValue(); |
795 } | |
796 } | 805 } |
797 | 806 |
798 | 807 |
799 /** | 808 /** |
800 * Sequence types, should never occur at this point because of | 809 * Sequence types, should never occur at this point because of |
839 } | 848 } |
840 catch (boost::bad_lexical_cast) | 849 catch (boost::bad_lexical_cast) |
841 { | 850 { |
842 return new DicomNullValue; | 851 return new DicomNullValue; |
843 } | 852 } |
853 catch (std::bad_cast) | |
854 { | |
855 return new DicomNullValue; | |
856 } | |
844 } | 857 } |
845 | 858 |
846 | 859 |
847 static void StoreElement(Json::Value& target, | 860 static void StoreElement(Json::Value& target, |
848 DcmElement& element, | 861 DcmElement& element, |
874 #if 0 | 887 #if 0 |
875 const std::string tagName = FromDcmtkBridge::GetName(tag); | 888 const std::string tagName = FromDcmtkBridge::GetName(tag); |
876 #else | 889 #else |
877 // This version of the code gives access to the name of the private tags | 890 // This version of the code gives access to the name of the private tags |
878 DcmTag tagbis(element.getTag()); | 891 DcmTag tagbis(element.getTag()); |
879 const std::string tagName(tagbis.getTagName()); | 892 const std::string tagName(tagbis.getTagName()); |
880 #endif | 893 #endif |
881 | 894 |
882 if (element.isLeaf()) | 895 if (element.isLeaf()) |
883 { | 896 { |
884 Json::Value value(Json::objectValue); | 897 Json::Value value(Json::objectValue); |
885 value["Name"] = tagName; | 898 value["Name"] = tagName; |
899 | |
900 if (tagbis.getPrivateCreator() != NULL) | |
901 { | |
902 value["PrivateCreator"] = tagbis.getPrivateCreator(); | |
903 } | |
886 | 904 |
887 std::auto_ptr<DicomValue> v(FromDcmtkBridge::ConvertLeafElement(element)); | 905 std::auto_ptr<DicomValue> v(FromDcmtkBridge::ConvertLeafElement(element)); |
888 if (v->IsNull()) | 906 if (v->IsNull()) |
889 { | 907 { |
890 value["Type"] = "Null"; | 908 value["Type"] = "Null"; |
1122 #if 0 | 1140 #if 0 |
1123 DcmTagKey tag(t.GetGroup(), t.GetElement()); | 1141 DcmTagKey tag(t.GetGroup(), t.GetElement()); |
1124 const DcmDataDictionary& dict = dcmDataDict.rdlock(); | 1142 const DcmDataDictionary& dict = dcmDataDict.rdlock(); |
1125 const DcmDictEntry* entry = dict.findEntry(tag, NULL); | 1143 const DcmDictEntry* entry = dict.findEntry(tag, NULL); |
1126 | 1144 |
1127 std::string s("Unknown"); | 1145 std::string s(DcmTag_ERROR_TagName); |
1128 if (entry != NULL) | 1146 if (entry != NULL) |
1129 { | 1147 { |
1130 s = std::string(entry->getTagName()); | 1148 s = std::string(entry->getTagName()); |
1131 } | 1149 } |
1132 | 1150 |
1135 #else | 1153 #else |
1136 DcmTag tag(t.GetGroup(), t.GetElement()); | 1154 DcmTag tag(t.GetGroup(), t.GetElement()); |
1137 const char* name = tag.getTagName(); | 1155 const char* name = tag.getTagName(); |
1138 if (name == NULL) | 1156 if (name == NULL) |
1139 { | 1157 { |
1140 return "Unknown"; | 1158 return DcmTag_ERROR_TagName; |
1141 } | 1159 } |
1142 else | 1160 else |
1143 { | 1161 { |
1144 return std::string(name); | 1162 return std::string(name); |
1145 } | 1163 } |
1229 { | 1247 { |
1230 char uid[100]; | 1248 char uid[100]; |
1231 | 1249 |
1232 switch (level) | 1250 switch (level) |
1233 { | 1251 { |
1252 case DicomRootLevel_Patient: | |
1253 { | |
1254 std::string uuid = Toolbox::GenerateUuid(); | |
1255 std::string id; | |
1256 id.reserve(uuid.size()); | |
1257 for (size_t i = 0; i < uuid.size() && i < 8; i++) | |
1258 { | |
1259 id.push_back(toupper(uuid[i])); | |
1260 } | |
1261 | |
1262 return id; | |
1263 } | |
1264 | |
1234 case DicomRootLevel_Instance: | 1265 case DicomRootLevel_Instance: |
1235 return dcmGenerateUniqueIdentifier(uid, SITE_INSTANCE_UID_ROOT); | 1266 return dcmGenerateUniqueIdentifier(uid, SITE_INSTANCE_UID_ROOT); |
1236 | 1267 |
1237 case DicomRootLevel_Series: | 1268 case DicomRootLevel_Series: |
1238 return dcmGenerateUniqueIdentifier(uid, SITE_SERIES_UID_ROOT); | 1269 return dcmGenerateUniqueIdentifier(uid, SITE_SERIES_UID_ROOT); |