Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve type declaration #258

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
269 changes: 230 additions & 39 deletions index.d.ts
Original file line number Diff line number Diff line change
@@ -1,99 +1,290 @@
declare module 'dicom-parser' {

export type ByteArray = Uint8Array | Buffer;
/**
* The tag of an element in the format `xGGGGEEEE` where :
* - `GGGG` stands for the big endian hexadecimal representation of the element's group number
* - `EEEE` stands for the big endian hexadecimal representation of the element's element number
*
* The `x` at the start is here to allow property access without requiring the use of the index access syntax.
*/
export type Tag = `x${string}` | string;

export const enum VR {
/** Application Entity */
AE = 'AE',
/** Age String */
AS = 'AS',
/** Attribute Tag */
AT = 'AT',
/** Code String */
CS = 'CS',
/** Date */
DA = 'DA',
/** Decimal String */
DS = 'DS',
/** Date Time */
DT = 'DT',
/** Floating Point Single */
FL = 'FL',
/** Floating Point Double */
FD = 'FD',
/** Integer String */
IS = 'IS',
/** Long String */
LO = 'LO',
/** Long Text */
LT = 'LT',
/** Other Byte String */
OB = 'OB',
/** Other Double String */
OD = 'OD',
/** Other Float String */
OF = 'OF',
/** Other Word String */
OW = 'OW',
/** Person Name */
PN = 'PN',
/** Short String */
SH = 'SH',
/** Signed Long */
SL = 'SL',
/** Sequence of Items */
SQ = 'SQ',
/** Signed Short */
SS = 'SS',
/** Short Text */
ST = 'ST',
/** Time */
TM = 'TM',
/** Unique Identifier (UID) */
UI = 'UI',
/** Unsigned Long */
UL = 'UL',
/** Unknown */
UN = 'UN',
/** Unsigned Short */
US = 'US',
/** Unlimited Text */
UT = 'UT'
}

/**
* Base template from which all elements in dataset inherit from.
*/
export interface DataElement {
/**
* The tag of the element in the format `xGGGGEEEE`.
* @see {@link Tag} for details on the formatting.
*/
tag: Tag;
/**
* The value representation of the element.
* This property will be undefined for file encoded using a transfer syntax using implicit VR,
* such as "Implicit VR Little Endian" (UID=1.2.840.10008.1.​2) which is the default transfer
* syntax defined by the spec and is thus widely used.
*/
vr?: VR;
/**
* The number of bytes in the Value field of the element.
* This property will be populated even if the element is defined with an undefined VL (0xFFFFFFFF).
*/
length: number;
/**
* Byte offset, from the start of the byte stream, where the Value field of the element starts
*/
dataOffset: number;
/**
* Is the element defined with an undefined VL (0xFFFFFFFF)?
* This property will be absent from elements with a defined Value Length, `true` otherwise.
*/
hadUndefinedLength?: true;
}

/**
* Used exclusively for Elements in the File Meta Information Group.
*/
export interface FileMetaInformationElement extends DataElement {
/**
* A little-endian parser provided as all elements of this group are required to be
* encoded in the "Explicit VR Little Endian Transfer Syntax" (UID=1.2.840.10008.1.2.1)
* as defined in [DICOM PS3.5](https://dicom.nema.org/medical/dicom/current/output/html/part05.html#PS3.5)
*/
parser: ByteArrayParser;
}

/**
* Used exclusively for `(7fe0,0010) Pixel Data Attribute` elements that are encoded using
* dataset encapsulation as defined in [DICOM PS3.5 A.4](https://dicom.nema.org/medical/dicom/2016b/output/chtml/part05/sect_A.4.html).
*/
export interface EncapsulatedPixelDataElement extends DataElement {
/**
* @inheritdoc
* The Pixel Data Attribute can only be encoded with VR of {@link VR.OB OB} or {@link VR.OW OW}
*/
vr?: VR.OB | VR.OW;

/**
* Pixel Data Attributes encoded using encapsulation are required to have a
* Value Length field set to undefined (0xFFFFFFFF).
*/
hadUndefinedLength: true;

/**
* This field discriminates between a Pixel Data Attribute element simply encoded with
* an undefined length and one actually using data set encapsulation.
*/
encapsulatedPixelData: true;
/**
* Holds the byte offset of each fragment, the first of which is the Basic Offset Table itself (it will always be 0).
* This property will always be present but might be empty depending on how the file was encoded.
*/
basicOffsetTable: number[];
/**
* Holds the information needed to extract the fragments from the byte stream.
* This property will always be populated with as many fragments as there are in the file.
*/
fragments: Fragment[];
}

/**
* Used inside an {@link EncapsulatedPixelDataElement} to define the position of each encapsulated element.
*/
export interface Fragment {
/**
* Byte offset, indexing from the start of the Pixel Data Attribute element, where the fragment starts.
*/
offset: number;
/**
* Byte offset, indexing from the start of the byte stream, where the fragment data starts.
*/
position: number;
/**
* Number of bytes contained by the fragment.
*/
length: number;
}

export interface Element {
tag: string;
vr?: string;
/**
* Basically an array of sub-datasets.
*/
export interface Sequence extends DataElement {
/**
* This field will always be populated for Sequence elements as they would not have been
* parsed correctly otherwise, this doesn't reflect whether or not the transfer syntax
* uses implicit or explicit VR.
*/
vr: VR.SQ;

/**
* Holds the items making up the sequence, can be empty if the sequence doesn't have any item.
*/
items: SequenceItem[];
}

/**
* Used inside a {@link Sequence} to define the content of an item of the sequence
*/
export interface SequenceItem {
/**
* Holds the elements contained by the sequence item.
*/
dataSet: DataSet;

/**
* Number of bytes in the item's dataset
*/
length: number;

/**
* Byte offset to the start of the item's dataset
*/
dataOffset: number;
items?: Element[];
dataSet?: DataSet;
parser?: ByteArrayParser;
hadUndefinedLength?: boolean;

encapsulatedPixelData?: boolean;
basicOffsetTable?: number[];
fragments?: Fragment[];
}

/**
* Union of all possible kinds of elements.
*/
export type Element = DataElement | Sequence | EncapsulatedPixelDataElement | FileMetaInformationElement;

export interface DataSet {
/**
* The buffer view of the entire file
*/
byteArray: ByteArray;
/**
* The parser to use for reading the dataset's elements, this parser is automatically selected
* to match the requirements of the transfer syntax.
*/
byteArrayParser : ByteArrayParser;
/**
* Access element with the DICOM tag in the format xGGGGEEEE.
* The record of the elements making up the dataset, accessible via the element's tag in the format xGGGGEEEE.
* @see {@link Tag} for details on the encoding.
*/
elements: {
[tag: string]: Element;
[tag: Tag]: Element;
};
warnings: string[];

/**
* Finds the element for tag and returns an unsigned int 16 if it exists and has data. Use this function for VR type US.
*/
uint16: (tag: string, index?: number) => number | undefined;
uint16: (tag: Tag, index?: number) => number | undefined;

/**
* Finds the element for tag and returns a signed int 16 if it exists and has data. Use this function for VR type SS.
*/
int16: (tag: string, index?: number) => number | undefined;
int16: (tag: Tag, index?: number) => number | undefined;

/**
* Finds the element for tag and returns an unsigned int 32 if it exists and has data. Use this function for VR type UL.
*/
uint32: (tag: string, index?: number) => number | undefined;
uint32: (tag: Tag, index?: number) => number | undefined;

/**
* Finds the element for tag and returns a signed int 32 if it exists and has data. Use this function for VR type SL.
*/
int32: (tag: string, index?: number) => number | undefined;
int32: (tag: Tag, index?: number) => number | undefined;

/**
* Finds the element for tag and returns a 32 bit floating point number if it exists and has data. Use this function for VR type FL.
*/
float: (tag: string, index?: number) => number | undefined;
float: (tag: Tag, index?: number) => number | undefined;

/**
* Finds the element for tag and returns a 64 bit floating point number if it exists and has data. Use this function for VR type FD.
*/
double: (tag: string, index?: number) => number | undefined;
double: (tag: Tag, index?: number) => number | undefined;

/**
* Returns the actual Value Multiplicity of an element - the number of values in a multi-valued element.
*/
numStringValues: (tag: string) => number | undefined;
numStringValues: (tag: Tag) => number | undefined;

/**
* Finds the element for tag and returns a string if it exists and has data. Use this function for VR types AE, CS, SH, and LO.
*/
string: (tag: string, index?: number) => string | undefined;
string: (tag: Tag, index?: number) => string | undefined;

/**
* Finds the element for tag and returns a string with the leading spaces preserved and trailing spaces removed if it exists and has data. Use this function for VR types UT, ST, and LT.
*/
text: (tag: string, index?: number) => string | undefined;
text: (tag: Tag, index?: number) => string | undefined;

/**
* Finds the element for tag and parses a string to a float if it exists and has data. Use this function for VR type DS.
*/
floatString: (tag: string, index?: number) => number | undefined;
floatString: (tag: Tag, index?: number) => number | undefined;

/**
* Finds the element for tag and parses a string to an integer if it exists and has data. Use this function for VR type IS.
*/
intString: (tag: string, index?: number) => number | undefined;
intString: (tag: Tag, index?: number) => number | undefined;

/**
* Finds the element for tag and parses an element tag according to the 'AT' VR definition if it exists and has data. Use this function for VR type AT.
*/
attributeTag: (tag: string) => string | undefined;
attributeTag: (tag: Tag) => string | undefined;
}
export type ByteArray = Uint8Array | Buffer;

export class ByteStream {
byteArray: ByteArray;
Expand All @@ -120,15 +311,15 @@ declare module 'dicom-parser' {

export interface ParseDicomOptions {
TransferSyntaxUID?: string;
untilTag?: string;
vrCallback?: (tag: string) => void;
untilTag?: Tag;
vrCallback?: (tag: Tag) => void;
inflater?: (arr: Uint8Array, position: number) => void;
}

export function parseDicom(arr: Uint8Array, option?: ParseDicomOptions): DataSet

export function isStringVr(vr: string): boolean
export function isPrivateTag(tag: string): boolean
export function isStringVr(vr: string): vr is VR
export function isPrivateTag(tag: Tag): boolean
export function parsePN(personName: string): {
familyName?: string;
givenName?: string;
Expand All @@ -151,9 +342,9 @@ declare module 'dicom-parser' {
type explicitDataSetToJSType = string | { dataOffset: number, length: number };
export function explicitDataSetToJS(dataSet: DataSet, options?: { omitPrivateAttibutes: boolean, maxElementLength: number }): explicitDataSetToJSType | explicitDataSetToJSType[]
export function createJPEGBasicOffsetTable(dataSet: DataSet, pixelDataElement: Element, fragments?: Fragment[]): number[];
export function parseDicomDataSetExplicit(dataSet: DataSet, byteStream: ByteStream, maxPosition?: number, options?: { untilTag: string }): void
type vrCallback = (tag: string) => string;
export function parseDicomDataSetImplicit(dataSet: DataSet, byteStream: ByteStream, maxPosition?: number, options?: { untilTag: string, vrCallback?: vrCallback }): void
export function parseDicomDataSetExplicit(dataSet: DataSet, byteStream: ByteStream, maxPosition?: number, options?: { untilTag: Tag }): void
type vrCallback = (tag: Tag) => VR;
export function parseDicomDataSetImplicit(dataSet: DataSet, byteStream: ByteStream, maxPosition?: number, options?: { untilTag: Tag, vrCallback?: vrCallback }): void
export function readFixedString(byteArray: ByteArray, position: number, length: number): string
export function alloc(byteArray: ByteArray, length: number): ByteArray
export const version: string;
Expand All @@ -163,15 +354,15 @@ declare module 'dicom-parser' {
export function findEndOfEncapsulatedElement(byteStream: ByteStream, element: Element, warnings?: string[]): void
export function findItemDelimitationItemAndSetElementLength(byteStream: ByteStream, element: Element): void
export const littleEndianByteArrayParser: ByteArrayParser;
export function readDicomElementExplicit(byteStream: ByteStream, warnings?: string[], untilTag?: string): Element
export function readDicomElementImplicit(byteStream: ByteStream, untilTag?: string, vrCallback?: vrCallback): Element
export function readDicomElementExplicit(byteStream: ByteStream, warnings?: string[], untilTag?: Tag): Element
export function readDicomElementImplicit(byteStream: ByteStream, untilTag?: Tag, vrCallback?: vrCallback): Element
export function readEncapsulatedImageFrame(dataSet: DataSet, pixelDataElement: Element, frameIndex: number, basicOffsetTable?: number[], fragments?: Fragment[]): ByteArray
export function readEncapsulatedPixelData(dataSet: DataSet, pixelDataElement: Element, frame: number): ByteArray
export function readEncapsulatedPixelDataFromFragments(dataSet: DataSet, pixelDataElement: Element, startFragmentIndex: number, numFragments?: number, fragments?: Fragment[]): ByteArray
export function readPart10Header(byteArray: ByteArray, options?: { untilTag: string }): DataSet
export function readPart10Header(byteArray: ByteArray, options?: { untilTag: Tag }): DataSet
export function readSequenceItemsExplicit(byteStream: ByteStream, element: Element, warnings?: string[]): void
export function readSequenceItemsImplicit(byteStream: ByteStream, element: Element, vrCallback?: vrCallback): void
export function readSequenceItem(byteStream: ByteStream): Pick<Element, 'tag' | 'length' | 'dataOffset'>
export function readTag(byteStream: ByteStream): string
export function readSequenceItem(byteStream: ByteStream): SequenceItem
export function readTag(byteStream: ByteStream): Tag

}