# HG changeset patch # User Sebastien Jodogne # Date 1481197506 -3600 # Node ID 9b373b7d671387a158176e69c4fff0befbf46eb4 # Parent 307365d0991ac5297c85ae0ae19b433574a3d0d9 Fix handling of encodings in C-FIND requests diff -r 307365d0991a -r 9b373b7d6713 Core/DicomFormat/DicomMap.h --- a/Core/DicomFormat/DicomMap.h Tue Dec 06 14:40:46 2016 +0100 +++ b/Core/DicomFormat/DicomMap.h Thu Dec 08 12:45:06 2016 +0100 @@ -47,7 +47,7 @@ private: friend class DicomArray; friend class FromDcmtkBridge; - friend class ToDcmtkBridge; + friend class ParsedDicomFile; typedef std::map Map; diff -r 307365d0991a -r 9b373b7d6713 Core/Enumerations.cpp --- a/Core/Enumerations.cpp Tue Dec 06 14:40:46 2016 +0100 +++ b/Core/Enumerations.cpp Thu Dec 08 12:45:06 2016 +0100 @@ -1083,15 +1083,18 @@ bool GetDicomEncoding(Encoding& encoding, const char* specificCharacterSet) { - std::string s = specificCharacterSet; + std::string s = Toolbox::StripSpaces(specificCharacterSet); Toolbox::ToUpperCase(s); // http://dicom.nema.org/medical/dicom/current/output/html/part03.html#sect_C.12.1.1.2 // https://github.com/dcm4che/dcm4che/blob/master/dcm4che-core/src/main/java/org/dcm4che3/data/SpecificCharacterSet.java if (s == "ISO_IR 6" || - s == "ISO_IR 192" || s == "ISO 2022 IR 6") { + encoding = Encoding_Ascii; + } + else if (s == "ISO_IR 192") + { encoding = Encoding_Utf8; } else if (s == "ISO_IR 100" || @@ -1238,8 +1241,10 @@ // http://dicom.nema.org/medical/dicom/current/output/html/part03.html#sect_C.12.1.1.2 switch (encoding) { + case Encoding_Ascii: + return "ISO_IR 6"; + case Encoding_Utf8: - case Encoding_Ascii: return "ISO_IR 192"; case Encoding_Latin1: diff -r 307365d0991a -r 9b373b7d6713 NEWS --- a/NEWS Tue Dec 06 14:40:46 2016 +0100 +++ b/NEWS Thu Dec 08 12:45:06 2016 +0100 @@ -18,6 +18,7 @@ to avoid waiting for the completion of image transfers * Possibility to DELETE "dicom-as-json" attachments to reconstruct the JSON summaries * "Keep" option for modifications to keep original DICOM identifiers (advanced feature) +* "/tools/default-encoding" to get or temporarily change the default encoding Plugins ------- @@ -29,6 +30,7 @@ Maintenance ----------- +* Fix handling of encodings in C-FIND requests * Use of DCMTK 3.6.1 dictionary of private tags in standalone builds * Avoid hard crash if not enough memory (handling of std::bad_alloc) * Improved robustness of Orthanc Explorer wrt. query/retrieve (maybe fix issue 24) diff -r 307365d0991a -r 9b373b7d6713 OrthancServer/DicomProtocol/DicomFindAnswers.cpp --- a/OrthancServer/DicomProtocol/DicomFindAnswers.cpp Tue Dec 06 14:40:46 2016 +0100 +++ b/OrthancServer/DicomProtocol/DicomFindAnswers.cpp Thu Dec 08 12:45:06 2016 +0100 @@ -109,19 +109,6 @@ return *dicom_; } - - DcmDataset* ExtractDcmDataset() const - { - if (dicom_ != NULL) - { - return new DcmDataset(*dicom_->GetDcmtkObject().getDataset()); - } - else - { - assert(map_ != NULL); - return ToDcmtkBridge::Convert(*map_); - } - } }; @@ -200,7 +187,7 @@ DcmDataset* DicomFindAnswers::ExtractDcmDataset(size_t index) const { - return GetAnswerInternal(index).ExtractDcmDataset(); + return new DcmDataset(*GetAnswer(index).GetDcmtkObject().getDataset()); } diff -r 307365d0991a -r 9b373b7d6713 OrthancServer/DicomProtocol/DicomUserConnection.cpp --- a/OrthancServer/DicomProtocol/DicomUserConnection.cpp Tue Dec 06 14:40:46 2016 +0100 +++ b/OrthancServer/DicomProtocol/DicomUserConnection.cpp Thu Dec 08 12:45:06 2016 +0100 @@ -478,8 +478,8 @@ } - static DcmDataset* ConvertQueryFields(const DicomMap& fields, - ModalityManufacturer manufacturer) + static ParsedDicomFile* ConvertQueryFields(const DicomMap& fields, + ModalityManufacturer manufacturer) { switch (manufacturer) { @@ -513,11 +513,11 @@ } } - return ToDcmtkBridge::Convert(*fix); + return new ParsedDicomFile(*fix); } default: - return ToDcmtkBridge::Convert(fields); + return new ParsedDicomFile(fields); } } @@ -577,7 +577,9 @@ CheckIsOpen(); - std::auto_ptr dataset(ConvertQueryFields(fields, manufacturer_)); + std::auto_ptr query(ConvertQueryFields(fields, manufacturer_)); + DcmDataset* dataset = query->GetDcmtkObject().getDataset(); + const char* clevel = NULL; const char* sopClass = NULL; @@ -585,19 +587,19 @@ { case ResourceType_Patient: clevel = "PATIENT"; - DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0052), "PATIENT"); + DU_putStringDOElement(dataset, DcmTagKey(0x0008, 0x0052), "PATIENT"); sopClass = UID_FINDPatientRootQueryRetrieveInformationModel; break; case ResourceType_Study: clevel = "STUDY"; - DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0052), "STUDY"); + DU_putStringDOElement(dataset, DcmTagKey(0x0008, 0x0052), "STUDY"); sopClass = UID_FINDStudyRootQueryRetrieveInformationModel; break; case ResourceType_Series: clevel = "SERIES"; - DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0052), "SERIES"); + DU_putStringDOElement(dataset, DcmTagKey(0x0008, 0x0052), "SERIES"); sopClass = UID_FINDStudyRootQueryRetrieveInformationModel; break; @@ -609,11 +611,11 @@ // This is a particular case for ClearCanvas, thanks to Peter Somlo . // https://groups.google.com/d/msg/orthanc-users/j-6C3MAVwiw/iolB9hclom8J // http://www.clearcanvas.ca/Home/Community/OldForums/tabid/526/aff/11/aft/14670/afv/topic/Default.aspx - DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0052), "IMAGE"); + DU_putStringDOElement(dataset, DcmTagKey(0x0008, 0x0052), "IMAGE"); } else { - DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0052), "INSTANCE"); + DU_putStringDOElement(dataset, DcmTagKey(0x0008, 0x0052), "INSTANCE"); } sopClass = UID_FINDStudyRootQueryRetrieveInformationModel; @@ -630,26 +632,26 @@ case ResourceType_Instance: // SOP Instance UID if (!fields.HasTag(0x0008, 0x0018)) - DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0018), ""); + DU_putStringDOElement(dataset, DcmTagKey(0x0008, 0x0018), ""); case ResourceType_Series: // Series instance UID if (!fields.HasTag(0x0020, 0x000e)) - DU_putStringDOElement(dataset.get(), DcmTagKey(0x0020, 0x000e), ""); + DU_putStringDOElement(dataset, DcmTagKey(0x0020, 0x000e), ""); case ResourceType_Study: // Accession number if (!fields.HasTag(0x0008, 0x0050)) - DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0050), ""); + DU_putStringDOElement(dataset, DcmTagKey(0x0008, 0x0050), ""); // Study instance UID if (!fields.HasTag(0x0020, 0x000d)) - DU_putStringDOElement(dataset.get(), DcmTagKey(0x0020, 0x000d), ""); + DU_putStringDOElement(dataset, DcmTagKey(0x0020, 0x000d), ""); case ResourceType_Patient: // Patient ID if (!fields.HasTag(0x0010, 0x0020)) - DU_putStringDOElement(dataset.get(), DcmTagKey(0x0010, 0x0020), ""); + DU_putStringDOElement(dataset, DcmTagKey(0x0010, 0x0020), ""); break; @@ -658,7 +660,7 @@ } assert(clevel != NULL && sopClass != NULL); - ExecuteFind(result, pimpl_->assoc_, dataset.get(), sopClass, false, clevel, pimpl_->dimseTimeout_); + ExecuteFind(result, pimpl_->assoc_, dataset, sopClass, false, clevel, pimpl_->dimseTimeout_); } @@ -668,21 +670,22 @@ { CheckIsOpen(); - std::auto_ptr dataset(ConvertQueryFields(fields, manufacturer_)); + std::auto_ptr query(ConvertQueryFields(fields, manufacturer_)); + DcmDataset* dataset = query->GetDcmtkObject().getDataset(); const char* sopClass = UID_MOVEStudyRootQueryRetrieveInformationModel; switch (level) { case ResourceType_Patient: - DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0052), "PATIENT"); + DU_putStringDOElement(dataset, DcmTagKey(0x0008, 0x0052), "PATIENT"); break; case ResourceType_Study: - DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0052), "STUDY"); + DU_putStringDOElement(dataset, DcmTagKey(0x0008, 0x0052), "STUDY"); break; case ResourceType_Series: - DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0052), "SERIES"); + DU_putStringDOElement(dataset, DcmTagKey(0x0008, 0x0052), "SERIES"); break; case ResourceType_Instance: @@ -692,11 +695,11 @@ // This is a particular case for ClearCanvas, thanks to Peter Somlo . // https://groups.google.com/d/msg/orthanc-users/j-6C3MAVwiw/iolB9hclom8J // http://www.clearcanvas.ca/Home/Community/OldForums/tabid/526/aff/11/aft/14670/afv/topic/Default.aspx - DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0052), "IMAGE"); + DU_putStringDOElement(dataset, DcmTagKey(0x0008, 0x0052), "IMAGE"); } else { - DU_putStringDOElement(dataset.get(), DcmTagKey(0x0008, 0x0052), "INSTANCE"); + DU_putStringDOElement(dataset, DcmTagKey(0x0008, 0x0052), "INSTANCE"); } break; @@ -722,7 +725,7 @@ T_DIMSE_C_MoveRSP response; DcmDataset* statusDetail = NULL; DcmDataset* responseIdentifiers = NULL; - OFCondition cond = DIMSE_moveUser(pimpl_->assoc_, presID, &request, dataset.get(), + OFCondition cond = DIMSE_moveUser(pimpl_->assoc_, presID, &request, dataset, NULL, NULL, /*opt_blockMode*/ DIMSE_BLOCKING, /*opt_dimse_timeout*/ pimpl_->dimseTimeout_, diff -r 307365d0991a -r 9b373b7d6713 OrthancServer/OrthancInitialization.cpp --- a/OrthancServer/OrthancInitialization.cpp Tue Dec 06 14:40:46 2016 +0100 +++ b/OrthancServer/OrthancInitialization.cpp Thu Dec 08 12:45:06 2016 +0100 @@ -1111,6 +1111,19 @@ } + void Configuration::SetDefaultEncoding(Encoding encoding) + { + std::string name = EnumerationToString(encoding); + + { + boost::recursive_mutex::scoped_lock lock(globalMutex_); + configuration_["DefaultEncoding"] = name; + } + + LOG(INFO) << "Default encoding was changed to: " << name; + } + + bool Configuration::HasConfigurationChanged() { Json::Value starting; diff -r 307365d0991a -r 9b373b7d6713 OrthancServer/OrthancInitialization.h --- a/OrthancServer/OrthancInitialization.h Tue Dec 06 14:40:46 2016 +0100 +++ b/OrthancServer/OrthancInitialization.h Thu Dec 08 12:45:06 2016 +0100 @@ -138,6 +138,8 @@ static Encoding GetDefaultEncoding(); + static void SetDefaultEncoding(Encoding encoding); + static bool HasConfigurationChanged(); diff -r 307365d0991a -r 9b373b7d6713 OrthancServer/OrthancRestApi/OrthancRestSystem.cpp --- a/OrthancServer/OrthancRestApi/OrthancRestSystem.cpp Tue Dec 06 14:40:46 2016 +0100 +++ b/OrthancServer/OrthancRestApi/OrthancRestSystem.cpp Thu Dec 08 12:45:06 2016 +0100 @@ -248,6 +248,23 @@ } + static void GetDefaultEncoding(RestApiGetCall& call) + { + Encoding encoding = Configuration::GetDefaultEncoding(); + call.GetOutput().AnswerBuffer(EnumerationToString(encoding), "text/plain"); + } + + + static void SetDefaultEncoding(RestApiPutCall& call) + { + Encoding encoding = StringToEncoding(call.GetBodyData()); + + Configuration::SetDefaultEncoding(encoding); + + call.GetOutput().AnswerBuffer(EnumerationToString(encoding), "text/plain"); + } + + void OrthancRestApi::RegisterSystem() { Register("/", ServeRoot); @@ -257,6 +274,8 @@ Register("/tools/execute-script", ExecuteScript); Register("/tools/now", GetNowIsoString); Register("/tools/dicom-conformance", GetDicomConformanceStatement); + Register("/tools/default-encoding", GetDefaultEncoding); + Register("/tools/default-encoding", SetDefaultEncoding); Register("/plugins", ListPlugins); Register("/plugins/{id}", GetPlugin); diff -r 307365d0991a -r 9b373b7d6713 OrthancServer/ParsedDicomFile.cpp --- a/OrthancServer/ParsedDicomFile.cpp Tue Dec 06 14:40:46 2016 +0100 +++ b/OrthancServer/ParsedDicomFile.cpp Thu Dec 08 12:45:06 2016 +0100 @@ -872,15 +872,55 @@ } - ParsedDicomFile::ParsedDicomFile(const DicomMap& map) : pimpl_(new PImpl) + void ParsedDicomFile::CreateFromDicomMap(const DicomMap& source, + Encoding defaultEncoding) { - std::auto_ptr dataset(ToDcmtkBridge::Convert(map)); + pimpl_->file_.reset(new DcmFileFormat); + + const DicomValue* tmp = source.TestAndGetValue(DICOM_TAG_SPECIFIC_CHARACTER_SET); + if (tmp != NULL) + { + Encoding encoding; + if (tmp->IsNull() || + tmp->IsBinary() || + !GetDicomEncoding(encoding, tmp->GetContent().c_str())) + { + throw OrthancException(ErrorCode_ParameterOutOfRange); + } + else + { + SetEncoding(encoding); + } + } + else + { + SetEncoding(defaultEncoding); + } - // NOTE: This implies an unnecessary memory copy of the dataset, but no way to get around - // http://support.dcmtk.org/redmine/issues/544 - std::auto_ptr fileFormat(new DcmFileFormat(dataset.get())); + for (DicomMap::Map::const_iterator + it = source.map_.begin(); it != source.map_.end(); ++it) + { + if (it->first != DICOM_TAG_SPECIFIC_CHARACTER_SET && + !it->second->IsNull()) + { + ReplacePlainString(it->first, it->second->GetContent()); + } + } + } + - pimpl_->file_.reset(fileFormat.release()); + ParsedDicomFile::ParsedDicomFile(const DicomMap& map, + Encoding defaultEncoding) : + pimpl_(new PImpl) + { + CreateFromDicomMap(map, defaultEncoding); + } + + + ParsedDicomFile::ParsedDicomFile(const DicomMap& map) : + pimpl_(new PImpl) + { + CreateFromDicomMap(map, Configuration::GetDefaultEncoding()); } diff -r 307365d0991a -r 9b373b7d6713 OrthancServer/ParsedDicomFile.h --- a/OrthancServer/ParsedDicomFile.h Tue Dec 06 14:40:46 2016 +0100 +++ b/OrthancServer/ParsedDicomFile.h Thu Dec 08 12:45:06 2016 +0100 @@ -52,6 +52,9 @@ ParsedDicomFile(ParsedDicomFile& other); + void CreateFromDicomMap(const DicomMap& source, + Encoding defaultEncoding); + void RemovePrivateTagsInternal(const std::set* toKeep); void UpdateStorageUid(const DicomTag& tag, @@ -65,6 +68,9 @@ public: ParsedDicomFile(bool createIdentifiers); // Create a minimal DICOM instance + ParsedDicomFile(const DicomMap& map, + Encoding defaultEncoding); + ParsedDicomFile(const DicomMap& map); ParsedDicomFile(const void* content, diff -r 307365d0991a -r 9b373b7d6713 OrthancServer/ToDcmtkBridge.cpp --- a/OrthancServer/ToDcmtkBridge.cpp Tue Dec 06 14:40:46 2016 +0100 +++ b/OrthancServer/ToDcmtkBridge.cpp Thu Dec 08 12:45:06 2016 +0100 @@ -41,24 +41,6 @@ namespace Orthanc { - DcmDataset* ToDcmtkBridge::Convert(const DicomMap& map) - { - std::auto_ptr result(new DcmDataset); - - for (DicomMap::Map::const_iterator - it = map.map_.begin(); it != map.map_.end(); ++it) - { - if (!it->second->IsNull()) - { - std::string s = it->second->GetContent(); - DU_putStringDOElement(result.get(), Convert(it->first), s.c_str()); - } - } - - return result.release(); - } - - DcmEVR ToDcmtkBridge::Convert(ValueRepresentation vr) { switch (vr) diff -r 307365d0991a -r 9b373b7d6713 OrthancServer/ToDcmtkBridge.h --- a/OrthancServer/ToDcmtkBridge.h Tue Dec 06 14:40:46 2016 +0100 +++ b/OrthancServer/ToDcmtkBridge.h Thu Dec 08 12:45:06 2016 +0100 @@ -45,8 +45,6 @@ return DcmTagKey(tag.GetGroup(), tag.GetElement()); } - static DcmDataset* Convert(const DicomMap& map); - static DcmEVR Convert(ValueRepresentation vr); }; } diff -r 307365d0991a -r 9b373b7d6713 TODO --- a/TODO Tue Dec 06 14:40:46 2016 +0100 +++ b/TODO Thu Dec 08 12:45:06 2016 +0100 @@ -114,6 +114,8 @@ * Use Semaphore::Locker everywhere (instead of explicit Release() and Acquire()) +* Avoid direct calls to FromDcmtkBridge, go through ParsedDicomFile + wherever possible ================= diff -r 307365d0991a -r 9b373b7d6713 UnitTestsSources/FromDcmtkTests.cpp --- a/UnitTestsSources/FromDcmtkTests.cpp Tue Dec 06 14:40:46 2016 +0100 +++ b/UnitTestsSources/FromDcmtkTests.cpp Thu Dec 08 12:45:06 2016 +0100 @@ -51,6 +51,7 @@ #include "../Plugins/Engine/PluginsEnumerations.h" #include +#include using namespace Orthanc; @@ -225,7 +226,7 @@ Encoding e; ASSERT_FALSE(GetDicomEncoding(e, "")); - ASSERT_TRUE(GetDicomEncoding(e, "ISO_IR 6")); ASSERT_EQ(Encoding_Utf8, e); + ASSERT_TRUE(GetDicomEncoding(e, "ISO_IR 6")); ASSERT_EQ(Encoding_Ascii, e); // http://dicom.nema.org/medical/dicom/current/output/html/part03.html#table_C.12-2 ASSERT_TRUE(GetDicomEncoding(e, "ISO_IR 100")); ASSERT_EQ(Encoding_Latin1, e); @@ -241,7 +242,7 @@ ASSERT_TRUE(GetDicomEncoding(e, "ISO_IR 166")); ASSERT_EQ(Encoding_Thai, e); // http://dicom.nema.org/medical/dicom/current/output/html/part03.html#table_C.12-3 - ASSERT_TRUE(GetDicomEncoding(e, "ISO 2022 IR 6")); ASSERT_EQ(Encoding_Utf8, e); + ASSERT_TRUE(GetDicomEncoding(e, "ISO 2022 IR 6")); ASSERT_EQ(Encoding_Ascii, e); ASSERT_TRUE(GetDicomEncoding(e, "ISO 2022 IR 100")); ASSERT_EQ(Encoding_Latin1, e); ASSERT_TRUE(GetDicomEncoding(e, "ISO 2022 IR 101")); ASSERT_EQ(Encoding_Latin2, e); ASSERT_TRUE(GetDicomEncoding(e, "ISO 2022 IR 109")); ASSERT_EQ(Encoding_Latin3, e); @@ -1042,3 +1043,129 @@ } } } + + + +static void CheckEncoding(const ParsedDicomFile& dicom, + Encoding expected) +{ + const char* value = NULL; + ASSERT_TRUE(dicom.GetDcmtkObject().getDataset()->findAndGetString(DCM_SpecificCharacterSet, value).good()); + + Encoding encoding; + ASSERT_TRUE(GetDicomEncoding(encoding, value)); + ASSERT_EQ(expected, encoding); +} + + +TEST(ParsedDicomFile, DicomMapEncodings1) +{ + Configuration::SetDefaultEncoding(Encoding_Ascii); + ASSERT_EQ(Encoding_Ascii, Configuration::GetDefaultEncoding()); + + { + DicomMap m; + ParsedDicomFile dicom(m); + ASSERT_EQ(1, dicom.GetDcmtkObject().getDataset()->card()); + CheckEncoding(dicom, Encoding_Ascii); + } + + { + DicomMap m; + ParsedDicomFile dicom(m, Encoding_Latin4); + ASSERT_EQ(1, dicom.GetDcmtkObject().getDataset()->card()); + CheckEncoding(dicom, Encoding_Latin4); + } + + { + DicomMap m; + m.SetValue(DICOM_TAG_SPECIFIC_CHARACTER_SET, "ISO_IR 148", false); + ParsedDicomFile dicom(m); + ASSERT_EQ(1, dicom.GetDcmtkObject().getDataset()->card()); + CheckEncoding(dicom, Encoding_Latin5); + } + + { + DicomMap m; + m.SetValue(DICOM_TAG_SPECIFIC_CHARACTER_SET, "ISO_IR 148", false); + ParsedDicomFile dicom(m, Encoding_Latin1); + ASSERT_EQ(1, dicom.GetDcmtkObject().getDataset()->card()); + CheckEncoding(dicom, Encoding_Latin5); + } +} + + +TEST(ParsedDicomFile, DicomMapEncodings2) +{ + const char* utf8 = NULL; + for (unsigned int i = 0; i < testEncodingsCount; i++) + { + if (testEncodings[i] == Encoding_Utf8) + { + utf8 = testEncodingsEncoded[i]; + break; + } + } + + ASSERT_TRUE(utf8 != NULL); + + for (unsigned int i = 0; i < testEncodingsCount; i++) + { + // 1251 codepage is not supported by the core DICOM standard, ignore it + if (testEncodings[i] != Encoding_Windows1251) + { + { + // Sanity check to test the proper behavior of "EncodingTests.py" + std::string encoded = Toolbox::ConvertFromUtf8(testEncodingsExpected[i], testEncodings[i]); + ASSERT_STREQ(testEncodingsEncoded[i], encoded.c_str()); + std::string decoded = Toolbox::ConvertToUtf8(encoded, testEncodings[i]); + ASSERT_STREQ(testEncodingsExpected[i], decoded.c_str()); + + if (testEncodings[i] != Encoding_Chinese) + { + // A specific source string is used in "EncodingTests.py" to + // test against Chinese, it is normal that it does not correspond to UTF8 + + std::string encoded = Toolbox::ConvertToUtf8(Toolbox::ConvertFromUtf8(utf8, testEncodings[i]), testEncodings[i]); + ASSERT_STREQ(testEncodingsExpected[i], encoded.c_str()); + } + } + + + Json::Value v; + + { + DicomMap m; + m.SetValue(DICOM_TAG_PATIENT_NAME, testEncodingsExpected[i], false); + + ParsedDicomFile dicom(m, testEncodings[i]); + + const char* encoded = NULL; + ASSERT_TRUE(dicom.GetDcmtkObject().getDataset()->findAndGetString(DCM_PatientName, encoded).good()); + ASSERT_STREQ(testEncodingsEncoded[i], encoded); + + dicom.DatasetToJson(v, DicomToJsonFormat_Human, DicomToJsonFlags_Default, 0); + + Encoding encoding; + ASSERT_TRUE(GetDicomEncoding(encoding, v["SpecificCharacterSet"].asCString())); + ASSERT_EQ(encoding, testEncodings[i]); + ASSERT_STREQ(testEncodingsExpected[i], v["PatientName"].asCString()); + } + + + { + DicomMap m; + m.SetValue(DICOM_TAG_SPECIFIC_CHARACTER_SET, GetDicomSpecificCharacterSet(testEncodings[i]), false); + m.SetValue(DICOM_TAG_PATIENT_NAME, testEncodingsExpected[i], false); + + ParsedDicomFile dicom(m, testEncodings[i]); + + Json::Value v2; + dicom.DatasetToJson(v2, DicomToJsonFormat_Human, DicomToJsonFlags_Default, 0); + + ASSERT_EQ(v2["PatientName"].asString(), v["PatientName"].asString()); + ASSERT_EQ(v2["SpecificCharacterSet"].asString(), v["SpecificCharacterSet"].asString()); + } + } + } +}