Mercurial > hg > orthanc
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 |