Beispiel #1
0
      void Mosaic::execute ()
      {
        const std::vector<File::Entry>& files (H.get_files());
        if (files.empty()) throw Exception ("no files specified in header for image \"" + H.name() + "\"");
        assert (H.datatype().bits() > 1);

        segsize = H.dim (0) * H.dim (1) * H.dim (2);
        assert (segsize * files.size() == DataSet::voxel_count (H));

        size_t bytes_per_segment = H.datatype().bytes() * segsize;
        if (files.size() * bytes_per_segment > std::numeric_limits<size_t>::max())
          throw Exception ("image \"" + H.name() + "\" is larger than maximum accessible memory");

        debug ("loading mosaic image \"" + H.name() + "\"...");
        addresses.resize (1);
        addresses[0] = new uint8_t [files.size() * bytes_per_segment];
        if (!addresses[0]) throw Exception ("failed to allocate memory for image \"" + H.name() + "\"");

        ProgressBar progress ("reformatting DICOM mosaic images...", slices*files.size());
        uint8_t* data = addresses[0];
        for (size_t n = 0; n < files.size(); n++) {
          File::MMap file (files[n], false, m_xdim * m_ydim * H.datatype().bytes());
          size_t nx = 0, ny = 0;
          for (size_t z = 0; z < slices; z++) {
            size_t ox = nx*xdim;
            size_t oy = ny*ydim;
            for (size_t y = 0; y < ydim; y++) {
              memcpy (data, file.address() + H.datatype().bytes() * (ox + m_xdim* (y+oy)), xdim * H.datatype().bytes());
              data += xdim * H.datatype().bytes();
            }
            nx++;
            if (nx >= m_xdim / xdim) {
              nx = 0;
              ny++;
            }
            ++progress;
          }
        }

        segsize = std::numeric_limits<size_t>::max();
      }
Beispiel #2
0
    void Default::copy_to_mem (const Header& header)
    {
      DEBUG ("loading image \"" + header.name() + "\"...");
      addresses.resize (files.size() > 1 && header.datatype().bits() *segsize != 8*size_t (bytes_per_segment) ? files.size() : 1);
      addresses[0].reset (new uint8_t [files.size() * bytes_per_segment]);
      if (!addresses[0]) 
        throw Exception ("failed to allocate memory for image \"" + header.name() + "\"");

      if (is_new) memset (addresses[0].get(), 0, files.size() * bytes_per_segment);
      else {
        for (size_t n = 0; n < files.size(); n++) {
          File::MMap file (files[n], false, false, bytes_per_segment);
          memcpy (addresses[0].get() + n*bytes_per_segment, file.address(), bytes_per_segment);
        }
      }

      if (addresses.size() > 1)
        for (size_t n = 1; n < addresses.size(); n++)
          addresses[n].reset (addresses[0].get() + n*bytes_per_segment);
      else segsize = std::numeric_limits<size_t>::max();
    }
Beispiel #3
0
      void Mosaic::load ()
      {
        if (files.empty())
          throw Exception ("no files specified in header for image \"" + name + "\"");

        assert (datatype.bits() > 1);

        size_t bytes_per_segment = datatype.bytes() * segsize;
        if (files.size() * bytes_per_segment > std::numeric_limits<size_t>::max())
          throw Exception ("image \"" + name + "\" is larger than maximum accessible memory");

        DEBUG ("loading mosaic image \"" + name + "\"...");
        addresses.resize (1);
        addresses[0].reset (new uint8_t [files.size() * bytes_per_segment]);
        if (!addresses[0])
          throw Exception ("failed to allocate memory for image \"" + name + "\"");

        ProgressBar progress ("reformatting DICOM mosaic images...", slices*files.size());
        uint8_t* data = addresses[0].get();
        for (size_t n = 0; n < files.size(); n++) {
          File::MMap file (files[n], false, false, m_xdim * m_ydim * datatype.bytes());
          size_t nx = 0, ny = 0;
          for (size_t z = 0; z < slices; z++) {
            size_t ox = nx*xdim;
            size_t oy = ny*ydim;
            for (size_t y = 0; y < ydim; y++) {
              memcpy (data, file.address() + datatype.bytes() * (ox + m_xdim* (y+oy)), xdim * datatype.bytes());
              data += xdim * datatype.bytes();
            }
            nx++;
            if (nx >= m_xdim / xdim) {
              nx = 0;
              ny++;
            }
            ++progress;
          }
        }

        segsize = std::numeric_limits<size_t>::max();
      }
