//-----------------------------------------------------------------------
    SceneManagerEnumerator::~SceneManagerEnumerator()
    {
		// Destroy all remaining instances
		// Really should have shutdown and unregistered by now, but catch here in case
		Instances instancesCopy = mInstances;
		for (Instances::iterator i = instancesCopy.begin(); i != instancesCopy.end(); ++i)
		{
			// destroy instances
			for(Factories::iterator f = mFactories.begin(); f != mFactories.end(); ++f)
			{
				if ((*f)->getMetaData().typeName == i->second->getTypeName())
				{
					(*f)->destroyInstance(i->second);
					mInstances.erase(i->first);
					break;
				}
			}

		}
		mInstances.clear();

    }
  static void AnonymizeOrModifyResource(DicomModification& modification,
                                        MetadataType metadataType,
                                        ChangeType changeType,
                                        ResourceType resourceType,
                                        RestApiPostCall& call)
  {
    bool isFirst = true;
    Json::Value result(Json::objectValue);

    ServerContext& context = OrthancRestApi::GetContext(call);

    typedef std::list<std::string> Instances;
    Instances instances;
    std::string id = call.GetUriComponent("id", "");
    context.GetIndex().GetChildInstances(instances, id);

    if (instances.empty())
    {
      return;
    }


    /**
     * Loop over all the instances of the resource.
     **/

    for (Instances::const_iterator it = instances.begin(); 
         it != instances.end(); ++it)
    {
      LOG(INFO) << "Modifying instance " << *it;

      std::auto_ptr<ServerContext::DicomCacheLocker> locker;

      try
      {
        locker.reset(new ServerContext::DicomCacheLocker(OrthancRestApi::GetContext(call), *it));
      }
      catch (OrthancException&)
      {
        // This child instance has been removed in between
        continue;
      }


      ParsedDicomFile& original = locker->GetDicom();
      DicomInstanceHasher originalHasher = original.GetHasher();


      /**
       * Compute the resulting DICOM instance.
       **/

      std::auto_ptr<ParsedDicomFile> modified(original.Clone());
      modification.Apply(*modified);

      DicomInstanceToStore toStore;
      toStore.SetParsedDicomFile(*modified);


      /**
       * Prepare the metadata information to associate with the
       * resulting DICOM instance (AnonymizedFrom/ModifiedFrom).
       **/

      DicomInstanceHasher modifiedHasher = modified->GetHasher();

      if (originalHasher.HashSeries() != modifiedHasher.HashSeries())
      {
        toStore.AddMetadata(ResourceType_Series, metadataType, originalHasher.HashSeries());
      }

      if (originalHasher.HashStudy() != modifiedHasher.HashStudy())
      {
        toStore.AddMetadata(ResourceType_Study, metadataType, originalHasher.HashStudy());
      }

      if (originalHasher.HashPatient() != modifiedHasher.HashPatient())
      {
        toStore.AddMetadata(ResourceType_Patient, metadataType, originalHasher.HashPatient());
      }

      assert(*it == originalHasher.HashInstance());
      toStore.AddMetadata(ResourceType_Instance, metadataType, *it);


      /**
       * Store the resulting DICOM instance into the Orthanc store.
       **/

      std::string modifiedInstance;
      if (context.Store(modifiedInstance, toStore) != StoreStatus_Success)
      {
        LOG(ERROR) << "Error while storing a modified instance " << *it;
        return;
      }

      // Sanity checks in debug mode
      assert(modifiedInstance == modifiedHasher.HashInstance());


      /**
       * Compute the JSON object that is returned by the REST call.
       **/

      if (isFirst)
      {
        std::string newId;

        switch (resourceType)
        {
          case ResourceType_Series:
            newId = modifiedHasher.HashSeries();
            break;

          case ResourceType_Study:
            newId = modifiedHasher.HashStudy();
            break;

          case ResourceType_Patient:
            newId = modifiedHasher.HashPatient();
            break;

          default:
            throw OrthancException(ErrorCode_InternalError);
        }

        result["Type"] = EnumerationToString(resourceType);
        result["ID"] = newId;
        result["Path"] = GetBasePath(resourceType, newId);
        result["PatientID"] = modifiedHasher.HashPatient();
        isFirst = false;
      }
    }

    call.GetOutput().AnswerJson(result);
  }
Esempio n. 3
0
  void Series::Load3DImage(void* target,
                           Orthanc::PixelFormat format,
                           size_t lineStride,
                           size_t stackStride,
                           Orthanc::ThreadedCommandProcessor::IListener* listener)
  {
    using namespace Orthanc;

    // Choose the extraction mode, depending on the format of the
    // target image.

    uint8_t bytesPerPixel;
    ImageExtractionMode mode;

    switch (format)
    {
      case PixelFormat_RGB24:
        bytesPerPixel = 3;
        mode = ImageExtractionMode_Preview;
        break;

      case PixelFormat_Grayscale8:
        bytesPerPixel = 1;
        mode = ImageExtractionMode_UInt8;  // Preview ???
        break; 

      case PixelFormat_Grayscale16:
        bytesPerPixel = 2;
        mode = ImageExtractionMode_UInt16;
        break;

      case PixelFormat_SignedGrayscale16:
        bytesPerPixel = 2;
        mode = ImageExtractionMode_UInt16;
        format = PixelFormat_Grayscale16;
        break;

      default:
        throw OrthancException(ErrorCode_NotImplemented);
    }


    // Check that the target image is properly sized
    unsigned int sx = GetWidth();
    unsigned int sy = GetHeight();

    if (lineStride < sx * bytesPerPixel ||
        stackStride < sx * sy * bytesPerPixel)
    {
      throw OrthancException(ErrorCode_BadRequest);
    }

    if (sx == 0 || sy == 0 || GetInstanceCount() == 0)
    {
      // Empty image, nothing to do
      if (listener)
        listener->SignalSuccess(0);
      return;
    }


    /**
     * Order the stacks according to their distance along the slice
     * normal (using the "Image Position Patient" tag). This works
     * even if the "SliceLocation" tag is absent.
     **/
    SliceLocator locator(GetInstance(0));

    typedef std::map<float, Instance*> Instances;
    Instances instances;
    for (unsigned int i = 0; i < GetInstanceCount(); i++)
    {
      float dist = locator.ComputeSliceLocation(GetInstance(i));
      instances[dist] = &GetInstance(i);
    }

    if (instances.size() != GetInstanceCount())
    {
      // Several instances have the same Z coordinate
      throw OrthancException(ErrorCode_NotImplemented);
    }


    // Submit the download of each stack as a set of commands
    ThreadedCommandProcessor processor(connection_.GetThreadCount());

    if (listener != NULL)
    {
      processor.SetListener(*listener);
    }

    uint8_t* stackTarget = reinterpret_cast<uint8_t*>(target);
    for (Instances::iterator it = instances.begin(); it != instances.end(); it++)
    {
      processor.Post(new ImageDownloadCommand(*it->second, format, mode, stackTarget, lineStride));
      stackTarget += stackStride;
    }


    // Wait for all the stacks to be downloaded
    if (!processor.Join())
    {
      throw OrthancException(ErrorCode_NetworkProtocol);
    }
  }