bool DCM_COMMAND_CLASS::encode(DATA_TF_CLASS& dataTransfer) // DESCRIPTION : encode DICOM command to dataTransfer stream. // PRECONDITIONS : // POSTCONDITIONS : // EXCEPTIONS : // NOTES : //<<=========================================================================== { // check if we need to add the group length attributes if (defineGroupLengthsM) { // add group length(s) - attributes sorted here addGroupLengths(); // update group length(s) setGroupLengths(dataTransfer.getTsCode()); } else { // sort the DICOM command attributes into ascending order SortAttributes(); } // set the transfer VR - used by the logger if (dataTransfer.isExplicitVR()) { // set to explicit setTransferVR(TRANSFER_ATTR_VR_EXPLICIT); } else { // set to implicit setTransferVR(TRANSFER_ATTR_VR_IMPLICIT); } // encode the command attributes return DCM_ATTRIBUTE_GROUP_CLASS::encode(dataTransfer); }
bool OD_VALUE_STREAM_CLASS::StreamPatternTo(DATA_TF_CLASS& data_transfer) // DESCRIPTION : Stream a OF pattern to the data_transfer. // PRECONDITIONS : // POSTCONDITIONS : // EXCEPTIONS : // NOTES : //<<=========================================================================== { float value; UINT row_start = start_valueM; UINT row_inc = rows_incrementM; UINT col_inc = columns_incrementM; UINT rows_same = rows_sameM; UINT columns_same = columns_sameM; bool byte_swap = IsByteSwapRequired(); const UINT nr_of_OT_in_OF = 4; // generate a simple test pattern if ((rowsM * columnsM * nr_of_OT_in_OF) != lengthM) { if (loggerM_ptr) { loggerM_ptr->text(LOG_ERROR, 1, "OD data generation failure - rows (%d) * columns (%d) not equal length (%d)", rowsM, columnsM, lengthM); } return false; } UINT32 length = columnsM; // columns = row length (NP) float *data_ptr = new float [length]; if (rows_same == 0) { rows_same++; } if (columns_same == 0) { columns_same++; } for (UINT rows = 0; rows < rowsM; rows++) { value = (float)row_start; for (UINT columns = 0; columns < columnsM; columns++) { data_ptr[columns] = value; if ((columns + 1) % columns_same == 0 ) { if ((value == 0xFFFF) && (col_inc != 0)) { value = 0; } else { value += (float)col_inc; } } } // swap the data bytes if required if (byte_swap) { SwapBytes((BYTE*) data_ptr, length * 4); } // write data into buffer data_transfer.writeBinary((BYTE*) data_ptr, length * 4); if ((rows + 1) % rows_same == 0) { if ((row_start == 0xFFFF) && (row_inc !=0)) { row_start = 0; } else { row_start += row_inc; } } } // cleanup delete data_ptr; // return result return true; }
bool DCM_DIR_DATASET_CLASS::decodeToFirstRecord(DATA_TF_CLASS &dataTransfer) // DESCRIPTION : Decode the DICOM DIR up to the beginning of the first // : Directory Record. // PRECONDITIONS : // POSTCONDITIONS : // EXCEPTIONS : // NOTES : //<<=========================================================================== { // initialize the Private Attribute Handler initializePrivateAttributeHandler(); bool lookingForDirectoryRecordSequence = true; // decode all attributes while ((dataTransfer.isData()) && (lookingForDirectoryRecordSequence)) { DCM_ATTRIBUTE_CLASS *attribute_ptr = new DCM_ATTRIBUTE_CLASS(); if (attribute_ptr == NULL) return false; // cascade the logger attribute_ptr->setLogger(loggerM_ptr); // cascade the parent attribute_ptr->setParent(this); // cascade the private attribute handler attribute_ptr->setPAH(pahM_ptr); UINT16 lastGroup = GROUP_FOUR; UINT16 lastElement = DIRECTORY_RECORD_SEQUENCE; // decode attributes one at a time UINT32 attributeLength; if (attribute_ptr->decode(dataTransfer, lastGroup, lastElement, &attributeLength)) { // add attribute to object addAttribute(attribute_ptr); } else { // check if we have reached the Directory Record Sequence if (attribute_ptr->GetGroup() < lastGroup) { // clean up delete attribute_ptr; // return error when reason for stopping is not the last group reached return false; } // decode group UINT16 group; dataTransfer >> group; // decode element UINT16 element; dataTransfer >> element;; // check that we have reached the Directory Record Sequence if ((group != GROUP_FOUR) || (element != DIRECTORY_RECORD_SEQUENCE)) { // clean up delete attribute_ptr; // rewound in decode() method to reread this tag but something has gone wrong return false; } // check on explicit VR ATTR_VR_ENUM vr = ATTR_VR_DOESNOTEXIST; if (dataTransfer.isExplicitVR()) { BYTE sl[2]; UINT16 length16; // we get the VR given dataTransfer >> sl[0]; dataTransfer >> sl[1]; UINT16 vr16 = (((UINT16) sl[0]) << 8) + ((UINT16) sl[1]); vr = dataTransfer.vr16ToVr(vr16); // set transfer vr attribute_ptr->setTransferVR(TRANSFER_ATTR_VR_EXPLICIT); // should be a sequence if (vr != ATTR_VR_SQ) { // sequence attribute expected if (loggerM_ptr) { loggerM_ptr->text(LOG_ERROR, 1, "Attribute (%04X,%04X) - should be VR of SQ but %02X%02X found.", group, element, sl[0], sl[1]); } return false; } // special SQ encoding // - decode 16 bit padding dataTransfer >> length16; } else { // set transfer vr attribute_ptr->setTransferVR(TRANSFER_ATTR_VR_IMPLICIT); // implicit VR vr = ATTR_VR_SQ; } // decode 32 bit length UINT32 length32; dataTransfer >> length32; // save the record sequence (as an empty sequence in the dataset attribute_ptr->SetVR(vr); addAttribute(attribute_ptr); // save the sequence value decoder for the calls to get next items sqValueM_ptr = new DCM_VALUE_SQ_CLASS(length32); // cascade the logger sqValueM_ptr->setLogger(loggerM_ptr); // cascade the private attribute handler sqValueM_ptr->setPAH(getPAH()); // found the directory record sequence lookingForDirectoryRecordSequence = false; }
bool OW_VALUE_STREAM_CLASS::StreamPatternTo(DATA_TF_CLASS& data_transfer) // DESCRIPTION : Stream a OW pattern to the data_transfer. // PRECONDITIONS : // POSTCONDITIONS : // EXCEPTIONS : // NOTES : //<<=========================================================================== { UINT row_start = start_valueM; UINT row_inc = rows_incrementM; UINT col_inc = columns_incrementM; UINT rows_same = rows_sameM; UINT columns_same = columns_sameM; bool byte_swap = IsByteSwapRequired(); if (rows_same == 0) { rows_same++; } if (columns_same == 0) { columns_same++; } // get hold of the current bits allocated if (bits_allocatedM == 16) { UINT16 value; // generate a simple test pattern const UINT nr_of_OT_in_OW = 2; if ((rowsM * columnsM * nr_of_OT_in_OW) != lengthM) { if (loggerM_ptr) { loggerM_ptr->text(LOG_ERROR, 1, "OW data generation failure - rows (%d) * columns (%d) not equal length (%d)", rowsM, columnsM, lengthM); } return false; } UINT32 length = columnsM; // columns = row length (NP) UINT16 *data_ptr = new UINT16 [length]; for (UINT rows = 0; rows < rowsM; rows++) { value = (UINT16)row_start; for (UINT columns = 0; columns < columnsM; columns++) { data_ptr[columns] = value; if ((columns + 1) % columns_same == 0) { if ((value == 0xFFFF) && (col_inc != 0)) { value = 0; } else { value = (UINT16)(value + col_inc); } } } // swap the data bytes if required if (byte_swap) { SwapBytes((BYTE*) data_ptr, length * 2); } // write data into buffer data_transfer.writeBinary((BYTE*) data_ptr, length * 2); if ((rows + 1) % rows_same == 0) { if ((row_start == 0xFFFF) && (row_inc !=0)) { row_start = 0; } else { row_start += row_inc; } } } // cleanup delete data_ptr; } else if (bits_allocatedM == 8) { BYTE value; // generate a simple test pattern - values have previously been range checked if ((rowsM * columnsM) != lengthM) { if (loggerM_ptr) { loggerM_ptr->text(LOG_ERROR, 1, "OW data generation failure - rows (%d) * columns (%d) not equal length (%d)", rowsM, columnsM, lengthM); } return false; } UINT32 length = columnsM; // columns = row length (NP) BYTE *data_ptr = new BYTE [length]; for (UINT rows = 0; rows < rowsM; rows++) { value = (BYTE)row_start; for (UINT columns = 0; columns < columnsM; columns++) { data_ptr[columns] = value; if ((columns + 1) % columns_same == 0) { if ((value == 0xFF) && (col_inc != 0)) { value = 0; } else { value = (BYTE)(value + col_inc); } } } // swap the data bytes if required if (byte_swap) { SwapBytes(data_ptr, length); } // write data into buffer data_transfer.writeBinary(data_ptr, length); if ((rows + 1) % rows_same == 0) { if ((row_start == 0xFFFF) && (row_inc !=0)) { row_start = 0; } else { row_start += row_inc; } } } // check for odd length - last fragment! if (lengthM & 0x1) { data_ptr[0] = 0x00; // write data into buffer data_transfer.writeBinary(data_ptr, 1); } // cleanup delete data_ptr; } // return result return true; }
void DCM_ATTRIBUTE_GROUP_CLASS::computeItemOffsets(DATA_TF_CLASS& dataTransfer) // DESCRIPTION : Compute any item offsets - for DICOMDIR. // PRECONDITIONS : // POSTCONDITIONS : // EXCEPTIONS : // NOTES : //<<=========================================================================== { // loop computing the offsets for each attribute for (int i = 0; i < GetNrAttributes(); i++) { // get the Attribute Data DCM_ATTRIBUTE_CLASS *attribute_ptr = GetAttribute(i); ATTR_VR_ENUM vr = attribute_ptr->GetVR(); ATTR_TYPE_ENUM type = attribute_ptr->GetType(); UINT32 length = attribute_ptr->getPaddedLength(); if ((vr != ATTR_VR_SQ) && (length == 0) && ((type == ATTR_TYPE_1C) || (type == ATTR_TYPE_2C))) { // do not encode zero length Type1C, Type2C continue; } // count length of the group & element = 4 bytes offsetM += 4; // count the [VR] length if (dataTransfer.getTsCode() & TS_IMPLICIT_VR) { // implicit VR - 32 bit length used = 4 bytes offsetM += 4; } else { // explicit VR = 2 bytes offsetM += 2; // check for special OB, OF, OW, OL, OD, SQ, UN, UR, UC& UT encoding if ((vr == ATTR_VR_OB) || (vr == ATTR_VR_OF) || (vr == ATTR_VR_OW) || (vr == ATTR_VR_OL) || (vr == ATTR_VR_OD) || (vr == ATTR_VR_SQ) || (vr == ATTR_VR_UN) || (vr == ATTR_VR_UR) || (vr == ATTR_VR_UC) || (vr == ATTR_VR_UT)) { // 16 bit padding & 32 bit length used = 6 bytes offsetM += 6; } else { // 16 bit length used = 4 bytes offsetM += 2; } } // handle the SQs separately if (vr == ATTR_VR_SQ) { // only interested if one SQ value available if (attribute_ptr->GetNrValues() == 1) { // get SQ value DCM_VALUE_SQ_CLASS *sqValue_ptr = static_cast<DCM_VALUE_SQ_CLASS*>(attribute_ptr->GetValue(0)); // run through items in sequence sqValue_ptr->computeItemOffsets(dataTransfer, &offsetM); } } else { // count standard attribute length offsetM += length; } } }
bool DCM_ITEM_CLASS::decode(DATA_TF_CLASS &dataTransfer, UINT16 lastGroup, UINT16 lastElement, UINT32 *length_ptr) // DESCRIPTION : decode the item attributes. // PRECONDITIONS : // POSTCONDITIONS : // EXCEPTIONS : // NOTES : //<<=========================================================================== { //set offset for this item; //will be used for media purposes offsetM = dataTransfer.getLength() - dataTransfer.getRemainingLength(); // decode item introducer dataTransfer >> introducerGroupM; if (length_ptr) *length_ptr += sizeof(introducerGroupM); dataTransfer >> introducerElementM; if (length_ptr) *length_ptr += sizeof(introducerElementM); // check if we have reached the sequence delimiter if (introducerElementM == SQ_DELIMITER) { // rewind the dataTransfer by the length of data read dataTransfer.rewind(sizeof(introducerGroupM) + sizeof(introducerElementM)); return false; } dataTransfer >> introducerLengthM; if (length_ptr) *length_ptr += sizeof(introducerLengthM); // check if we have reached the dataset trailing padding if ((introducerGroupM == DATASET_TRAILING_PADDING_GROUP) && (introducerElementM == DATASET_TRAILING_PADDING_ELEMENT)) { if (loggerM_ptr) { loggerM_ptr->text(LOG_DEBUG, 1, "Decode - Dataset Trailing Padding (%04X,%04X), length is %08X", introducerGroupM, introducerElementM, introducerLengthM); } // rewind the dataTransfer by the length of data read dataTransfer.rewind(sizeof(introducerGroupM) + sizeof(introducerElementM) + sizeof(introducerLengthM)); // just return - don't do anything with dataset trailing padding return false; } if (loggerM_ptr) { loggerM_ptr->text(LOG_DEBUG, 1, "Decode - Item Introducer (%04X,%04X), length is %08X", introducerGroupM, introducerElementM, introducerLengthM); } if (introducerGroupM != ITEM_GROUP) { if (loggerM_ptr) { loggerM_ptr->text(LOG_ERROR, 1, "Item Introducer Group. Should be: %04X, is: %04X", ITEM_GROUP, introducerGroupM); } } if (introducerElementM != ITEM_ELEMENT) { if (loggerM_ptr) { loggerM_ptr->text(LOG_ERROR, 1, "Item Introducer Element. Should be: %04X, is: %04X", ITEM_ELEMENT, introducerElementM); } } // set up the defined length field definedLengthM = (introducerLengthM == UNDEFINED_LENGTH) ? false : true; lengthM = introducerLengthM; UINT32 itemLength = introducerLengthM; // push a new recognition code table for private attribute handling in the item if (pahM_ptr) { pahM_ptr->pushRecognitionCodeTable(); } // decode the item attributes bool result = DCM_ATTRIBUTE_GROUP_CLASS::decode(dataTransfer, lastGroup, lastElement, &itemLength); // update the message length if (length_ptr) *length_ptr += itemLength; // now pop the new recognition code table if (pahM_ptr) { pahM_ptr->popRecognitionCodeTable(); } // check if item should be delimited if ((result) && (!definedLengthM)) { // decode the delimiter dataTransfer >> delimiterGroupM; if (length_ptr) *length_ptr += sizeof(delimiterGroupM); dataTransfer >> delimiterElementM; if (length_ptr) *length_ptr += sizeof(delimiterElementM); dataTransfer >> delimiterLengthM; if (length_ptr) *length_ptr += sizeof(delimiterLengthM); if (loggerM_ptr) { loggerM_ptr->text(LOG_DEBUG, 1, "Decode - Item Delimiter (%04X,%04X), length is %08X", delimiterGroupM, delimiterElementM, delimiterLengthM); } if (delimiterGroupM != ITEM_GROUP) { if (loggerM_ptr) { loggerM_ptr->text(LOG_ERROR, 1, "Item Delimiter Group. Should be: %04X, is: %04X", ITEM_GROUP, delimiterGroupM); } } if (delimiterElementM != ITEM_DELIMITER) { if (loggerM_ptr) { loggerM_ptr->text(LOG_ERROR, 1, "Item Delimiter Element. Should be: %04X, is: %04X", ITEM_DELIMITER, delimiterElementM); } } if (delimiterLengthM != 0) { if (loggerM_ptr) { loggerM_ptr->text(LOG_ERROR, 1, "Item Delimiter Length. Should be: %08X, is: %08X", 0, delimiterLengthM); } } }