fix(MetadataProvider): Correctly assign imageId for multiframe images and remove unused frame information retrieval method (#5965)

This commit is contained in:
Alireza authored and GitHub committed 2026-07-10 15:35:09 -04:00
1 parent 2c54616136
commit 1eee3e6119
7 files changed
+369 -43

No files matched your search

+26 -37
View File
@@ -1,6 +1,7 @@
import queryString from 'query-string';
import dicomParser from 'dicom-parser';
import { utilities } from '@cornerstonejs/core';
import { utilities as csMetadataUtilities } from '@cornerstonejs/metadata';
import { baseImageURIForMetadata } from '../utils/imageIdToURI';
import DicomMetadataStore from '../services/DicomMetadataStore';
import fetchPaletteColorLookupTableData from '../utils/metadataProvider/fetchPaletteColorLookupTableData';
@@ -8,6 +9,7 @@ import toNumber from '../utils/toNumber';
import combineFrameInstance from '../utils/combineFrameInstance';
const { calibratedPixelSpacingMetadataProvider, getPixelSpacingInformation } = utilities;
const { getUriModule } = csMetadataUtilities;
class MetadataProvider {
private readonly imageURIToUIDs: Map<string, any> = new Map();
@@ -60,7 +62,22 @@ class MetadataProvider {
return;
}
return (frameNumber && combineFrameInstance(frameNumber, instance)) || instance;
const result = (frameNumber && combineFrameInstance(frameNumber, instance)) || instance;
// We reassign the imageId on the instance because multiframe images processed
// through combineFrameInstance will mistakenly get the first imageId.
// This happens because the DICOM web data store only keeps the first instance.
// Defined non-enumerable so spreading the instance into another object does
// not carry the imageId over (it belongs to this frame only).
if (result) {
Object.defineProperty(result, 'imageId', {
value: imageId,
writable: true,
enumerable: false,
configurable: true,
});
}
return result;
}
get(query, imageId, options = { fallback: false }) {
@@ -423,37 +440,6 @@ class MetadataProvider {
return metadata;
}
/**
* Retrieves the frameNumber information, depending on the url style
* wadors /frames/1
* wadouri &frame=1
* @param {*} imageId
* @returns
*/
getFrameInformationFromURL(imageId) {
function getInformationFromURL(informationString, separator) {
let result = '';
const splittedStr = imageId.split(informationString)[1];
if (splittedStr.includes(separator)) {
result = splittedStr.split(separator)[0];
} else {
result = splittedStr;
}
return result;
}
if (imageId.includes('/frames')) {
return getInformationFromURL('/frames', '/');
}
if (imageId.includes('?frame=')) {
return getInformationFromURL('?frame=', '&');
}
if (imageId.includes('&frame=')) {
return getInformationFromURL('&frame=', '&');
}
return;
}
getUIDsFromImageID(imageId) {
if (imageId.startsWith('wadors:')) {
const strippedImageId = imageId.split('/studies/')[1];
@@ -467,23 +453,26 @@ class MetadataProvider {
};
} else if (imageId.includes('?requestType=WADO')) {
const qs = queryString.parse(imageId);
const frameNumber = qs.frameNumber || qs.frame;
return {
StudyInstanceUID: qs.studyUID,
SeriesInstanceUID: qs.seriesUID,
SOPInstanceUID: qs.objectUID,
frameNumber: qs.frameNumber,
frameNumber,
};
}
const imageURI = baseImageURIForMetadata(imageId);
const uids = this.imageURIToUIDs.get(imageURI);
const frameNumber = this.getFrameInformationFromURL(imageId) || '1';
if (uids && frameNumber !== undefined) {
return { ...uids, frameNumber };
if (!uids) {
return;
}
return uids;
const frameNumber = getUriModule(imageId)?.framesString || uids.frameNumber || '1';
return { ...uids, frameNumber };
}
}