Example #1
0
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);
}
Example #2
0
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;
}
Example #3
0
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;
}
Example #5
0
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;
		}
	}
}
Example #6
0
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);
			}
		}
	}