Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | 182x 182x 182x 139674x | import dcmjs from 'dcmjs';
export const EXPLICIT_VR_LITTLE_ENDIAN = '1.2.840.10008.1.2.1';
export const DICOM_WRITE_OPTIONS = {
allowInvalidVRLength: false,
// `fragmentMultiframe` only governs whether a SINGLE frame is split across
// multiple fragments (dcmjs splits frames larger than its 20KB fragment size).
// It does NOT merge frames: in an encapsulated (compressed) transfer syntax
// every frame is always written as its own fragment, preceded by the Basic
// Offset Table; in an uncompressed syntax pixel data is never fragmented at
// all. Keeping this `false` therefore yields exactly one fragment per frame
// for compressed SEG — the conformant layout — without splitting large frames.
fragmentMultiframe: false,
};
/** OHIF runtime fields — not DICOM tags; must not be enumerable for dcmjs datasetToDict. */
export const RUNTIME_INSTANCE_PROPERTY_KEYS = [
'url',
'wadorsuri',
'wadouri',
'wadoRoot',
'wadoUri',
'wadoUriRoot',
'imageRendering',
'imageId',
'_parentInstance',
'frameNumber',
] as const;
/**
* Attaches OHIF runtime data on an instance without enumerable keys (safe for dcmjs datasetToDict).
*/
export function setNonEnumerableInstanceProperty(
instance: Record<string, unknown>,
key: string,
value: unknown
) {
Object.defineProperty(instance, key, {
value,
enumerable: false,
writable: true,
configurable: true,
});
}
/**
* Re-defines any existing enumerable runtime properties as non-enumerable (keeps values).
*/
export function makeExistingPropertiesNonEnumerable(instance: Record<string, unknown>) {
for (const key of RUNTIME_INSTANCE_PROPERTY_KEYS) {
Iif (!Object.prototype.hasOwnProperty.call(instance, key)) {
continue;
}
const descriptor = Object.getOwnPropertyDescriptor(instance, key);
Iif (!descriptor || descriptor.enumerable === false) {
continue;
}
setNonEnumerableInstanceProperty(instance, key, descriptor.value);
}
}
export function getDatasetTransferSyntaxUID(dataset) {
const fromMeta = dataset?._meta?.TransferSyntaxUID;
Iif (typeof fromMeta === 'string') {
return fromMeta;
}
Iif (Array.isArray(fromMeta?.Value)) {
return fromMeta.Value[0];
}
Iif (typeof dataset?.TransferSyntaxUID === 'string') {
return dataset.TransferSyntaxUID;
}
return EXPLICIT_VR_LITTLE_ENDIAN;
}
function applyTransferSyntaxToFileMeta(dicomDict, transferSyntaxUID) {
Iif (!transferSyntaxUID || !dicomDict?.meta) {
return;
}
// Hex key only: DicomMessage.write treats every meta key as a tag string, so a
// naturalized key like 'TransferSyntaxUID' would be parsed via parseInt(..., 16)
// into tag (0000,0000) and written as a garbage element in group 2.
dicomDict.meta['00020010'] = { vr: 'UI', Value: [transferSyntaxUID] };
}
export function datasetToDicomPart10Buffer(dataset) {
makeExistingPropertiesNonEnumerable(dataset);
const transferSyntaxUID = getDatasetTransferSyntaxUID(dataset);
const dicomDict = dcmjs.data.datasetToDict(dataset);
applyTransferSyntaxToFileMeta(dicomDict, transferSyntaxUID);
return dicomDict.write(DICOM_WRITE_OPTIONS);
}
export function datasetToDicomBlob(dataset) {
const part10Buffer = datasetToDicomPart10Buffer(dataset);
return new Blob([part10Buffer], { type: 'application/dicom' });
}
export function writeDicomDictToPart10Buffer(dicomDict) {
return dicomDict.write(DICOM_WRITE_OPTIONS);
}
|