/** Check whether given type 1 attribute is present and has a length > 0. * @param key - [in] The attribute tag check * @param targetDset - [out] targetDset * @param defaultValue - [in] value to be inserted if attribute is missing * (needs invent option for type 1 attributes enabled) * @return A string with an error message if attribute is not present * or has length of 0 */ OFString D2DCommon::checkAndInventType1Attrib(const DcmTagKey& key, DcmDataset* targetDset, const OFString& defaultValue) const { OFString err; OFBool exists = targetDset->tagExists(key); if (!exists) { OFString err = "Document2Dcm: Missing type 1 attribute: "; err += DcmTag(key).getTagName(); err += "\n"; return err; } DcmElement *elem; OFCondition cond = targetDset->findAndGetElement(key, elem); if (cond.bad() || !elem || (elem->getLength() == 0)) { if (!m_inventMissingType1Attribs) { err += "Document2Dcm: Empty value for type 1 attribute: "; err += DcmTag(key).getTagName(); err += "\n"; return err; } //holds element to insert in item DcmElement *elem = NULL; DcmTag tag(key); OFBool wasError = OFFalse; //if dicom element could be created, insert in to item and modify to value if (newDicomElement(elem, tag).good()) { if (targetDset->insert(elem, OFTrue).good()) { if (elem->putString(defaultValue.c_str()).good()) { if (m_debug) { OFString msg = "Document2Dcm: Inserting missing type 1 attribute "; msg += tag.getTagName(); msg += " with value "; msg += defaultValue; printMessage(m_logStream, msg); return err; } } else wasError = OFTrue; } else wasError = OFTrue; } else wasError = OFTrue; if (wasError) { err += "Unable to insert type 1 attribute "; err += tag.getTagName(); err += " with value "; err += defaultValue; err += "\n"; } } return err; }
// copy optional string value from dataset to directory record static void copyStringWithDefault(DcmItem& dataset, const DcmTagKey &key, DcmDirectoryRecord& record, const char *defaultValue, const OFBool printWarning) { OFCondition status; if (dataset.tagExistsWithValue(key)) { OFString stringValue; /* retrieve string value from source dataset and put it into the destination dataset */ status = dataset.findAndGetOFStringArray(key, stringValue); if (status.good()) status = record.putAndInsertString(key, stringValue.c_str()); } else { if (printWarning && (defaultValue != NULL)) { /* create warning message */ LOG(WARNING) << "DICOMDIR: " << DcmTag(key).getTagName() << " " << key << " missing, using alternative: " << defaultValue; } /* put default value */ status = record.putAndInsertString(key, defaultValue); } }
// print an error message to the console (stderr) that something went wrong with an attribute static void printAttributeErrorMessage(const DcmTagKey &key, const OFCondition &error, const char *operation) { if (error.bad()) { OFString str; if (operation != NULL) { str = "cannot "; str += operation; str += " "; } LOG(ERROR) << error.text() << ": " << str << DcmTag(key).getTagName() << " " << key; } }
/** Inserts an empty element with the given tag into a dataset * @param key - [in] The attribute tag to check * @param targetDset - [out] targetDset * @return A string with an error message if attribute is not present * nor gets inserted automatically (see m_inventMissingType2Attribs) */ OFString D2DCommon::checkAndInventType2Attrib(const DcmTagKey& key, DcmDataset* targetDset) const { OFString err; OFBool exists = targetDset->tagExists(key); if (!exists) { if (m_inventMissingType2Attribs) { DcmTag tag(key); if (m_debug) printMessage(m_logStream, "Document2Dcm: Inserting missing type 2 attribute: ", tag.getTagName()); targetDset->insertEmptyElement(tag); } else { err = "Document2Dcm: Missing type 2 attribute: "; err += DcmTag(key).getTagName(); err += "\n"; return err; } } return err; }
/** Reads pixel data and corresponding attributes like rows etc. from image * file and inserts them into dataset. * @param dset - [out] The dataset to export the pixel data attributes to * @param outputTS - [out] The proposed transfex syntax of the dataset * @return EC_Normal, if successful, error otherwise */ OFCondition I2DImgSource::readAndInsertSpecificTags( DcmDataset* dset, E_TransferSyntax& outputTS) { Uint16 samplesPerPixel, rows, cols, bitsAlloc, bitsStored, highBit, pixelRepr, planConf; Uint16 pixAspectH = 1; Uint16 pixAspectV = 1; OFString photoMetrInt; outputTS = EXS_Unknown; char* pixData = NULL; Uint32 length; OFCondition cond = readPixelData(rows, cols, samplesPerPixel, photoMetrInt, bitsAlloc, bitsStored, highBit, pixelRepr, planConf, pixAspectH, pixAspectV, pixData, length, outputTS); if (cond.bad()) return cond; if (m_debug) printMessage(m_logStream, "Document2Dcm: Store imported pixel data to DICOM file"); cond = dset->putAndInsertUint16(DCM_SamplesPerPixel, samplesPerPixel); if (cond.bad()) return cond; cond = dset->putAndInsertOFStringArray(DCM_PhotometricInterpretation, photoMetrInt); if (cond.bad()) return cond; cond = dset->putAndInsertOFStringArray(DCM_ConversionType, "WSD"); if (cond.bad()) return cond; /* cond = dset->putAndInsertOFStringArray(DCM_ImagerPixelSpacing, "1.000000\\1.000000"); if (cond.bad()) return cond; cond = dset->putAndInsertOFStringArray(DCM_PixelSpacing, "1.000000\\1.000000"); if (cond.bad()) return cond; */ cond = dset->putAndInsertOFStringArray(DCM_ImagePositionPatient, "0.000000\\0.000000\\0.000000"); if (cond.bad()) return cond; cond = dset->putAndInsertOFStringArray(DCM_ImageOrientationPatient, "1.000000\\0.000000\\0.000000\\0.000000\\1.000000\\0.000000"); if (cond.bad()) return cond; // Should only be written if Samples per Pixel > 1 if (samplesPerPixel > 1) { cond = dset->putAndInsertUint16(DCM_PlanarConfiguration, planConf); if (cond.bad()) return cond; } cond = dset->putAndInsertUint16(DCM_Rows, rows); if (cond.bad()) return cond; cond = dset->putAndInsertUint16(DCM_Columns, cols); if (cond.bad()) return cond; cond = dset->putAndInsertUint16(DCM_BitsAllocated, bitsAlloc); if (cond.bad()) return cond; cond = dset->putAndInsertUint16(DCM_BitsStored, bitsStored); if (cond.bad()) return cond; cond = dset->putAndInsertUint16(DCM_HighBit, highBit); if (cond.bad()) return cond; cond = dset->putAndInsertUint16(DCM_PixelRepresentation, pixelRepr); if (cond.bad()) return cond; if (Recompress()) { // create initial pixel sequence DcmElement* element = newDicomElement(DcmTag(DCM_PixelData, EVR_OW)); element->putUint8Array((const Uint8*)pixData, length); cond = dset->insert(element); if (cond.bad()) { delete element; return cond; } //lo pasamos a jpeg lossless // create representation parameters for lossy and lossless OFCmdUnsignedInt opt_selection_value = 6; //este numero implica cierta perdida... si fuera 0 seria lossless real OFCmdUnsignedInt opt_point_transform = 3; E_TransferSyntax opt_oxfer; GNC::GCS::Permisos::EstadoPermiso codificacion = GNC::GCS::IControladorPermisos::Instance()->Get("core.importacion", "codec"); switch (codificacion.ObtenerValor<int>()) { case 0: { //baseline opt_oxfer = EXS_JPEGProcess1; DJ_RPLossy rp_lossy((int)90); const DcmRepresentationParameter *rp = &rp_lossy; dset->chooseRepresentation(opt_oxfer, rp); } break; case 1: { //progresivo opt_oxfer = EXS_JPEGProcess10_12; DJ_RPLossy rp_lossy((int)90); const DcmRepresentationParameter *rp = &rp_lossy; dset->chooseRepresentation(opt_oxfer, rp); } break; case 2: default: { //lossless GNC::GCS::Permisos::EstadoPermiso estado = GNC::GCS::IControladorPermisos::Instance()->Get("core.importacion", "quality"); if (estado) { opt_point_transform = std::min<int>(estado.ObtenerValor<int>(), 14); opt_point_transform = std::max<int>(estado.ObtenerValor<int>(), 0); } opt_oxfer = EXS_JPEGProcess14SV1; DJ_RPLossless rp_lossless((int)opt_selection_value, (int)opt_point_transform); const DcmRepresentationParameter *rp = &rp_lossless; dset->chooseRepresentation(opt_oxfer, rp); } break; } if(!dset->canWriteXfer(opt_oxfer)) return OFCondition(EC_UnsupportedEncoding); // force meta-header to refresh SOP Class/Instance UIDs. delete dset->remove(DCM_MediaStorageSOPClassUID); delete dset->remove(DCM_MediaStorageSOPInstanceUID); outputTS = opt_oxfer; return cond; } else { if (IsCompressed()) { DcmPixelSequence *pixelSequence = NULL; if (m_debug) printMessage(m_logStream, "Document2Dcm: Store imported pixel data to DICOM file"); // create initial pixel sequence pixelSequence = new DcmPixelSequence(DcmTag(DCM_PixelData, EVR_OB)); if (pixelSequence == NULL) return EC_MemoryExhausted; // insert empty offset table into sequence DcmPixelItem *offsetTable = new DcmPixelItem(DcmTag(DCM_Item, EVR_OB)); if (offsetTable == NULL) { delete pixelSequence; pixelSequence = NULL; return EC_MemoryExhausted; } cond = pixelSequence->insert(offsetTable); if (cond.bad()) { delete offsetTable; offsetTable = NULL; delete pixelSequence; pixelSequence = NULL; return cond; } // insert frame into pixel sequence DcmOffsetList dummyList; cond = pixelSequence->storeCompressedFrame(dummyList, (Uint8*) pixData, length, 0); // storeCompressedFrame(..) does a deep copy, so the pixdata memory can be freed now delete[] pixData; if (cond.bad()) { delete pixelSequence; return cond; } cond = dset->insert(pixelSequence); if (cond.bad()) delete pixelSequence; if (m_debug) printMessage(m_logStream, "Document2Dcm: Inserting Image Pixel module information"); return dset->putAndInsertUint16(DCM_PixelRepresentation, pixelRepr); } else { //little endian to little endian... // create initial pixel sequence DcmElement* element = newDicomElement(DcmTag(DCM_PixelData, EVR_OW)); element->putUint8Array((const Uint8*)pixData, length); cond = dset->insert(element); if (cond.bad()) { delete element; return cond; } outputTS = EXS_LittleEndianExplicit; return cond; } } }
int ctkDICOMDatasetTest1( int argc, char * argv [] ) { Q_UNUSED(argc); Q_UNUSED(argv); ctkDICOMDataset dataset; dataset.InitializeFromDataset(0); dataset.InitializeFromFile(QString()); try { dataset.Serialize(); } catch(...) { std::cout << "ctkDICOMDataset::Serialize() throws exceptions" << std::endl; //return EXIT_FAILURE; } try { dataset.Deserialize(); } catch(...) { std::cout << "ctkDICOMDataset::Deserialize() throws exceptions" << std::endl; //return EXIT_FAILURE; } dataset.MarkForInitialization(); try { dataset.EnsureDcmDataSetIsInitialized(); } catch(...) { std::cout << "ctkDICOMDataset::EnsureDcmDataSetIsInitialized() throws" << " exceptions" << std::endl; //return EXIT_FAILURE; } // deactivating the lower part since it (correctly) causes // execptions since it calls methods on an uninitialized object return EXIT_SUCCESS; dataset.CopyElement(0, DcmTagKey(), 0); QString decode = dataset.Decode(DcmTag(),OFString()); if (!decode.isEmpty()) { std::cerr << "ctkDICOMDataset::Decode() failed: " << qPrintable(decode) << std::endl; return EXIT_FAILURE; } OFString encode = dataset.Encode(DcmTag(), decode); DcmElement* element = 0; OFCondition condition = dataset.findAndGetElement(DcmTag(), element); if (ctkDICOMDataset::CheckCondition(condition)) { std::cerr << "ctkDICOMDataset::findAndGetElement() failed" << std::endl; return EXIT_FAILURE; } OFString string; condition = dataset.findAndGetOFString(DcmTag(), string); if (ctkDICOMDataset::CheckCondition(condition)) { std::cerr << "ctkDICOMDataset::findAndGetOFString() failed" << std::endl; return EXIT_FAILURE; } try { QString string = dataset.GetAllElementValuesAsString(DcmTag()); QString string2 = dataset.GetElementAsString(DcmTag()); QStringList list = dataset.GetElementAsStringList(DcmTag()); ctkDICOMPersonName name = dataset.GetElementAsPersonName(DcmTag()); ctkDICOMPersonNameList nameList = dataset.GetElementAsPersonNameList(DcmTag()); QDate date = dataset.GetElementAsDate(DcmTag()); QTime time = dataset.GetElementAsTime(DcmTag()); double doubleValue = dataset.GetElementAsDouble(DcmTag()); int integerValue = dataset.GetElementAsInteger(DcmTag()); int shortValue = dataset.GetElementAsSignedShort(DcmTag()); int ushortValue = dataset.GetElementAsUnsignedShort(DcmTag()); QDateTime dateTime = dataset.GetElementAsDateTime(DcmTag()); Q_UNUSED(string); Q_UNUSED(string2); Q_UNUSED(list); Q_UNUSED(name); Q_UNUSED(nameList); Q_UNUSED(date); Q_UNUSED(time); Q_UNUSED(doubleValue); Q_UNUSED(integerValue); Q_UNUSED(shortValue); Q_UNUSED(ushortValue); Q_UNUSED(dateTime); dataset.SetElementAsString( DcmTag(), QString()); dataset.SetElementAsStringList( DcmTag(), QStringList() ); dataset.SetElementAsPersonName( DcmTag(), ctkDICOMPersonName()); dataset.SetElementAsPersonNameList( DcmTag(), ctkDICOMPersonNameList() ); dataset.SetElementAsDate( DcmTag(), QDate() ); dataset.SetElementAsTime( DcmTag(), QTime() ); dataset.SetElementAsDateTime( DcmTag(), QDateTime() ); dataset.SetElementAsInteger( DcmTag(), 0 ); // type IS dataset.SetElementAsSignedShort( DcmTag(), 0 ); // type SS dataset.SetElementAsUnsignedShort( DcmTag(), 0 ); // type US } catch(...) { std::cout << "ctkDICOMDataset::GetElementValueAsXXX() throws exceptions" << std::endl; //return EXIT_FAILURE; } ctkDICOMDataset::TranslateDefinedTermPatientPosition(QString()); ctkDICOMDataset::TranslateDefinedTermModality(QString()); ctkDICOMDataset::TagKey(DcmTag()); ctkDICOMDataset::TagDescription(DcmTag()); ctkDICOMDataset::TagVR(DcmTag()); return EXIT_SUCCESS; }