Example #1
0
/* Convert an mxArray to an Image. mx must have at most IM_NDIMS + 1 
 * dimensions and be of type single (float). */
int mx2im(const mxArray *const mx, Image *const im) {

        const mwSize *mxDims;
        float *mxData;
        mwIndex mxNDims;
        int i, x, y, z, c, mxNSpaceDims;

        // Verify inputs
        mxNDims = (int) mxGetNumberOfDimensions(mx);
	if (mxNDims > MX_IM_NDIMS || !mxIsSingle(mx) || mxIsComplex(mx))
                return SIFT3D_FAILURE;

        // Copy the spatial dimensions
        mxNSpaceDims = SIFT3D_MIN((int) mxNDims, MX_IM_NDIMS - 1);
        mxDims = mxGetDimensions(mx);
        for (i = 0; i < mxNSpaceDims; i++) {
                SIFT3D_IM_GET_DIMS(im)[i] = (int) mxDims[i];
        }

        // Pad the unfilled dimensions with 1
        for (i = mxNSpaceDims; i < MX_IM_NDIMS - 1; i++) {
                SIFT3D_IM_GET_DIMS(im)[i] = 1; 
        } 

        // Copy the number of channels, defaulting to 1
        im->nc = mxNDims == MX_IM_NDIMS ? (int) mxDims[MX_IM_NDIMS] : 1;

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

        // Get the data
        if ((mxData = mxGetData(mx)) == NULL)
                return SIFT3D_FAILURE;

        // Transpose and copy the data
        SIFT3D_IM_LOOP_START_C(im, x, y, z, c)

                mwIndex idx;

                idx = mxImGetIdx(mx, x, y, z, c);

                SIFT3D_IM_GET_VOX(im, x, y, z, c) = mxData[idx];

        SIFT3D_IM_LOOP_END_C

        return SIFT3D_SUCCESS;
}
Example #2
0
/* Helper function to write an image to a directory of DICOM files using C++ */
static int write_dcm_dir_cpp(const char *path, const Image *const im,
        const Dcm_meta *const meta) {

        Image slice;

        // Initialize C intermediates
        init_im(&slice);

        // Initialize the metadata to defaults, if it is null 
        Dcm_meta meta_new;
        set_meta_defaults(meta, &meta_new);

        // Get the number of leading zeros for the file names
        const int num_slices = im->nz;
        const int num_zeros = static_cast<int>(ceil(log10(
                static_cast<double>(num_slices))));

        // Form the printf format string for file names
#define BUF_LEN 16
        char format[BUF_LEN];
        snprintf(format, BUF_LEN, "%%0%dd.%s", num_zeros, ext_dcm); 
#undef BUF_LEN

        // Resize the slice buffer
        slice.nx = im->nx; 
        slice.ny = im->ny;
        slice.nz = 1;
        slice.nc = im->nc;
        im_default_stride(&slice);
        if (im_resize(&slice)) {
                im_free(&slice);
                return SIFT3D_FAILURE;
        }

        // Copy the units to the slice
        memcpy(SIFT3D_IM_GET_UNITS(&slice), SIFT3D_IM_GET_UNITS(im), 
                IM_NDIMS * sizeof(double));

        // Get the maximum absolute value of the whole image volume
        const float max_val = im_max_abs(im);

        // Write each slice
        for (int i = 0; i < num_slices; i++) {

                // Form the slice file name
#define BUF_LEN 1024
                char buf[BUF_LEN];
                snprintf(buf, BUF_LEN, format, i);

                // Form the full file path
                std::string fullfile(path + sepStr + buf);

                // Copy the data to the slice
                int x, y, z, c;
                SIFT3D_IM_LOOP_START_C(&slice, x, y, z, c)
                        SIFT3D_IM_GET_VOX(&slice, x, y, z, c) =
                                SIFT3D_IM_GET_VOX(im, x, y, i, c);
                SIFT3D_IM_LOOP_END_C

                // Generate a new SOPInstanceUID
                dcmGenerateUniqueIdentifier(meta_new.instance_uid, 
                        SITE_INSTANCE_UID_ROOT); 

                // Set the instance number
                const unsigned int instance = static_cast<unsigned int>(i + 1);
                meta_new.instance_num = instance;

                // Write the slice to a file
                if (write_dcm(fullfile.c_str(), &slice, &meta_new, max_val)) {
                        im_free(&slice);
                        return SIFT3D_FAILURE;
                }
        }

        // Clean up
        im_free (&slice);

        return SIFT3D_SUCCESS;
}
Example #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;
} 
Example #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;
}