Exemplo n.º 1
0
def convert_ATvalue(byte_string, is_little_endian, struct_format=None):
    """Read and return AT (tag) data_element value(s)"""
    length = len(byte_string)
    if length == 4:
        return convert_tag(byte_string, is_little_endian)
    # length > 4
    if length % 4 != 0:
        logger.warn("Expected length to be multiple of 4 for VR 'AT', "
                    "got length %d", length)
    return MultiValue(Tag, [convert_tag(byte_string, is_little_endian, offset=x)
                            for x in range(0, length, 4)])
Exemplo n.º 2
0
def convert_numbers(byte_string, is_little_endian, struct_format):
    """Convert `byte_string` to a value,
       depending on `struct_format`.

    Given an encoded DICOM Element value,
    use `struct_format` and the endianness
    of the data to decode it.

    Parameters
    ----------
    byte_string : bytes
        The raw byte data to decode.
    is_little_endian : bool
        The encoding of `byte_string`.
    struct_format : str
        The type of data encoded in `byte_string`.

    Returns
    -------
    str
        If there is no encoded data in `byte_string`
        then an empty string will
        be returned.
    value
        If `byte_string` encodes a single value
         then it will be returned.
    list
        If `byte_string` encodes multiple values
        then a list of the decoded
        values will be returned.
    """
    endianChar = '><' [is_little_endian]

    # "=" means use 'standard' size, needed on 64-bit systems.
    bytes_per_value = calcsize("=" + struct_format)
    length = len(byte_string)

    if length % bytes_per_value != 0:
        logger.warn("Expected length to be even multiple of number size")

    format_string = "%c%u%c" % (endianChar, length // bytes_per_value,
                                struct_format)

    value = unpack(format_string, byte_string)

    # if the number is empty, then return the empty
    # string rather than empty list
    if len(value) == 0:
        return ''
    elif len(value) == 1:
        return value[0]
    else:
        # convert from tuple to a list so can modify if need to
        return list(value)
Exemplo n.º 3
0
def read_delimiter_item(fp, delimiter):
    """Read and ignore an expected delimiter.

    If the delimiter is not found or correctly formed, a warning is logged.
    """
    found = fp.read(4)
    if found != delimiter:
        logger.warn("Expected delimitor %s, got %s at file position 0x%x", Tag(delimiter), Tag(found), fp.tell() - 4)
    length = fp.read_UL()
    if length != 0:
        logger.warn("Expected delimiter item to have length 0, got %d at file position 0x%x", length, fp.tell() - 4)
Exemplo n.º 4
0
def convert_DA_string(byte_string, is_little_endian, struct_format=None):
    """Read and return a DA value"""
    if datetime_conversion:
        if not in_py2:
            byte_string = byte_string.decode(encoding)
        length = len(byte_string)
        if length != 8:
            logger.warn("Expected length to be 8, got length %d", length)
        return DA(byte_string)
    else:
        return convert_string(byte_string, is_little_endian, struct_format)
Exemplo n.º 5
0
def convert_DT_string(byte_string, is_little_endian, struct_format=None):
    """Read and return a DT value"""
    if datetime_conversion:
        if not in_py2:
            byte_string = byte_string.decode(encoding)
        length = len(byte_string)
        if length < 14 or length > 26:
            logger.warn("Expected length between 14 and 26, got length %d", length)
        return DT(byte_string)
    else:
        return convert_string(byte_string, is_little_endian, struct_format)
