/* ----------------------------- MNI Header ----------------------------------- @NAME : acr_peek_at_next_element_id @INPUT : afp - Acr_File pointer from which to read @OUTPUT : group_id element_id @RETURNS : VIO_Status @DESCRIPTION: Peeks ahead to get the group and element ids of the next element. The file position is restored. If a read error occurs, then group_id and element_id are set to INT_MIN and the status is returned. @METHOD : @GLOBALS : @CALLS : @CREATED : February 5, 1997 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ Acr_Status acr_peek_at_next_element_id(Acr_File *afp, int *group_id, int *element_id) { long buflen; unsigned char buffer[2*ACR_SIZEOF_SHORT]; Acr_Short svalue; Acr_Status status, status2; Acr_byte_order byte_order; /* Set default values */ status = ACR_OK; *group_id = INT_MIN; *element_id = INT_MIN; /* Read in the values */ status = acr_read_buffer(afp, buffer, SIZEOF_ARRAY(buffer), &buflen); /* Put them back */ status2 = acr_unget_buffer(afp, buffer, buflen); if (status == ACR_OK) status = status2; /* Check for input error */ if (status != ACR_OK) return status; /* Get the id's */ byte_order = acr_get_byte_order(afp); acr_get_short(byte_order, 1, &buffer[0], &svalue); *group_id = (int)svalue; acr_get_short(byte_order, 1, &buffer[ACR_SIZEOF_SHORT], &svalue); *element_id = (int)svalue; return status; }
/* ----------------------------- MNI Header ----------------------------------- @NAME : acr_read_one_element @INPUT : afp - Acr_File pointer from which to read @OUTPUT : group_id - ACR-NEMA group id element_id - ACR-NEMA element id data_length - length of data to follow data_pointer - pointer to data. Space is allocated by this routine. One additional byte is allocated and set to zero so that the data can be treated as a string. @RETURNS : Status. @DESCRIPTION: Routine to read in one ACR-NEMA element. @METHOD : @GLOBALS : @CALLS : @CREATED : November 10, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ Acr_Status acr_read_one_element(Acr_File *afp, int *group_id, int *element_id, long *data_length, char **data_pointer) { int ch, i, buflen; unsigned char buffer[2*ACR_SIZEOF_SHORT+ACR_SIZEOF_LONG]; unsigned short grpid, elid; size_t size_allocated; buflen = sizeof(buffer)/sizeof(buffer[0]); /* Read in group id, element id and length of data */ for (i=0; i < buflen; i++) { ch = acr_getc(afp); if (ch == EOF) { if (i == 0) return ACR_END_OF_INPUT; else return ACR_PROTOCOL_ERROR; } buffer[i] = ch; } acr_get_short(1, &buffer[0], &grpid); *group_id = grpid; acr_get_short(1, &buffer[2], &elid); *element_id = elid; acr_get_long(1, &buffer[4], data_length); /* Allocate space for the data and null-terminate it */ size_allocated = *data_length + 1; *data_pointer = MALLOC(size_allocated); if (*data_pointer == NULL) { *data_length = 0; size_allocated = *data_length + 1; *data_pointer = MALLOC(size_allocated); } (*data_pointer)[*data_length] = '\0'; /* Read in the data */ for (i=0; i < *data_length; i++) { ch = acr_getc(afp); if (ch == EOF) { FREE(*data_pointer); return ACR_PROTOCOL_ERROR; } (*data_pointer)[i] = ch; } return ACR_OK; }
/* ARGSUSED */ static double get_short(Acr_VR_Entry *vr_entry, Acr_byte_order byte_order, char *data, long data_length) { Acr_Short value; if (data_length == ACR_SIZEOF_SHORT) { acr_get_short(byte_order, 1, data, &value); return (double) value; } else { return 0.0; } }
/* ----------------------------- MNI Header ----------------------------------- @NAME : acr_test_byte_order @INPUT : afp @OUTPUT : (none) @RETURNS : status. @DESCRIPTION: Tests input for byte ordering to use. The test is done by looking at the length of the first element. First a test is done for implicit VR, assuming that the length of the first element is less than 64K and greater than zero, and we try the two possible byte orders. If the VR encoding is explicit, then we have two shortwords (2-bytes), both of which are non-zero and the longword (4 bytes) will be greater than 64K. In this case, we test the 2-byte length looking for a length that is less than 256 bytes. If that fails, than we revert to the original byte order. @METHOD : @GLOBALS : @CALLS : @CREATED : November 10, 1993 (Peter Neelin) @MODIFIED : January 29, 1997 (P.N.) ---------------------------------------------------------------------------- */ Acr_Status acr_test_byte_order(Acr_File *afp) { long buflen; unsigned char buffer[2*ACR_SIZEOF_SHORT+ACR_SIZEOF_LONG]; Acr_Long data_length; Acr_Short data_length2; Acr_Status status; Acr_byte_order byte_order, old_byte_order; #define ACR_TEST_MAX USHRT_MAX #define ACR_TEST_MAX2 UCHAR_MAX /* Save old byte ordering */ old_byte_order = acr_get_byte_order(afp); /* Read in group id, element id and length of data */ status = acr_read_buffer(afp, buffer, SIZEOF_ARRAY(buffer), &buflen); if (status != ACR_OK) return status; /* Put the characters back */ status = acr_unget_buffer(afp, buffer, buflen); if (status != ACR_OK) return status; /* Test data length (the first element should be a group length). Try big-endian ordering first. */ byte_order = ACR_BIG_ENDIAN; acr_set_byte_order(afp, byte_order); acr_get_long(byte_order, 1, &buffer[2*ACR_SIZEOF_SHORT], &data_length); /* If that doesn't work, set it to little-endian ordering. */ if (data_length >= ACR_TEST_MAX) { byte_order = ACR_LITTLE_ENDIAN; acr_set_byte_order(afp, byte_order); acr_get_long(byte_order, 1, &buffer[2*ACR_SIZEOF_SHORT], &data_length); } /* If one of them worked, then it means that we have implicit VR encoding since we didn't look for a VR field */ if (data_length < ACR_TEST_MAX) { acr_set_vr_encoding(afp, ACR_IMPLICIT_VR); } /* Otherwise we probably have explicit vr encoding. */ else { acr_set_vr_encoding(afp, ACR_EXPLICIT_VR); /* Check the length in this case to see if it small. The default will be little endian. */ byte_order = ACR_BIG_ENDIAN; acr_set_byte_order(afp, byte_order); acr_get_short(byte_order, 1, &buffer[3*ACR_SIZEOF_SHORT], &data_length2); if (data_length2 >= ACR_TEST_MAX2) { byte_order = ACR_LITTLE_ENDIAN; acr_set_byte_order(afp, byte_order); acr_get_short(byte_order, 1, &buffer[3*ACR_SIZEOF_SHORT], &data_length2); } if (data_length2 >= ACR_TEST_MAX2) { /* If we get here, we have completely failed to make sense of * the byte ordering. */ acr_set_byte_order(afp, old_byte_order); } } return ACR_OK; }
/* ----------------------------- MNI Header ----------------------------------- @NAME : acr_read_one_element @INPUT : afp - Acr_File pointer from which to read @OUTPUT : group_id - ACR-NEMA group id element_id - ACR-NEMA element id vr_name - 2 character string giving value representation. Two NULs are returned if VR is unknown. data_length - length of data to follow. Value ACR_VARIABLE_LENGTH is returned for undefined length elements in which case the data portion is not read in. data_pointer - pointer to data. Space is allocated by this routine. One additional byte is allocated and set to zero so that the data can be treated as a string. If a sequence is encountered, then NULL is returned. @RETURNS : VIO_Status. @DESCRIPTION: Routine to read in one ACR-NEMA element. @METHOD : @GLOBALS : @CALLS : @CREATED : November 10, 1993 (Peter Neelin) @MODIFIED : January 29, 1997 (P.N.) ---------------------------------------------------------------------------- */ Acr_Status acr_read_one_element(Acr_File *afp, int *group_id, int *element_id, char vr_name[], long *data_length, char **data_pointer) { long buflen; unsigned char buffer[2*ACR_SIZEOF_SHORT+ACR_SIZEOF_LONG]; Acr_Short grpid, elid, sval; Acr_Long datalen; size_t size_allocated; int offset; Acr_byte_order byte_order; Acr_Status status; /* Get byte ordering */ byte_order = acr_get_byte_order(afp); /* Read in group id, element id and length of data */ status = acr_read_buffer(afp, buffer, SIZEOF_ARRAY(buffer), &buflen); if (status != ACR_OK) return status; offset = 0; acr_get_short(byte_order, 1, &buffer[offset], &grpid); offset += ACR_SIZEOF_SHORT; *group_id = (int)grpid; acr_get_short(byte_order, 1, &buffer[offset], &elid); offset += ACR_SIZEOF_SHORT; *element_id = (int)elid; /* Look for VR and length of data */ if (grpid == ACR_ITEM_GROUP || acr_get_vr_encoding(afp) == ACR_IMPLICIT_VR) { vr_name[0] = '\0'; vr_name[1] = '\0'; acr_get_long(byte_order, 1, &buffer[offset], &datalen); offset += ACR_SIZEOF_LONG; } else { vr_name[0] = buffer[offset++]; vr_name[1] = buffer[offset++]; acr_get_short(byte_order, 1, &buffer[offset], &sval); offset += ACR_SIZEOF_SHORT; datalen = (Acr_Long)sval; } /* Read in length for special VR's */ if (is_special_vr(vr_name)) { status = acr_read_buffer(afp, buffer, (long) ACR_SIZEOF_LONG, NULL); if (status != ACR_OK) return ACR_ABNORMAL_END_OF_INPUT; acr_get_long(byte_order, 1, &buffer[0], &datalen); } /* Check for undefined length */ if (datalen == ACR_UNDEFINED_ELEMENT_LENGTH) { *data_length = ACR_VARIABLE_LENGTH; *data_pointer = NULL; return ACR_OK; } *data_length = (long)datalen; /* Check for sequence VR */ if (is_sequence_vr(vr_name)) { *data_pointer = NULL; return ACR_OK; } /* Allocate space for the data and null-terminate it */ size_allocated = *data_length + 1; *data_pointer = MALLOC(size_allocated); if (*data_pointer == NULL) { *data_length = 0; size_allocated = *data_length + 1; *data_pointer = MALLOC(size_allocated); } (*data_pointer)[*data_length] = '\0'; /* Read in the data */ status = acr_read_buffer(afp, (unsigned char *) *data_pointer, *data_length, NULL); if (status != ACR_OK) { FREE(*data_pointer); return ACR_ABNORMAL_END_OF_INPUT; } return ACR_OK; }