Exemplo n.º 1
0
 StoreStatus ServerContext::Store(std::string& resultPublicId,
                                  const char* dicomBuffer,
                                  size_t dicomSize)
 {
   ParsedDicomFile dicom(dicomBuffer, dicomSize);
   return Store(resultPublicId, dicom.GetDicom(), dicomBuffer, dicomSize);
 }
Exemplo n.º 2
0
int main(int argc, char **argv){
	S_LOG("main");
        logxx::GlobalLogLevel(logxx::warning);
        EncodingConverter converter;
        if (argc < 2){
                log(logxx::error) << "A path with dicom files should be specified" << logxx::endl;
                return 1;
        } else {
                std::string path(argv[1]);                
                if (path[path.length()-1] != '/')
                        path += '/';
                
                std::string csvFile = path + "out.csv";
                std::ofstream out(csvFile);
                if (out.good()){
                        Dir dir(path, true, ".dcm");
                        if (dir.Ok()) {
                                std::string fName;
                                while ((fName = dir.Read()).empty() == false) {
                                        log(logxx::debug) << "{" << fName << "}" << logxx::endl;
                                        Dicom dicom(path + fName);
                                        if (dicom.Parse(converter)){
                                                // cppcheck-suppress constStatement
                                                log(logxx::notice) << "{" << fName << "} Parsed" << logxx::endl;
                                                out << fName << "," << dicom << std::endl;

                                        } else {
                                                // cppcheck-suppress constStatement
                                                log(logxx::notice) << "{" << fName << "} Not parsed" << logxx::endl;
                                        }
                                        PrintProgress();
                                }
                                return 0;
                        } else {
                                log(logxx::error) << "Can't open path {" << path << "}" << logxx::endl;
                                return 1;
                        }
                } else {
                        log(logxx::error) << "Can't open file {" << csvFile <<  "} for writing"  << logxx::endl;
                        return 1;
                }
        }
}
Exemplo n.º 3
0
/* Helper funciton to read a directory of DICOM files using C++ */
static int read_dcm_dir_cpp(const char *path, Image *const im) {

        struct stat st;
        DIR *dir;
        struct dirent *ent;
        int i, nx, ny, nz, nc, num_files, off_z;

        // Verify that the directory exists
	if (stat(path, &st)) {
                SIFT3D_ERR("read_dcm_dir_cpp: cannot find file %s \n", path);
                return SIFT3D_FAILURE;
	} else if (!S_ISDIR(st.st_mode)) {
                SIFT3D_ERR("read_dcm_dir_cpp: file %s is not a directory \n",
                        path);
                return SIFT3D_FAILURE;
	}

        // Open the directory
        if ((dir = opendir(path)) == NULL) {
                SIFT3D_ERR("read_dcm_dir_cpp: unexpected error opening "
                        "directory %s \n", path);
                return SIFT3D_FAILURE;
        }

        // Get all of the .dcm files in the directory
        std::vector<Dicom> dicoms;
        while ((ent = readdir(dir)) != NULL) {

                // Form the full file path
                std::string fullfile(std::string(path) + sepStr + ent->d_name);

                // Check if it is a DICOM file 
                if (im_get_format(fullfile.c_str()) != DICOM)
                        continue;

                // Read the file
                Dicom dicom(fullfile);
                if (!dicom.isValid()) {
                        closedir(dir);
                        return SIFT3D_FAILURE;
                }

                // Add the file to the list
                dicoms.push_back(dicom);
        }

        // Release the directory
        closedir(dir);
        
        // Get the number of files
        num_files = dicoms.size();

        // Verify that dicom files were found
        if (num_files == 0) {
                SIFT3D_ERR("read_dcm_dir_cpp: no DICOM files found in %s \n",
                        path);
                return SIFT3D_FAILURE;
        }

        // Check that the files are from the same series
        const Dicom &first = dicoms[0];
        for (int i = 1; i < num_files; i++) {

                const Dicom &dicom = dicoms[i];

                if (!first.eqSeries(dicom)) {
                        SIFT3D_ERR("read_dcm_dir_cpp: file %s is from a "
                                "different series than file %s \n", 
                                dicom.name().c_str(), first.name().c_str());
                        return SIFT3D_FAILURE;
                }
        }

        // Initialize the output dimensions
        nx = first.getNx();
        ny = first.getNy();
        nc = first.getNc();

        // Verify the dimensions of the other files, counting the total
        // series z-dimension
        nz = 0;
        for (i = 0; i < num_files; i++) {

                // Get a slice
                const Dicom &dicom = dicoms[i];        

                // Verify the dimensions
                if (dicom.getNx() != nx || dicom.getNy() != ny || 
                        dicom.getNc() != nc) {
                        SIFT3D_ERR("read_dcm_dir_cpp: slice %s "
                                "(%d, %d, %d) does not match the "
                                "dimensions of slice %s (%d, %d, %d) \n",
                                dicom.name().c_str(), dicom.getNx(), 
                                dicom.getNy(), dicom.getNc(), 
                                first.name().c_str(), nx, ny, nc);
                        return SIFT3D_FAILURE;
                }

                // Count the z-dimension
                nz += dicom.getNz();
        }

        // Resize the output
        im->nx = nx;
        im->ny = ny;
        im->nz = nz;
        im->nc = nc;
        im->ux = first.getUx(); 
        im->uy = first.getUy();
        im->uz = first.getUz();
        im_default_stride(im);
        if (im_resize(im))
                return SIFT3D_FAILURE;

        // Sort the slices by z position
        std::sort(dicoms.begin(), dicoms.end()); 

        // Allocate a temporary image for the slices
        Image slice;
        init_im(&slice);

        // Read the image data
        off_z = 0;
        for (i = 0; i < num_files; i++) {

                int x, y, z, c;

                const char *slicename = dicoms[i].name().c_str();

                // Read the slice 
                if (read_dcm(slicename, &slice)) {
                        im_free(&slice);
                        return SIFT3D_FAILURE;
                }

                // Copy the data to the volume
                SIFT3D_IM_LOOP_START_C(&slice, x, y, z, c)

                        SIFT3D_IM_GET_VOX(im, x, y, z + off_z, c) =
                                SIFT3D_IM_GET_VOX(&slice, x, y, z, c);

                SIFT3D_IM_LOOP_END_C

                off_z += slice.nz;
        }
        assert(off_z == nz);
        im_free(&slice);

        return SIFT3D_SUCCESS;
} 
Exemplo n.º 4
0
/* Helper function to read a DICOM file using C++ */
static int read_dcm_cpp(const char *path, Image *const im) {

        // Read the image metadata
        Dicom dicom(path);
        if (!dicom.isValid())
                return SIFT3D_FAILURE;

        // Load the DicomImage object
        DicomImage dicomImage(path);
        if (dicomImage.getStatus() != EIS_Normal) {
                SIFT3D_ERR("read_dcm_cpp: failed to open image %s (%s)\n",
                        path, DicomImage::getString(dicomImage.getStatus()));
                return SIFT3D_FAILURE;
        }

        // Initialize the image fields
        im->nx = dicom.getNx();
        im->ny = dicom.getNy();
        im->nz = dicom.getNz();
        im->nc = dicom.getNc();
        im->ux = dicom.getUx();
        im->uy = dicom.getUy();
        im->uz = dicom.getUz();

        // Resize the output
        im_default_stride(im);
        if (im_resize(im))
                return SIFT3D_FAILURE;

        // Get the bit depth of the image
        const int bufNBits = 32;
        const int depth = dicomImage.getDepth();
        if (depth > bufNBits) {
                SIFT3D_ERR("read_dcm_cpp: buffer is insufficiently wide "
                        "for %d-bit data of image %s \n", depth, path);
                return SIFT3D_FAILURE;
        }

        // Get the number of bits by which we need to shift the 32-bit data, to
        // recover the original resolution (DICOM uses Big-endian encoding)
        const uint32_t shift = isLittleEndian() ? 
                static_cast<uint32_t>(bufNBits - depth) : 0;

        // Read each frame
        for (int i = 0; i < im->nz; i++) { 

                // Get a pointer to the data, rendered as a 32-bit int
                const uint32_t *const frameData = 
                        static_cast<const uint32_t *const>(
                                dicomImage.getOutputData(
                                        static_cast<int>(bufNBits), i));
                if (frameData == NULL) {
                        SIFT3D_ERR("read_dcm_cpp: could not get data from "
                                "image %s frame %d (%s)\n", path, i, 
                                DicomImage::getString(dicomImage.getStatus()));
                        return SIFT3D_FAILURE;
                }

                // Copy the frame
                const int x_start = 0;
                const int y_start = 0;
                const int z_start = i;
                const int x_end = im->nx - 1;
                const int y_end = im->ny - 1;
                const int z_end = z_start;
                int x, y, z;
                SIFT3D_IM_LOOP_LIMITED_START(im, x, y, z, x_start, x_end,
                        y_start, y_end, z_start, z_end)

                        // Get the voxel and shift it to match the original
                        // magnitude 
                        const uint32_t vox =
                                frameData[x + y * im->nx] >> shift;

                        // Convert to float and write to the output image
                        SIFT3D_IM_GET_VOX(im, x, y, z, 0) =
                                static_cast<float>(vox);

                SIFT3D_IM_LOOP_END
        }

        return SIFT3D_SUCCESS;
}
Exemplo n.º 5
0
    void ReconstructMainDicomTags(IDatabaseWrapper& database,
                                  IStorageArea& storageArea,
                                  ResourceType level)
    {
      // WARNING: The database should be locked with a transaction!

      // TODO: This function might consume much memory if level ==
      // ResourceType_Instance. To improve this, first download the
      // list of studies, then remove the instances for each single
      // study (check out OrthancRestApi::InvalidateTags for an
      // example). Take this improvement into consideration for the
      // next upgrade of the database schema.

      const char* plural = NULL;

      switch (level)
      {
        case ResourceType_Patient:
          plural = "patients";
          break;

        case ResourceType_Study:
          plural = "studies";
          break;

        case ResourceType_Series:
          plural = "series";
          break;

        case ResourceType_Instance:
          plural = "instances";
          break;

        default:
          throw OrthancException(ErrorCode_InternalError);
      }

      LOG(WARNING) << "Upgrade: Reconstructing the main DICOM tags of all the " << plural << "...";

      std::list<std::string> resources;
      database.GetAllPublicIds(resources, level);

      for (std::list<std::string>::const_iterator
             it = resources.begin(); it != resources.end(); ++it)
      {
        // Locate the resource and one of its child instances
        int64_t resource, instance;
        ResourceType tmp;

        if (!database.LookupResource(resource, tmp, *it) ||
            tmp != level ||
            !FindOneChildInstance(instance, database, resource, level))
        {
          LOG(ERROR) << "Cannot find an instance for " << EnumerationToString(level) 
                     << " with identifier " << *it;
          throw OrthancException(ErrorCode_InternalError);
        }

        // Get the DICOM file attached to some instances in the resource
        FileInfo attachment;
        if (!database.LookupAttachment(attachment, instance, FileContentType_Dicom))
        {
          LOG(ERROR) << "Cannot retrieve the DICOM file associated with instance " << database.GetPublicId(instance);
          throw OrthancException(ErrorCode_InternalError);
        }

        try
        {
          // Read and parse the content of the DICOM file
          StorageAccessor accessor(storageArea);

          std::string content;
          accessor.Read(content, attachment);

          ParsedDicomFile dicom(content);

          // Update the tags of this resource
          DicomMap dicomSummary;
          dicom.ExtractDicomSummary(dicomSummary);

          database.ClearMainDicomTags(resource);
          StoreMainDicomTags(database, resource, level, dicomSummary);
        }
        catch (OrthancException&)
        {
          LOG(ERROR) << "Cannot decode the DICOM file with UUID " << attachment.GetUuid()
                     << " associated with instance " << database.GetPublicId(instance);
          throw;
        }
      }
    }
  static void AddAnswer(DicomFindAnswers& answers,
                        const Json::Value& resource,
                        const DicomArray& query,
                        const std::list<DicomTag>& sequencesToReturn,
                        const DicomMap* counters)
  {
    DicomMap result;

    for (size_t i = 0; i < query.GetSize(); i++)
    {
      if (query.GetElement(i).GetTag() == DICOM_TAG_QUERY_RETRIEVE_LEVEL)
      {
        // Fix issue 30 on Google Code (QR response missing "Query/Retrieve Level" (008,0052))
        result.SetValue(query.GetElement(i).GetTag(), query.GetElement(i).GetValue());
      }
      else if (query.GetElement(i).GetTag() == DICOM_TAG_SPECIFIC_CHARACTER_SET)
      {
        // Do not include the encoding, this is handled by class ParsedDicomFile
      }
      else
      {
        std::string tag = query.GetElement(i).GetTag().Format();
        std::string value;
        if (resource.isMember(tag))
        {
          value = resource.get(tag, Json::arrayValue).get("Value", "").asString();
          result.SetValue(query.GetElement(i).GetTag(), value, false);
        }
        else
        {
          result.SetValue(query.GetElement(i).GetTag(), "", false);
        }
      }
    }

    if (counters != NULL)
    {
      DicomArray tmp(*counters);
      for (size_t i = 0; i < tmp.GetSize(); i++)
      {
        result.SetValue(tmp.GetElement(i).GetTag(), tmp.GetElement(i).GetValue().GetContent(), false);
      }
    }

    if (result.GetSize() == 0 &&
        sequencesToReturn.empty())
    {
      LOG(WARNING) << "The C-FIND request does not return any DICOM tag";
    }
    else if (sequencesToReturn.empty())
    {
      answers.Add(result);
    }
    else
    {
      ParsedDicomFile dicom(result);

      for (std::list<DicomTag>::const_iterator tag = sequencesToReturn.begin();
           tag != sequencesToReturn.end(); ++tag)
      {
        const Json::Value& source = resource[tag->Format()];

        if (source.type() == Json::objectValue &&
            source.isMember("Type") &&
            source.isMember("Value") &&
            source["Type"].asString() == "Sequence" &&
            source["Value"].type() == Json::arrayValue)
        {
          Json::Value content = Json::arrayValue;

          for (Json::Value::ArrayIndex i = 0; i < source["Value"].size(); i++)
          {
            Json::Value item;
            Toolbox::SimplifyTags(item, source["Value"][i], DicomToJsonFormat_Short);
            content.append(item);
          }

          dicom.Replace(*tag, content, false, DicomReplaceMode_InsertIfAbsent);
        }
      }

      answers.Add(dicom);
    }
  }