Пример #1
0
/* Set a Dcm_meta struct to default values. Generates new UIDs. */
static void default_Dcm_meta(Dcm_meta *const meta) {
        meta->patient_name = default_patient_name;
        meta->patient_id = default_patient_id;
        meta->series_descrip = default_series_descrip;
        dcmGenerateUniqueIdentifier(meta->study_uid, SITE_STUDY_UID_ROOT);
        dcmGenerateUniqueIdentifier(meta->series_uid, SITE_SERIES_UID_ROOT);
        dcmGenerateUniqueIdentifier(meta->instance_uid, SITE_INSTANCE_UID_ROOT); 
        meta->instance_num = default_instance_num;
}
Пример #2
0
void DicomUtils::AddDicomElements(DcmDataset*& dataset)
{
	//构建测试数据

	/*	添加患者信息	*/
	dataset->putAndInsertUint16(DCM_AccessionNumber,0);
	dataset->putAndInsertString(DCM_PatientName,"zssure",true);
	dataset->putAndInsertString(DCM_PatientID,"2234");
	dataset->putAndInsertString(DCM_PatientBirthDate,"20141221");
	dataset->putAndInsertString(DCM_PatientSex,"M");

	/*	添加Study信息	*/
	dataset->putAndInsertString(DCM_StudyDate,"20141221");
	dataset->putAndInsertString(DCM_StudyTime,"195411");
	char uid[100];
	dcmGenerateUniqueIdentifier(uid,SITE_STUDY_UID_ROOT);
	dataset->putAndInsertString(DCM_StudyInstanceUID,uid);
	dataset->putAndInsertString(DCM_StudyID,"1111");


	/*	添加Series信息	*/
	dataset->putAndInsertString(DCM_SeriesDate,"20141221");
	dataset->putAndInsertString(DCM_SeriesTime,"195411");
	memset(uid,0,sizeof(char)*100);
	dcmGenerateUniqueIdentifier(uid,SITE_SERIES_UID_ROOT);
	dataset->putAndInsertString(DCM_SeriesInstanceUID,uid);
	/*	添加Image信息	*/
	dataset->putAndInsertString(DCM_ImageType,"ORIGINAL\\PRIMARY\\AXIAL");
	dataset->putAndInsertString(DCM_ContentDate,"20141221");
	dataset->putAndInsertString(DCM_ContentTime,"200700");
	dataset->putAndInsertString(DCM_InstanceNumber,"1");
	dataset->putAndInsertString(DCM_SamplesPerPixel,"1");
	dataset->putAndInsertString(DCM_PhotometricInterpretation,"MONOCHROME2");
	dataset->putAndInsertString(DCM_PixelSpacing,"0.3\\0.3");
	dataset->putAndInsertString(DCM_BitsAllocated,"16");
	dataset->putAndInsertString(DCM_BitsStored,"16");
	dataset->putAndInsertString(DCM_HighBit,"15");
	dataset->putAndInsertString(DCM_WindowCenter,"600");
	dataset->putAndInsertString(DCM_WindowWidth,"800");
	dataset->putAndInsertString(DCM_RescaleIntercept,"0");
	dataset->putAndInsertString(DCM_RescaleSlope,"1");


}
Volume* VolumeBuilderFromCaptures::build()
{
    Q_ASSERT(m_parentStudy);
    Q_ASSERT(m_vtkImageAppend->GetNumberOfInputs());

    // Creem la nova sèrie
    Series *newSeries = new Series();

    // Omplim la informació de la sèrie a partir de la sèrie de referència

    // Assignem la modalitat segons el valor introduit. El valor per defecte és 'OT' (Other).
    newSeries->setModality(m_modality);
    newSeries->setSOPClassUID(QString(UID_SecondaryCaptureImageStorage));

    // Generem el SeriesInstanceUID a partir del generador de DCMTK. \TODO Utilitzar el nostre UID_ROOT?
    char seriesUid[100];
    dcmGenerateUniqueIdentifier(seriesUid, SITE_SERIES_UID_ROOT);
    newSeries->setInstanceUID(QString(seriesUid));
    // \TODO Quin criteri volem seguir per donar nous noms?
    newSeries->setSeriesNumber(QString("0000") + QString::number(m_parentStudy->getSeries().count()));
    newSeries->setDescription(this->getSeriesDescription());

    // Assignem la sèrie a l'estudi al qual partenyia l'inputVolume.
    newSeries->setParentStudy(m_parentStudy);
    m_parentStudy->addSeries(newSeries);

    // Obtenim el nou vtkImageData a partir de la sortida del vtkImageAppend.
    // Fem un flip horitzontal per tal utilitzar el mateix sistema de coordenades que DICOM.
    m_vtkImageAppend->Update();

    vtkSmartPointer<vtkImageData> newVtkData = vtkSmartPointer<vtkImageData>::New();
    newVtkData->ShallowCopy(m_vtkImageAppend->GetOutput());

    // Creem el nou volume
    Volume *newVolume = new Volume();
    newSeries->addVolume(newVolume);

    // Generem les noves imatges a partir del vtkData generat per vtkImageAppend
    int samplesPerPixel = newVtkData->GetNumberOfScalarComponents();
    int bitsAllocated;
    int bitsStored;
    int highBit;
    int pixelRepresentation;
    int rows;
    int columns;

    // \TODO Potser podriem ser mes precisos
    QString photometricInterpretation;
    if (samplesPerPixel == 1)
    {
        photometricInterpretation = QString("MONOCHROME2");
    }
    else if (samplesPerPixel == 3)
    {
        photometricInterpretation = QString("RGB");
    }

    int scalarType = newVtkData->GetScalarType();

    switch (scalarType)
    {
        //case VTK_CHAR:
        //break;
        case VTK_SIGNED_CHAR:
            bitsAllocated = 8;
            pixelRepresentation = 1;
            break;
        case VTK_UNSIGNED_CHAR:
            bitsAllocated = 8;
            pixelRepresentation = 0;
            break;
        case VTK_SHORT:
            bitsAllocated = 16;
            pixelRepresentation = 1;
            break;
        case VTK_UNSIGNED_SHORT:
            bitsAllocated = 16;
            pixelRepresentation = 0;
            break;
        case VTK_INT:
            bitsAllocated = 32;
            pixelRepresentation = 1;
            break;
        case VTK_UNSIGNED_INT:
            bitsAllocated = 32;
            pixelRepresentation = 0;
            break;
//        case VTK_FLOAT:
//            bitsAllocated = 32;
//            pixelRepresentation = 1; ?
//            break;
//        case VTK_DOUBLE:
//            bitsAllocated = 64;
//            pixelRepresentation = 1; ?
//            break;
        default:
            DEBUG_LOG(QString("Pixel Type no suportat: ") + newVtkData->GetScalarTypeAsString());

    }

    bitsStored = bitsAllocated;
    highBit = bitsStored - 1;

    int *dimensions = newVtkData->GetDimensions();
    double *spacing = newVtkData->GetSpacing();

    rows = dimensions[1];
    columns = dimensions[0];

    Image *currentImage;

    for (int i = 0; i < dimensions[2]; i++)
    {
        currentImage = new Image();

        // Generem el SOPInstanceUID a partir del generador de DCMTK. \TODO Utilitzar el nostre UID_ROOT?
        char instanceUid[100];
        dcmGenerateUniqueIdentifier(instanceUid, SITE_INSTANCE_UID_ROOT);
        currentImage->setSOPInstanceUID(QString(instanceUid));
        newSeries->addImage(currentImage);
        newVolume->addImage(currentImage);
        currentImage->setParentSeries(newSeries);
        currentImage->setOrderNumberInVolume(i);
        currentImage->setVolumeNumberInSeries(0);

        currentImage->setBitsAllocated(bitsAllocated);
        currentImage->setBitsStored(bitsStored);
        currentImage->setHighBit(highBit);
        currentImage->setColumns(columns);
        currentImage->setInstanceNumber(QString::number(i + 1));
        currentImage->setPhotometricInterpretation(photometricInterpretation);
        currentImage->setPixelRepresentation(pixelRepresentation);
        currentImage->setPixelSpacing(spacing[0], spacing[1]);
        currentImage->setRows(rows);
        currentImage->setSamplesPerPixel(samplesPerPixel);

    }

    // Es fa després d'haver inserit les imatges perquè el nou Volume activi el flag de dades carregades.
    newVolume->setData(newVtkData);

    newVolume->setNumberOfPhases(1);
    newVolume->setNumberOfSlicesPerPhase(newSeries->getImages().count());

    // Informació de DEBUG
    DEBUG_LOG(QString("\nNova sèrie generada:") +
     QString("\n  SeriesInstanceUID: ") + newSeries->getInstanceUID() +
     QString("\n  SeriesNumber: ") + newSeries->getSeriesNumber() +
     QString("\n  SeriesDescription: ") + newSeries->getDescription() +
     QString("\n  SOPClassUID: ") + newSeries->getSOPClassUID() +
     QString("\n  Modality: ") + newSeries->getModality() +
     QString("\n  SamplesPerPixel: ") + QString::number(samplesPerPixel) +
     QString("\n  PhotometricInterpretation: ") + photometricInterpretation +
     QString("\n  BitsAllocated: ") + QString::number(bitsAllocated) +
     QString("\n  BitsStored: ") + QString::number(bitsStored) +
     QString("\n  HighBit: ") + QString::number(highBit) +
     QString("\n  PixelRepresentation: ") + QString::number(pixelRepresentation) +
     QString("\n  PixelSpacing: ") + QString::number(spacing[0]) + QString(",") + QString::number(spacing[1]) +
     QString("\n  Num.Imatges: ") + QString::number(newSeries->getImages().count()));

    return newVolume;

}
Пример #4
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;
}
Пример #5
0
int gendicom(const char* file_name, const std::vector<float> &data,
             unsigned int rows, unsigned int cols)
{

char uid[100];
DcmFileFormat fileformat;
DcmDataset *dataset = fileformat.getDataset();
OFCondition result = EC_Normal;

if (result.good()) result = dataset->putAndInsertString(DCM_SOPClassUID, UID_SecondaryCaptureImageStorage);

//if (result.good()) result = dataset->putAndInsertString(DCM_MediaStorageSOPClassUID, UID_SecondaryCaptureImageStorage); //same as SOP
if (result.good()) result = dataset->putAndInsertString(DCM_SOPInstanceUID, dcmGenerateUniqueIdentifier(uid, SITE_INSTANCE_UID_ROOT));
//if (result.good()) result = dataset->putAndInsertString(DCM_MediaStorageSOPInstanceUID, dcmGenerateUniqueIdentifier(uid, SITE_INSTANCE_UID_ROOT));
if (result.good()) result = dataset->putAndInsertString(DCM_SeriesInstanceUID, dcmGenerateUniqueIdentifier(uid, SITE_INSTANCE_UID_ROOT));
if (result.good()) result = dataset->putAndInsertString(DCM_StudyInstanceUID, dcmGenerateUniqueIdentifier(uid, SITE_INSTANCE_UID_ROOT));
//if (result.good()) result = dataset->putAndInsertString(DCM_TransferSyntaxUID, UID_LittleEndianExplicitTransferSyntax);

//if (result.good()) result = dataset->putAndInsertUint16(DCM_FileMetaInformationVersion, 1);

if (result.good()) result = dataset->putAndInsertString(DCM_ImageType, "DERIVED");
if (result.good()) result = dataset->putAndInsertString(DCM_Modality, "MR");
if (result.good()) result = dataset->putAndInsertString(DCM_ConversionType, "WSD");
if (result.good()) result = dataset->putAndInsertString(DCM_DerivationDescription, "IRGN Processed MR Reconstruction");
if (result.good()) result = dataset->putAndInsertString(DCM_SecondaryCaptureDeviceManufacturer, "IMT TUGRAZ");
if (result.good()) result = dataset->putAndInsertString(DCM_SecondaryCaptureDeviceManufacturerModelName, "IMT Cuda Workstation");
if (result.good()) result = dataset->putAndInsertString(DCM_PatientName, "Doe^John");

// set instance creation date and time
OFString s;
if (result.good()) result = DcmDate::getCurrentDate(s);
if (result.good()) result = dataset->putAndInsertOFStringArray(DCM_InstanceCreationDate, s);
if (result.good()) result = DcmTime::getCurrentTime(s);
if (result.good()) result = dataset->putAndInsertOFStringArray(DCM_InstanceCreationTime, s);


//--- Write image-data ---
std::vector<Uint16> uint16_data;

float val=0;
float min_val;
float max_val = *std::max_element(data.begin(),data.end());
for(unsigned int i=0; i<data.size(); ++i)
{
  val = (data[i]/max_val)*65535;
  uint16_data.push_back(Uint16(val));
}

max_val = *std::max_element(uint16_data.begin(),uint16_data.end());
min_val = *std::min_element(uint16_data.begin(),uint16_data.end());
std::cout<<"\n max-val: "<<max_val;
std::cout<<"\n min-val: "<<min_val;

unsigned bits=16;
Uint16 bitsAllocated=((bits-1)/8+1)*8;
Uint16 bitsStored=bits;
Uint16 highBit=bits-1;
if (result.good()) result = dataset->putAndInsertUint16(DCM_BitsAllocated, bitsAllocated);
if (result.good()) result = dataset->putAndInsertUint16(DCM_BitsStored, bitsStored);
if (result.good()) result = dataset->putAndInsertUint16(DCM_HighBit, highBit);

if (result.good()) result = dataset->putAndInsertUint16(DCM_Rows, rows);
if (result.good()) result = dataset->putAndInsertUint16(DCM_Columns, cols);

if (result.good()) result = dataset->putAndInsertUint16(DCM_PixelRepresentation, 0);  // 1 signed, 0 unsigned
if (result.good()) result = dataset->putAndInsertOFStringArray(DCM_PhotometricInterpretation, "MONOCHROME2");
if (result.good()) result = dataset->putAndInsertUint16(DCM_SamplesPerPixel, 1);

if (result.good()) result = dataset->putAndInsertUint16(DCM_SmallestImagePixelValue, min_val);
if (result.good()) result = dataset->putAndInsertUint16(DCM_LargestImagePixelValue, max_val);

Uint8* pixelData = (Uint8*)&uint16_data[0];
Uint32 pixelLength;

pixelLength = uint16_data.size()*2;   //number of elements in vector * 2bytes (for Uint16)

dataset->putAndInsertUint8Array(DCM_PixelData, pixelData, pixelLength);
OFCondition status = fileformat.saveFile(file_name, EXS_LittleEndianExplicit);

if (result.bad())
  std::cerr << "Error: cannot write DICOM file (" << result.text() << ")" << std::endl;

if (status.bad())
  std::cerr << "Error: cannot write DICOM file (" << status.text() << ")" << std::endl;

return 0;

}