Exemplo n.º 6
0
def convert_numbers(byte_string, is_little_endian, struct_format):
    """Read a "value" of type struct_format from the dicom file. "Value" can be more than one number"""
    endianChar = '><'[is_little_endian]
    bytes_per_value = calcsize("=" + struct_format)  # "=" means use 'standard' size, needed on 64-bit systems.
    length = len(byte_string)
    if length % bytes_per_value != 0:
        logger.warn("Expected length to be even multiple of number size")
    format_string = "%c%u%c" % (endianChar, length // bytes_per_value, struct_format)
    value = unpack(format_string, byte_string)
    if len(value) == 1:
        return value[0]
    else:
        return list(value)  # convert from tuple to a list so can modify if need to
Exemplo n.º 7
0
def read_delimiter_item(fp, delimiter):
    """Read and ignore an expected delimiter.

    If the delimiter is not found or correctly formed, a warning is logged.
    """
    found = fp.read(4)
    if found != delimiter:
        logger.warn("Expected delimitor %s, got %s at file position 0x%x",
                    Tag(delimiter), Tag(found),
                    fp.tell() - 4)
    length = fp.read_UL()
    if length != 0:
        logger.warn(
            "Expected delimiter item to have length 0, "
            "got %d at file position 0x%x", length,
            fp.tell() - 4)
Exemplo n.º 8
0
def convert_numbers(byte_string, is_little_endian, struct_format):
    """Read a "value" of type struct_format from the dicom file. "Value" can be more than one number"""
    endianChar = '><'[is_little_endian]
    bytes_per_value = calcsize(
        "=" + struct_format
    )  # "=" means use 'standard' size, needed on 64-bit systems.
    length = len(byte_string)
    if length % bytes_per_value != 0:
        logger.warn("Expected length to be even multiple of number size")
    format_string = "%c%u%c" % (endianChar, length // bytes_per_value,
                                struct_format)
    value = unpack(format_string, byte_string)
    if len(value) == 1:
        return value[0]
    else:
        return list(
            value)  # convert from tuple to a list so can modify if need to
Exemplo n.º 9
0
def convert_numbers(byte_string, is_little_endian, struct_format):
    """Convert `byte_string` to a value, depending on `struct_format`.

    Given an encoded DICOM Element value, use `struct_format` and the endianness
    of the data to decode it.

    Parameters
    ----------
    byte_string : bytes
        The raw byte data to decode.
    is_little_endian : bool
        The encoding of `byte_string`.
    struct_format : str
        The type of data encoded in `byte_string`.

    Returns
    -------
    str
        If there is no encoded data in `byte_string` then an empty string will
        be returned.
    value
        If `byte_string` encodes a single value then it will be returned.
    list
        If `byte_string` encodes multiple values then a list of the decoded
        values will be returned.
    """
    endianChar = '><'[is_little_endian]
    bytes_per_value = calcsize(
        "=" + struct_format
    )  # "=" means use 'standard' size, needed on 64-bit systems.
    length = len(byte_string)
    if length % bytes_per_value != 0:
        logger.warn("Expected length to be even multiple of number size")
    format_string = "%c%u%c" % (endianChar, length // bytes_per_value,
                                struct_format)
    value = unpack(format_string, byte_string)
    if len(
            value
    ) == 0:  # if the number is empty, then return the empty string rather than empty list
        return ''
    elif len(value) == 1:
        return value[0]
    else:
        return list(
            value)  # convert from tuple to a list so can modify if need to
Exemplo n.º 10
0
def absorb_delimiter_item(fp, is_little_endian, delimiter):
    """Read (and ignore) undefined length sequence or item terminators."""
    if is_little_endian:
        struct_format = "<HHL"
    else:
        struct_format = ">HHL"
    group, elem, length = unpack(struct_format, fp.read(8))
    tag = TupleTag((group, elem))
    if tag != delimiter:
        msg = "Did not find expected delimiter '%s'" % dictionary_description(delimiter)
        msg += ", instead found %s at file position 0x%x" % (str(tag), fp.tell() - 8)
        logger.warn(msg)
        fp.seek(fp.tell() - 8)
        return
    logger.debug("%04x: Found Delimiter '%s'", fp.tell() - 8, dictionary_description(delimiter))
    if length == 0:
        logger.debug("%04x: Read 0 bytes after delimiter", fp.tell() - 4)
    else:
        logger.debug("%04x: Expected 0x00000000 after delimiter, found 0x%x", fp.tell() - 4, length)
Exemplo n.º 11
0
def convert_ATvalue(
    byte_string: bytes,
    is_little_endian: bool,
    struct_format: Optional[str] = None
) -> Union[BaseTag, MutableSequence[BaseTag]]:
    """Return a decoded 'AT' value.

    Parameters
    ----------
    byte_string : bytes
        The encoded 'AT' element value.
    is_little_endian : bool
        ``True`` if the value is encoded as little endian, ``False`` otherwise.
    struct_format : str, optional
        Not used.

    Returns
    -------
    BaseTag or MultiValue of BaseTag
        The decoded value(s).
    """
    length = len(byte_string)
    if length == 4:
        return convert_tag(byte_string, is_little_endian)

    # length > 4
    if length % 4 != 0:
        logger.warn(
            "Expected length to be multiple of 4 for VR 'AT', "
            f"got length {length}"
        )
    return MultiValue(
        Tag,
        [
            convert_tag(byte_string, is_little_endian, offset=x)
            for x in range(0, length, 4)
        ]
    )
Exemplo n.º 12
0
def absorb_delimiter_item(fp: BinaryIO, is_little_endian: bool,
                          delimiter: BaseTag) -> None:
    """Read (and ignore) undefined length sequence or item terminators."""
    if is_little_endian:
        struct_format = "<HHL"
    else:
        struct_format = ">HHL"
    group, elem, length = unpack(struct_format, fp.read(8))
    tag = TupleTag((group, elem))
    if tag != delimiter:
        logger.warn("Did not find expected delimiter "
                    f"'{dictionary_description(delimiter)}', instead found "
                    f"{tag} at file position 0x{fp.tell() - 8:X}")
        fp.seek(fp.tell() - 8)
        return

    logger.debug("%04x: Found Delimiter '%s'",
                 fp.tell() - 8, dictionary_description(delimiter))

    if length == 0:
        logger.debug("%04x: Read 0 bytes after delimiter", fp.tell() - 4)
    else:
        logger.debug("%04x: Expected 0x00000000 after delimiter, found 0x%x",
                     fp.tell() - 4, length)
Exemplo n.º 13
0
def _TM_from_byte_string(byte_string):
    byte_string = byte_string.rstrip()
    length = len(byte_string)
    if (length < 2 or length > 16) and length != 0:
        logger.warn("Expected length between 2 and 16, got length %d", length)
    return TM(byte_string)
Exemplo n.º 14
0
def _DT_from_byte_string(byte_string):
    byte_string = byte_string.rstrip()
    length = len(byte_string)
    if length < 4 or length > 26:
        logger.warn("Expected length between 4 and 26, got length %d", length)
    return DT(byte_string)
Exemplo n.º 15
0
def _DA_from_byte_string(byte_string):
    byte_string = byte_string.rstrip()
    length = len(byte_string)
    if length != 8 and length != 0:
        logger.warn("Expected length to be 8, got length %d", length)
    return DA(byte_string)
Exemplo n.º 16
0
def _DT_from_byte_string(byte_string):
    byte_string = byte_string.rstrip()
    length = len(byte_string)
    if length < 4 or length > 26:
        logger.warn("Expected length between 4 and 26, got length %d", length)
    return DT(byte_string)
Exemplo n.º 17
0
def _DA_from_byte_string(byte_string):
    byte_string = byte_string.rstrip()
    length = len(byte_string)
    if length != 8 and length != 0:
        logger.warn("Expected length to be 8, got length %d", length)
    return DA(byte_string)
Exemplo n.º 18
0
def _TM_from_byte_string(byte_string):
    byte_string = byte_string.rstrip()
    length = len(byte_string)
    if (length < 2 or length > 16) and length != 0:
        logger.warn("Expected length between 2 and 16, got length %d", length)
    return TM(byte_string)