Skip to content
Open
Show file tree
Hide file tree
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
50 changes: 50 additions & 0 deletions platform/core/src/classes/MetadataProvider.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,4 +107,54 @@ describe('MetadataProvider', () => {
});
});
});

describe('the overlay plane module', () => {
it('reads an overlay that dcmjs named by keyword', () => {
// What dcmjs >= 0.50 makes of group 6000 in DICOMweb metadata.
const instance = {
OverlayRows: 512,
OverlayColumns: 256,
OverlayType: 'G',
OverlayOrigin: [1, 1],
OverlayBitsAllocated: 1,
OverlayBitPosition: 0,
OverlayData: { BulkDataURI: 'http://localhost/bulk/overlay-6000' },
};

const { overlays } = metadataProvider.getTagFromInstance('overlayPlaneModule', instance);

expect(overlays).toHaveLength(1);
expect(overlays[0]).toMatchObject({
rows: 512,
columns: 256,
type: 'G',
x: 1,
y: 1,
pixelData: { BulkDataURI: 'http://localhost/bulk/overlay-6000' },
});
});

it('reads overlays that dcmjs kept under their tag', () => {
// dcmjs < 0.50 keeps the hex tag as the key.
const instance = {
'60000010': 512,
'60000011': 256,
'60000040': 'G',
'60000050': [1, 1],
'60003000': { BulkDataURI: 'http://localhost/bulk/overlay-6000' },
'60020010': 64,
'60020011': 32,
'60020040': 'R',
'60020050': [5, 7],
'60023000': { BulkDataURI: 'http://localhost/bulk/overlay-6002' },
};

const { overlays } = metadataProvider.getTagFromInstance('overlayPlaneModule', instance);

expect(overlays).toMatchObject([
{ rows: 512, columns: 256, type: 'G', x: 1, y: 1 },
{ rows: 64, columns: 32, type: 'R', x: 5, y: 7 },
]);
});
});
});
36 changes: 22 additions & 14 deletions platform/core/src/classes/MetadataProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -279,8 +279,14 @@ class MetadataProvider {
groupStr = `600${overlayGroup.toString(16)}`;
}

// dcmjs >= 0.50 names 60xx tags by keyword (OverlayData, OverlayRows, ...) instead of
// by tag. All overlay groups share these keywords, so dcmjs keeps at most one overlay
// under them; it is read as group 6000.
const getValue = (tag: string, keyword: string) =>
instance[tag] ?? (overlayGroup === 0x00 ? instance[keyword] : undefined);

const OverlayDataTag = `${groupStr}3000`;
const OverlayData = instance[OverlayDataTag];
const OverlayData = getValue(OverlayDataTag, 'OverlayData');

if (!OverlayData) {
continue;
Expand All @@ -295,24 +301,26 @@ class MetadataProvider {
const ROIAreaTag = `${groupStr}1301`;
const ROIMeanTag = `${groupStr}1302`;
const ROIStandardDeviationTag = `${groupStr}1303`;
const OverlayOrigin = instance[OverlayOriginTag];
const OverlayOrigin = getValue(OverlayOriginTag, 'OverlayOrigin');
const OverlayRows = getValue(OverlayRowsTag, 'OverlayRows');
const OverlayColumns = getValue(OverlayColumnsTag, 'OverlayColumns');

let rows = 0;
if (instance[OverlayRowsTag] instanceof Array) {
if (OverlayRows instanceof Array) {
// The DICOM VR for overlay rows is US (unsigned short).
const rowsInt16Array = new Uint16Array(instance[OverlayRowsTag][0]);
const rowsInt16Array = new Uint16Array(OverlayRows[0]);
rows = rowsInt16Array[0];
} else {
rows = instance[OverlayRowsTag];
rows = OverlayRows;
}

let columns = 0;
if (instance[OverlayColumnsTag] instanceof Array) {
if (OverlayColumns instanceof Array) {
// The DICOM VR for overlay columns is US (unsigned short).
const columnsInt16Array = new Uint16Array(instance[OverlayColumnsTag][0]);
const columnsInt16Array = new Uint16Array(OverlayColumns[0]);
columns = columnsInt16Array[0];
} else {
columns = instance[OverlayColumnsTag];
columns = OverlayColumns;
}

let x = 0;
Expand All @@ -330,15 +338,15 @@ class MetadataProvider {
const overlay = {
rows: rows,
columns: columns,
type: instance[OverlayType],
type: getValue(OverlayType, 'OverlayType'),
x,
y,
pixelData: OverlayData,
description: instance[OverlayDescriptionTag],
label: instance[OverlayLabelTag],
roiArea: instance[ROIAreaTag],
roiMean: instance[ROIMeanTag],
roiStandardDeviation: instance[ROIStandardDeviationTag],
description: getValue(OverlayDescriptionTag, 'OverlayDescription'),
label: getValue(OverlayLabelTag, 'OverlayLabel'),
roiArea: getValue(ROIAreaTag, 'ROIArea'),
roiMean: getValue(ROIMeanTag, 'ROIMean'),
roiStandardDeviation: getValue(ROIStandardDeviationTag, 'ROIStandardDeviation'),
};

overlays.push(overlay);
Expand Down