Beispiel #4
0
      void dicom_to_mapper (
          MR::Image::Mapper& dmap, 
          MR::Image::Header& H, 
          std::vector< RefPtr<Series> >& series_list)
      {
        assert (series_list.size() > 0);
        H.format = FormatDICOM;

        Patient* patient (series_list[0]->study->patient);
        String sbuf = ( patient->name.size() ? patient->name : "unnamed" );
        sbuf += " " + format_ID (patient->ID);
        if (series_list[0]->modality.size()) sbuf += String (" [") + series_list[0]->modality + "]";
        if (series_list[0]->name.size()) sbuf += String (" ") + series_list[0]->name;
        H.comments.push_back (sbuf);
        H.name = sbuf;

        // build up sorted list of frames:
        std::vector<Frame*> frames;

        // loop over series list:
        for (std::vector< RefPtr<Series> >::const_iterator series_it = series_list.begin(); series_it != series_list.end(); ++series_it) {
          Series& series (**series_it);

          try {
            series.read();
          }
          catch (Exception) { 
            throw Exception ("error reading series " + str (series.number) + " of DICOM image \"" + H.name + "\""); 
          }

          std::sort (series.begin(), series.end());

          // loop over images in each series:
          for (Series::const_iterator image_it = series.begin(); image_it != series.end(); ++image_it) {
            Image& image (**image_it);

            // if multi-frame, loop over frames in image:
            if (image.frames.size()) {
              std::sort (image.frames.begin(), image.frames.end());
              for (std::vector< RefPtr<Frame> >::const_iterator frame_it = image.frames.begin(); frame_it != image.frames.end(); ++frame_it) 
                frames.push_back (&**frame_it);
            }
            // otherwise add image frame:
            else 
              frames.push_back (&image);

          }
        }

        std::vector<guint> dim = Frame::count (frames);

        if (dim[0] > 1) { // switch axes so slice dim is inner-most:
          std::vector<Frame*> list (frames);
          std::vector<Frame*>::iterator it = frames.begin();
          for (guint k = 0; k < dim[2]; ++k) 
            for (guint i = 0; i < dim[0]; ++i) 
              for (guint j = 0; j < dim[1]; ++j) 
                *(it++) = list[i+dim[0]*(j+dim[1]*k)];
        }

        gfloat slice_separation = Frame::get_slice_separation (frames, dim[1]);


        if (series_list[0]->study->name.size()) {
          sbuf = "study: " + series_list[0]->study->name;
          H.comments.push_back (sbuf);
        }

        if (patient->DOB.size()) {
          sbuf = "DOB: " + format_date (patient->DOB);
          H.comments.push_back (sbuf);
        }

        if (series_list[0]->date.size()) {
          sbuf = "DOS: " + format_date (series_list[0]->date);
          if (series_list[0]->time.size()) 
            sbuf += " " + format_time (series_list[0]->time);
          H.comments.push_back (sbuf);
        }





        MR::Image::Axes& axes (H.axes);
        const Image& image (*(*series_list[0])[0]);

        guint nchannels = image.frames.size() ? 1 : image.data_size / (image.dim[0] * image.dim[1] * (image.bits_alloc/8));
        if (nchannels > 1) 
          info ("data segment is larger than expected from image dimensions - interpreting as multi-channel data");

        axes.set_ndim (3 + (dim[0]*dim[2]>1) + (nchannels>1));

        guint current_axis = 3;
        guint current_stride = 0;

        add_axis ("channel", axes, current_axis, current_stride, nchannels);

        axes.axis[0] = current_stride++;
        axes.dim[0] = image.dim[0];
        axes.vox[0] = image.pixel_size[0];
        axes.desc[0] = MR::Image::Axis::left_to_right;
        axes.units[0] = MR::Image::Axis::millimeters;

        axes.axis[1] = current_stride++;
        axes.dim[1] = image.dim[1];
        axes.vox[1] = image.pixel_size[1];
        axes.desc[1] = MR::Image::Axis::posterior_to_anterior;
        axes.units[1] = MR::Image::Axis::millimeters;

        axes.axis[2] = current_stride++;
        axes.dim[2] = dim[1];
        axes.vox[2] = slice_separation;
        axes.desc[2] = MR::Image::Axis::inferior_to_superior;
        axes.units[2] = MR::Image::Axis::millimeters;

        add_axis ("volume", axes, current_axis, current_stride, dim[0]*dim[2]);

        if (image.bits_alloc == 8) H.data_type = DataType::UInt8;
        else if (image.bits_alloc == 16) {
          H.data_type = DataType::UInt16;
          if (image.is_BE) H.data_type.set_flag (DataType::BigEndian);
          else H.data_type.set_flag (DataType::LittleEndian);
        }
        else throw Exception ("unexpected number of allocated bits per pixel (" + str (image.bits_alloc) 
            + ") in file \"" + H.name + "\"");

        H.offset = image.scale_intercept;
        H.scale = image.scale_slope;

        Math::Matrix M(4,4);

        M(0,0) = -image.orientation_x[0];
        M(1,0) = -image.orientation_x[1];
        M(2,0) = image.orientation_x[2];
        M(3,0) = 0.0;

        M(0,1) = -image.orientation_y[0];
        M(1,1) = -image.orientation_y[1];
        M(2,1) = image.orientation_y[2];
        M(3,1) = 0.0;

        M(0,2) = -image.orientation_z[0];
        M(1,2) = -image.orientation_z[1];
        M(2,2) = image.orientation_z[2];
        M(3,2) = 0.0;

        M(0,3) = -image.position_vector[0];
        M(1,3) = -image.position_vector[1];
        M(2,3) = image.position_vector[2];
        M(3,3) = 1.0;

        H.set_transform (M);


        H.DW_scheme = Frame::get_DW_scheme (frames, dim[1], M);



        for (guint n = 1; n < frames.size(); ++n) // check consistency of data scaling:
          if (frames[n]->scale_intercept != frames[n-1]->scale_intercept ||
              frames[n]->scale_slope != frames[n-1]->scale_slope)
            throw Exception ("unable to load series due to inconsistent data scaling between DICOM images");


        if (image.frames.size()) { // need to preload and re-arrange:
          ProgressBar::init (frames.size(), "DICOM image contains multiple frames - reformating..."); 

          guint8* mem = NULL;
          try { 
            mem = new guint8 [H.memory_footprint()]; 
            if (!mem) throw;
          }
          catch (...) { 
            throw Exception ("failed to allocate memory for image data!"); 
          }

          guint8* dest = mem;
          const guint row_stride = nchannels * frames[0]->row_stride * (frames[0]->bits_alloc/8);
          const guint row_size = nchannels * frames[0]->dim[0] * (frames[0]->bits_alloc/8);
          File::MMap mmap;
          for (guint n = 0; n < frames.size(); ++n) {
            mmap.init (frames[n]->filename);
            mmap.map();
            const guint8* src = (guint8*) mmap.address() + frames[n]->data;
            for (guint row = 0; row < frames[n]->dim[1]; ++row) {
              memcpy (dest, src, row_size);
              dest += row_size;
              src += row_stride;
            }
            ProgressBar::inc();
          }
          ProgressBar::done();

          dmap.add (mem);

        }
        else { // use standard backend:
          
          for (guint n = 0; n < frames.size(); ++n) {
            const Image* image = static_cast<const Image*> (frames[n]);
            dmap.add (image->filename, image->data);
          }

        }


      
      }