comparison OrthancServer/OrthancRestApi/OrthancRestAnonymizeModify.cpp @ 1565:4b23310eb7e8

add tags per instances in a series
author Sebastien Jodogne <s.jodogne@gmail.com>
date Fri, 21 Aug 2015 17:29:16 +0200
parents 1b7def486e62
children 3be6eb3757c8
comparison
equal deleted inserted replaced
1564:1b7def486e62 1565:4b23310eb7e8
486 486
487 return true; 487 return true;
488 } 488 }
489 489
490 490
491 static bool InjectTags(ParsedDicomFile& dicom,
492 const Json::Value& tags)
493 {
494 if (tags.type() != Json::objectValue)
495 {
496 LOG(ERROR) << "Bad syntax to specify the tags";
497 return false;
498 }
499
500 // Inject the user-specified tags
501 Json::Value::Members members = tags.getMemberNames();
502 for (size_t i = 0; i < members.size(); i++)
503 {
504 const std::string& name = members[i];
505 if (tags[name].type() != Json::stringValue)
506 {
507 LOG(ERROR) << "Only string values are supported when creating DICOM instances";
508 return false;
509 }
510
511 std::string value = tags[name].asString();
512
513 DicomTag tag = FromDcmtkBridge::ParseTag(name);
514 if (tag != DICOM_TAG_SPECIFIC_CHARACTER_SET)
515 {
516 if (tag != DICOM_TAG_PATIENT_ID &&
517 dicom.HasTag(tag))
518 {
519 LOG(ERROR) << "Trying to override a value inherited from a parent module";
520 return false;
521 }
522
523 if (tag == DICOM_TAG_PIXEL_DATA)
524 {
525 LOG(ERROR) << "Use \"Content\" to inject an image into a new DICOM instance";
526 return false;
527 }
528 else
529 {
530 dicom.Replace(tag, Toolbox::ConvertFromUtf8(value, dicom.GetEncoding()));
531 }
532 }
533 }
534
535 return true;
536 }
537
538
491 static void CreateSeries(RestApiPostCall& call, 539 static void CreateSeries(RestApiPostCall& call,
492 ParsedDicomFile& base /* in */, 540 ParsedDicomFile& base /* in */,
493 const Json::Value& content) 541 const Json::Value& content)
494 { 542 {
495 assert(content.isArray()); 543 assert(content.isArray());
501 549
502 std::string someInstance; 550 std::string someInstance;
503 551
504 for (Json::ArrayIndex i = 0; i < content.size(); i++) 552 for (Json::ArrayIndex i = 0; i < content.size(); i++)
505 { 553 {
506 if (content[i].type() != Json::stringValue) 554 std::auto_ptr<ParsedDicomFile> dicom(base.Clone());
555 const Json::Value* payload = NULL;
556
557 if (content[i].type() == Json::stringValue)
558 {
559 payload = &content[i];
560 }
561 else if (content[i].type() == Json::objectValue)
562 {
563 if (!content[i].isMember("Content"))
564 {
565 LOG(ERROR) << "No payload is present for one instance in the series";
566 return;
567 }
568
569 payload = &content[i]["Content"];
570
571 if (content[i].isMember("Tags") &&
572 !InjectTags(*dicom, content[i]["Tags"]))
573 {
574 return;
575 }
576 }
577
578 if (payload == NULL ||
579 payload->type() != Json::stringValue)
507 { 580 {
508 LOG(ERROR) << "The payload of the DICOM instance must be specified according to Data URI scheme"; 581 LOG(ERROR) << "The payload of the DICOM instance must be specified according to Data URI scheme";
509 return; 582 return;
510 } 583 }
511 584
512 std::auto_ptr<ParsedDicomFile> dicom(base.Clone()); 585 dicom->EmbedContent(payload->asString());
513 dicom->EmbedContent(content[i].asString());
514 dicom->Replace(DICOM_TAG_INSTANCE_NUMBER, boost::lexical_cast<std::string>(i + 1)); 586 dicom->Replace(DICOM_TAG_INSTANCE_NUMBER, boost::lexical_cast<std::string>(i + 1));
515 dicom->Replace(DICOM_TAG_IMAGE_INDEX, boost::lexical_cast<std::string>(i + 1)); 587 dicom->Replace(DICOM_TAG_IMAGE_INDEX, boost::lexical_cast<std::string>(i + 1));
516 588
517 if (!StoreCreatedInstance(someInstance, context, *dicom)) 589 if (!StoreCreatedInstance(someInstance, context, *dicom))
518 { 590 {
539 request["Tags"].type() != Json::objectValue) 611 request["Tags"].type() != Json::objectValue)
540 { 612 {
541 return; 613 return;
542 } 614 }
543 615
544 Encoding encoding;
545
546 if (request["Tags"].isMember("SpecificCharacterSet"))
547 {
548 const char* tmp = request["Tags"]["SpecificCharacterSet"].asCString();
549 if (!GetDicomEncoding(encoding, tmp))
550 {
551 LOG(ERROR) << "Unknown specific character set: " << tmp;
552 return;
553 }
554 }
555 else
556 {
557 std::string tmp = Configuration::GetGlobalStringParameter("DefaultEncoding", "Latin1");
558 encoding = StringToEncoding(tmp.c_str());
559 }
560
561 ParsedDicomFile dicom; 616 ParsedDicomFile dicom;
562 dicom.SetEncoding(encoding); 617
618 {
619 Encoding encoding;
620
621 if (request["Tags"].isMember("SpecificCharacterSet"))
622 {
623 const char* tmp = request["Tags"]["SpecificCharacterSet"].asCString();
624 if (!GetDicomEncoding(encoding, tmp))
625 {
626 LOG(ERROR) << "Unknown specific character set: " << tmp;
627 return;
628 }
629 }
630 else
631 {
632 std::string tmp = Configuration::GetGlobalStringParameter("DefaultEncoding", "Latin1");
633 encoding = StringToEncoding(tmp.c_str());
634 }
635
636 dicom.SetEncoding(encoding);
637 }
563 638
564 ResourceType parentType = ResourceType_Instance; 639 ResourceType parentType = ResourceType_Instance;
565 640
566 if (request.isMember("Parent")) 641 if (request.isMember("Parent"))
567 { 642 {
593 return; // Error: No instance (should never happen) 668 return; // Error: No instance (should never happen)
594 } 669 }
595 670
596 context.ReadJson(siblingTags, siblingInstances.front()); 671 context.ReadJson(siblingTags, siblingInstances.front());
597 } 672 }
673
674
675 // Choose the same encoding as the parent resource
676 {
677 static const char* SPECIFIC_CHARACTER_SET = "0008,0005";
678
679 if (siblingTags.isMember(SPECIFIC_CHARACTER_SET))
680 {
681 Encoding encoding;
682 if (!siblingTags[SPECIFIC_CHARACTER_SET].isMember("Value") ||
683 siblingTags[SPECIFIC_CHARACTER_SET]["Value"].type() != Json::stringValue ||
684 !GetDicomEncoding(encoding, siblingTags[SPECIFIC_CHARACTER_SET]["Value"].asCString()))
685 {
686 LOG(ERROR) << "Unable to get the encoding of the parent resource";
687 return;
688 }
689
690 dicom.SetEncoding(encoding);
691 }
692 }
693
598 694
599 // Retrieve the tags for all the parent modules 695 // Retrieve the tags for all the parent modules
600 typedef std::set<DicomTag> ModuleTags; 696 typedef std::set<DicomTag> ModuleTags;
601 ModuleTags moduleTags; 697 ModuleTags moduleTags;
602 698
633 dicom.Replace(*it, ""); 729 dicom.Replace(*it, "");
634 } 730 }
635 else if (tag["Type"] == "String") 731 else if (tag["Type"] == "String")
636 { 732 {
637 std::string value = tag["Value"].asString(); 733 std::string value = tag["Value"].asString();
638 dicom.Replace(*it, Toolbox::ConvertFromUtf8(value, encoding)); 734 dicom.Replace(*it, Toolbox::ConvertFromUtf8(value, dicom.GetEncoding()));
639 } 735 }
640 } 736 }
641 } 737 }
642 } 738 }
643 739
644 740
645 // Inject time-related information 741 // Inject time-related information
646 std::string date, time; 742 std::string date, time;
647 Toolbox::GetNowDicom(date, time); 743 Toolbox::GetNowDicom(date, time);
648 dicom.Replace(DICOM_TAG_ACQUISITION_DATE, date); 744 dicom.Replace(DICOM_TAG_ACQUISITION_DATE, date);
649 dicom.Replace(DICOM_TAG_ACQUISITION_TIME, time); 745 dicom.Replace(DICOM_TAG_ACQUISITION_TIME, time);
666 dicom.Replace(DICOM_TAG_STUDY_DATE, date); 762 dicom.Replace(DICOM_TAG_STUDY_DATE, date);
667 dicom.Replace(DICOM_TAG_STUDY_TIME, time); 763 dicom.Replace(DICOM_TAG_STUDY_TIME, time);
668 } 764 }
669 765
670 766
671 // Inject the user-specified tags 767 if (!InjectTags(dicom, request["Tags"]))
672 Json::Value::Members members = request["Tags"].getMemberNames(); 768 {
673 for (size_t i = 0; i < members.size(); i++) 769 return; // Error
674 { 770 }
675 const std::string& name = members[i]; 771
676 if (request["Tags"][name].type() != Json::stringValue)
677 {
678 LOG(ERROR) << "Only string values are supported when creating DICOM instances";
679 return;
680 }
681
682 std::string value = request["Tags"][name].asString();
683
684 DicomTag tag = FromDcmtkBridge::ParseTag(name);
685 if (tag != DICOM_TAG_SPECIFIC_CHARACTER_SET)
686 {
687 if (dicom.HasTag(tag))
688 {
689 LOG(ERROR) << "Trying to override a value inherited from a parent module";
690 return;
691 }
692
693 if (tag == DICOM_TAG_PIXEL_DATA)
694 {
695 LOG(ERROR) << "Use \"Content\" to inject an image into a new DICOM instance";
696 return;
697 }
698 else
699 {
700 dicom.Replace(tag, Toolbox::ConvertFromUtf8(value, encoding));
701 }
702 }
703 }
704 772
705 // Inject the content (either an image, or a PDF file) 773 // Inject the content (either an image, or a PDF file)
706 if (request.isMember("Content")) 774 if (request.isMember("Content"))
707 { 775 {
708 const Json::Value& content = request["Content"]; 776 const Json::Value& content = request["Content"];
714 } 782 }
715 else if (content.type() == Json::arrayValue) 783 else if (content.type() == Json::arrayValue)
716 { 784 {
717 if (content.size() > 0) 785 if (content.size() > 0)
718 { 786 {
719 // Let's create a series 787 // Let's create a series instead of a single instance
720 CreateSeries(call, dicom, content); 788 CreateSeries(call, dicom, content);
721 return; 789 return;
722 } 790 }
723 } 791 }
724 else 792 else