improve export schema

This commit is contained in:
Ross
2025-06-01 22:17:41 +01:00
parent 313c7a9e9a
commit 1fd3020f0c
+114 -121
View File
@@ -1073,134 +1073,127 @@ function App() {
} }
useEffect(() => { useEffect(() => {
// Export the current viewer state as JSON // Export the current viewer state as JSON
window.exportViewerState = () => { window.exportViewerState = () => {
const numActive = viewportGrid.rows * viewportGrid.cols; const numActive = viewportGrid.rows * viewportGrid.cols;
const activeViewportModes = viewportModes.slice(0, numActive); const modes = viewportModes.slice(0, numActive);
const activeSelectedStackIdx = selectedStackIdx.slice(0, numActive); const stackIdx = selectedStackIdx.slice(0, numActive);
const activeAvailableStacks = availableStacks; const stacks = availableStacks.map(s => ({
const activeViewportImageIds = viewportImageIds.slice(0, numActive); i: s.imageIds, // imageIds
u: s.studyInstanceUID // studyInstanceUID
}));
// Collect viewport properties, stack positions, and camera for active viewports // Only keep minimal properties
const renderingEngine = renderingEngineRef.current; const renderingEngine = renderingEngineRef.current;
const viewportProperties: any[] = []; const props: any[] = [];
const stackPositions: number[] = []; const stackPos: number[] = [];
const cameraProperties: any[] = []; const cam: any[] = [];
for (let i = 0; i < numActive; i++) { for (let i = 0; i < numActive; i++) {
let props = null; let p = null, s = null, c = null;
let stackPos = null; if (renderingEngine) {
let camera = null; const viewportId = `CT_${i}`;
if (renderingEngine) { const viewport = renderingEngine.getViewport(viewportId);
const viewportId = `CT_${i}`; if (viewport) {
const viewport = renderingEngine.getViewport(viewportId); if (typeof viewport.getProperties === "function") {
if (viewport) { const { voiRange, invert, interpolationType, VOILUTFunction, colormap } = viewport.getProperties();
if (typeof viewport.getProperties === "function") { p = { voiRange, invert, interpolationType, VOILUTFunction, colormap };
props = viewport.getProperties(); }
} if (typeof viewport.getCurrentImageIdIndex === "function") {
if (typeof viewport.getCurrentImageIdIndex === "function") { s = viewport.getCurrentImageIdIndex();
stackPos = viewport.getCurrentImageIdIndex(); }
} if (typeof viewport.getCamera === "function") {
if (typeof viewport.getCamera === "function") { c = viewport.getCamera();
camera = viewport.getCamera();
}
} }
} }
viewportProperties.push(props); }
stackPositions.push(stackPos); props.push(p);
cameraProperties.push(camera); stackPos.push(s);
cam.push(c);
}
// Use short keys for compactness
const state = {
grid: viewportGrid,
modes,
stacks,
stackIdx,
stackPos,
props,
cam,
};
return JSON.stringify(state);
};
// Import and restore a viewer state from JSON (using stack indices)
window.importViewerState = (json: string) => {
try {
restoringStateRef.current = true;
const state = typeof json === "string" ? JSON.parse(json) : json;
if (state.grid) setViewportGrid(state.grid);
if (state.modes) setViewportModes(state.modes);
if (state.stacks) setAvailableStacks(state.stacks.map((s: any) => ({
imageIds: s.i,
studyInstanceUID: s.u,
})));
if (state.stackIdx && state.stacks) {
const reconstructed = state.stackIdx.map(
(idx: number) => state.stacks[idx]?.i || []
);
setViewportImageIds(reconstructed);
setSelectedStackIdx(state.stackIdx);
} }
const state = { setTimeout(() => {
viewportGrid, const renderingEngine = renderingEngineRef.current;
viewportModes: activeViewportModes, if (!renderingEngine) {
selectedStackIdx: activeSelectedStackIdx,
availableStacks: activeAvailableStacks,
viewportImageIds: activeViewportImageIds,
viewportProperties,
stackPositions,
cameraProperties,
};
return JSON.stringify(state, null, 2);
};
window.importViewerState = (json: string) => {
try {
console.log("Importing viewer state:", json);
restoringStateRef.current = true;
const state = typeof json === "string" ? JSON.parse(json) : json;
if (state.viewportGrid) setViewportGrid(state.viewportGrid);
if (state.viewportModes) setViewportModes(state.viewportModes);
if (state.selectedStackIdx) setSelectedStackIdx(state.selectedStackIdx);
if (state.availableStacks) setAvailableStacks(state.availableStacks);
if (state.viewportImageIds) setViewportImageIds(state.viewportImageIds);
setTimeout(() => {
const renderingEngine = renderingEngineRef.current;
if (!renderingEngine) {
restoringStateRef.current = false;
return;
}
const numActive = state.viewportGrid?.rows * state.viewportGrid?.cols || 1;
for (let i = 0; i < numActive; i++) {
const viewportId = `CT_${i}`;
const viewport = renderingEngine.getViewport(viewportId);
if (!viewport) continue;
// Restore stack position (scroll)
if (
state.stackPositions &&
typeof state.stackPositions[i] === "number" &&
typeof viewport.setImageIdIndex === "function"
) {
if (csUtilities && csUtilities.jumpToSlice) {
csUtilities.jumpToSlice(viewport.element, { imageIndex: state.stackPositions[i] });
} else {
viewport.setImageIdIndex(state.stackPositions[i]);
}
}
// Restore viewport properties (VOI, invert, etc.)
if (
state.viewportProperties &&
state.viewportProperties[i] &&
typeof viewport.setProperties === "function"
) {
const props = state.viewportProperties[i];
const { voiRange, invert, interpolationType, VOILUTFunction, colormap } = props;
const propsToRestore: any = {};
if (voiRange && voiRange.lower !== undefined && voiRange.upper !== undefined) propsToRestore.voiRange = voiRange;
if (invert !== undefined) propsToRestore.invert = invert;
if (interpolationType !== undefined) propsToRestore.interpolationType = interpolationType;
if (VOILUTFunction) propsToRestore.VOILUTFunction = VOILUTFunction;
if (
colormap !== undefined &&
colormap !== null &&
(typeof colormap === "string" || (typeof colormap === "object" && !("actor" in colormap)))
) {
propsToRestore.colormap = colormap;
}
viewport.setProperties(propsToRestore);
viewport.render();
}
// Restore camera properties (zoom, pan, orientation)
if (
state.cameraProperties &&
state.cameraProperties[i] &&
typeof viewport.setCamera === "function"
) {
viewport.setCamera(state.cameraProperties[i]);
viewport.render();
}
}
restoringStateRef.current = false; restoringStateRef.current = false;
console.log("Viewer state restored successfully"); return;
}, 300); }
} catch (e) { const numActive = state.grid?.rows * state.grid?.cols || 1;
for (let i = 0; i < numActive; i++) {
const viewportId = `CT_${i}`;
const viewport = renderingEngine.getViewport(viewportId);
if (!viewport) continue;
// Restore stack position
if (
state.stackPos &&
typeof state.stackPos[i] === "number" &&
typeof viewport.setImageIdIndex === "function"
) {
if (csUtilities && csUtilities.jumpToSlice) {
csUtilities.jumpToSlice(viewport.element, { imageIndex: state.stackPos[i] });
} else {
viewport.setImageIdIndex(state.stackPos[i]);
}
}
// Restore properties
if (
state.props &&
state.props[i] &&
typeof viewport.setProperties === "function"
) {
viewport.setProperties(state.props[i]);
viewport.render();
}
// Restore camera
if (
state.cam &&
state.cam[i] &&
typeof viewport.setCamera === "function"
) {
viewport.setCamera(state.cam[i]);
viewport.render();
}
}
restoringStateRef.current = false; restoringStateRef.current = false;
alert("Failed to import viewer state: " + e); }, 300);
} } catch (e) {
}; restoringStateRef.current = false;
alert("Failed to import viewer state: " + e);
}
};
// Export all annotations using cornerstoneTools.annotation.state.getAllAnnotations() // Export all annotations using cornerstoneTools.annotation.state.getAllAnnotations()
window.exportAnnotations = () => { window.exportAnnotations = () => {