Mercurial > hg > orthanc
comparison OrthancFramework/Sources/DicomParsing/FromDcmtkBridge.cpp @ 4527:31f940334496
Handle public tags with "UN" value representation and containing a string (cf. DICOM CP 246)
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Wed, 24 Feb 2021 12:39:35 +0100 |
parents | 671ee7c1fd46 |
children | 93a51d228d80 |
comparison
equal
deleted
inserted
replaced
4526:59b667dd58a8 | 4527:31f940334496 |
---|---|
552 { | 552 { |
553 return DicomTag(element.getGTag(), element.getETag()); | 553 return DicomTag(element.getGTag(), element.getETag()); |
554 } | 554 } |
555 | 555 |
556 | 556 |
557 static DicomValue* CreateValueFromUtf8String(const DicomTag& tag, | |
558 const std::string& utf8, | |
559 unsigned int maxStringLength, | |
560 const std::set<DicomTag>& ignoreTagLength) | |
561 { | |
562 if (maxStringLength != 0 && | |
563 utf8.size() > maxStringLength && | |
564 ignoreTagLength.find(tag) == ignoreTagLength.end()) | |
565 { | |
566 return new DicomValue; // Too long, create a NULL value | |
567 } | |
568 else | |
569 { | |
570 return new DicomValue(utf8, false); | |
571 } | |
572 } | |
573 | |
574 | |
557 DicomValue* FromDcmtkBridge::ConvertLeafElement(DcmElement& element, | 575 DicomValue* FromDcmtkBridge::ConvertLeafElement(DcmElement& element, |
558 DicomToJsonFlags flags, | 576 DicomToJsonFlags flags, |
559 unsigned int maxStringLength, | 577 unsigned int maxStringLength, |
560 Encoding encoding, | 578 Encoding encoding, |
561 bool hasCodeExtensions, | 579 bool hasCodeExtensions, |
565 { | 583 { |
566 // This function is only applicable to leaf elements | 584 // This function is only applicable to leaf elements |
567 throw OrthancException(ErrorCode_BadParameterType); | 585 throw OrthancException(ErrorCode_BadParameterType); |
568 } | 586 } |
569 | 587 |
570 char *c = NULL; | 588 { |
571 if (element.isaString() && | 589 char *c = NULL; |
572 element.getString(c).good()) | 590 if (element.isaString() && |
573 { | 591 element.getString(c).good()) |
574 if (c == NULL) // This case corresponds to the empty string | 592 { |
575 { | 593 if (c == NULL) // This case corresponds to the empty string |
576 return new DicomValue("", false); | 594 { |
577 } | 595 return new DicomValue("", false); |
578 else | |
579 { | |
580 std::string s(c); | |
581 std::string utf8 = Toolbox::ConvertToUtf8(s, encoding, hasCodeExtensions); | |
582 | |
583 if (maxStringLength != 0 && | |
584 utf8.size() > maxStringLength && | |
585 ignoreTagLength.find(GetTag(element)) == ignoreTagLength.end()) | |
586 { | |
587 return new DicomValue; // Too long, create a NULL value | |
588 } | 596 } |
589 else | 597 else |
590 { | 598 { |
591 return new DicomValue(utf8, false); | 599 const std::string s(c); |
600 const std::string utf8 = Toolbox::ConvertToUtf8(s, encoding, hasCodeExtensions); | |
601 return CreateValueFromUtf8String(GetTag(element), utf8, maxStringLength, ignoreTagLength); | |
592 } | 602 } |
593 } | 603 } |
594 } | 604 } |
595 | 605 |
596 | 606 |
597 if (element.getVR() == EVR_UN) | 607 if (element.getVR() == EVR_UN) |
598 { | 608 { |
599 // Unknown value representation: Lookup in the dictionary. This | 609 /** |
600 // is notably the case for private tags registered with the | 610 * Unknown value representation: Lookup in the dictionary. This |
601 // "Dictionary" configuration option. | 611 * is notably the case for private tags registered with the |
612 * "Dictionary" configuration option, or for public tags with | |
613 * "EVR_UN" in the case of Little Endian Implicit transfer | |
614 * syntax (cf. DICOM CP 246). | |
615 * ftp://medical.nema.org/medical/dicom/final/cp246_ft.pdf | |
616 **/ | |
602 DictionaryLocker locker; | 617 DictionaryLocker locker; |
603 | 618 |
604 const DcmDictEntry* entry = locker->findEntry(element.getTag().getXTag(), | 619 const DcmDictEntry* entry = locker->findEntry(element.getTag().getXTag(), |
605 element.getTag().getPrivateCreator()); | 620 element.getTag().getPrivateCreator()); |
606 if (entry != NULL && | 621 if (entry != NULL && |
607 entry->getVR().isaString()) | 622 entry->getVR().isaString()) |
608 { | 623 { |
609 Uint8* data = NULL; | 624 Uint8* data = NULL; |
610 | 625 |
611 // At (*), we do not try and convert to UTF-8, as nothing says | 626 if (element.getUint8Array(data) == EC_Normal) |
612 // the encoding of the private tag is the same as that of the | 627 { |
613 // remaining of the DICOM dataset. Only go for ASCII strings. | 628 Uint32 length = element.getLength(); |
614 | 629 |
615 if (element.getUint8Array(data) == EC_Normal && | 630 if (data == NULL || |
616 Toolbox::IsAsciiString(data, element.getLength())) // (*) | 631 length == 0) |
617 { | |
618 if (data == NULL) | |
619 { | 632 { |
620 return new DicomValue("", false); // Empty string | 633 return new DicomValue("", false); // Empty string |
621 } | 634 } |
622 else if (maxStringLength != 0 && | 635 |
623 element.getLength() > maxStringLength && | 636 // Remove the trailing padding, if any |
624 ignoreTagLength.find(GetTag(element)) == ignoreTagLength.end()) | 637 if (length > 0 && |
638 length % 2 == 0 && | |
639 data[length - 1] == '\0') | |
625 { | 640 { |
626 return new DicomValue; // Too long, create a NULL value | 641 length = length - 1; |
642 } | |
643 | |
644 if (element.getTag().isPrivate()) | |
645 { | |
646 // For private tags, we do not try and convert to UTF-8, | |
647 // as nothing ensures that the encoding of the private tag | |
648 // is the same as that of the remaining of the DICOM | |
649 // dataset. Only go for ASCII strings. | |
650 if (Toolbox::IsAsciiString(data, length)) | |
651 { | |
652 const std::string s(reinterpret_cast<const char*>(data), length); | |
653 return CreateValueFromUtf8String(GetTag(element), s, maxStringLength, ignoreTagLength); | |
654 } | |
655 else | |
656 { | |
657 // Not a plain ASCII string: Consider it as a binary | |
658 // value that is handled in the switch-case below | |
659 } | |
627 } | 660 } |
628 else | 661 else |
629 { | 662 { |
630 std::string s(reinterpret_cast<const char*>(data), element.getLength()); | 663 // For public tags, convert to UTF-8 by using the |
631 return new DicomValue(s, false); | 664 // "SpecificCharacterSet" tag, if present. This branch is |
665 // new in Orthanc 1.9.1 (cf. DICOM CP 246). | |
666 const std::string s(reinterpret_cast<const char*>(data), length); | |
667 const std::string utf8 = Toolbox::ConvertToUtf8(s, encoding, hasCodeExtensions); | |
668 return CreateValueFromUtf8String(GetTag(element), utf8, maxStringLength, ignoreTagLength); | |
632 } | 669 } |
633 } | 670 } |
634 } | 671 } |
635 } | 672 } |
636 | 673 |