further improvements
This commit is contained in:
+15
-1
@@ -7,7 +7,21 @@
|
||||
<title>Vite + React + TS</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<div id="root" style="max-height:500px; height:500px; overflow:auto;"></div>
|
||||
<script type="module" src="/src/main.tsx"></script>
|
||||
|
||||
<input type="file" id="dicomInput" multiple />
|
||||
<button onclick="sendToViewer()">Send to Viewer</button>
|
||||
<script>
|
||||
function sendToViewer() {
|
||||
const files = document.getElementById('dicomInput').files;
|
||||
if (window.loadDicomStackFromFiles) {
|
||||
window.loadDicomStackFromFiles(files);
|
||||
} else {
|
||||
alert("Viewer API not ready");
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
+70
-18
@@ -9,7 +9,6 @@ import { init as csToolsInit, addTool, ToolGroupManager, Enums as csToolsEnums,
|
||||
import { LengthTool, ProbeTool, ArrowAnnotateTool, RectangleROITool, EllipticalROITool, PlanarFreehandROITool, PlanarFreehandContourSegmentationTool, SculptorTool, CrosshairsTool, ReferenceLinesTool, ReferenceCursors } from "@cornerstonejs/tools"
|
||||
import { init as dicomImageLoaderInit } from "@cornerstonejs/dicom-image-loader"
|
||||
import * as cornerstoneTools from '@cornerstonejs/tools';
|
||||
import { StackScrollOutOfBoundsEvent } from 'core/src/types/EventTypes';
|
||||
import { segmentation, Enums as csEnums } from '@cornerstonejs/tools';
|
||||
import { voi } from "@cornerstonejs/tools/utilities"
|
||||
import { readDicomElementExplicit } from "dicom-parser"
|
||||
@@ -18,6 +17,20 @@ import { metaData } from '@cornerstonejs/core';
|
||||
import * as dicomParser from "dicom-parser";
|
||||
import cornerstoneDICOMImageLoader from "@cornerstonejs/dicom-image-loader"
|
||||
|
||||
// Extend the Window interface to include cornerstoneTools
|
||||
declare global {
|
||||
interface Window {
|
||||
cornerstoneTools: typeof cornerstoneTools;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Add this type for clarity
|
||||
declare global {
|
||||
interface Window {
|
||||
loadDicomStackFromFiles?: (files: FileList | File[]) => void;
|
||||
}
|
||||
}
|
||||
|
||||
window.cornerstoneTools = cornerstoneTools;
|
||||
|
||||
@@ -203,7 +216,10 @@ function App() {
|
||||
if (url.startsWith("blob:") || url.startsWith("/")) {
|
||||
if (cornerstoneDICOMImageLoader.wadouri.dataSetCacheManager) {
|
||||
// If load returns a promise, collect it
|
||||
const result = cornerstoneDICOMImageLoader.wadouri.dataSetCacheManager.load(url);
|
||||
// @ts-ignore
|
||||
const result = cornerstoneDICOMImageLoader.wadouri.dataSetCacheManager.load(
|
||||
url,
|
||||
);
|
||||
if (result && typeof result.then === "function") {
|
||||
loadPromises.push(result);
|
||||
}
|
||||
@@ -367,6 +383,21 @@ function App() {
|
||||
setMetaModalOpen(true);
|
||||
};
|
||||
|
||||
// Inside your App component:
|
||||
useEffect(() => {
|
||||
window.loadDicomStackFromFiles = (files: FileList | File[]) => {
|
||||
// Convert FileList to array if needed
|
||||
const fileArray = Array.from(files);
|
||||
// Your logic to handle the files and load them as a stack
|
||||
// For example, call your existing handler:
|
||||
handleFilesSelected({ target: { files: fileArray } } as any);
|
||||
};
|
||||
// Cleanup on unmount
|
||||
return () => {
|
||||
window.loadDicomStackFromFiles = undefined;
|
||||
};
|
||||
}, []);
|
||||
|
||||
const [altPressed, setAltPressed] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -472,24 +503,39 @@ function App() {
|
||||
const fileInputRef = useRef<HTMLInputElement | null>(null);
|
||||
|
||||
// Handler for file input change
|
||||
const handleFilesSelected = async (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const files = event.target.files;
|
||||
if (!files || files.length === 0) return;
|
||||
const handleFilesSelected = async (event: React.ChangeEvent<HTMLInputElement> | { target: { files: File[] | FileList } }) => {
|
||||
const files = event.target.files;
|
||||
if (!files || files.length === 0) return;
|
||||
|
||||
// Reset order by slice location when new files are loaded
|
||||
setOrderBySliceLocation(false);
|
||||
setOrderBySliceLocation(false);
|
||||
|
||||
// Convert FileList to Array and sort by name (optional, for series order)
|
||||
const fileArray = Array.from(files).sort((a, b) => a.name.localeCompare(b.name));
|
||||
// Convert FileList to Array and sort by name (optional)
|
||||
const fileArray = Array.from(files).sort((a, b) => a.name.localeCompare(b.name));
|
||||
|
||||
// Create imageIds for each file using the cornerstone-wado-image-loader file API
|
||||
// (Assumes cornerstone-wado-image-loader is configured for file loading)
|
||||
const imageIds = fileArray.map(
|
||||
file => `wadouri:${URL.createObjectURL(file)}`
|
||||
);
|
||||
// Create imageIds for each file
|
||||
const imageIds = fileArray.map(
|
||||
file => `wadouri:${URL.createObjectURL(file)}`
|
||||
);
|
||||
|
||||
// Add as a new stack
|
||||
setAvailableStacks(prev => {
|
||||
const next = [...prev, imageIds];
|
||||
// Optionally, set the new stack as active in the first viewport:
|
||||
setViewportImageIds(vpPrev => {
|
||||
const vpNext = [...vpPrev];
|
||||
vpNext[0] = imageIds;
|
||||
return vpNext;
|
||||
});
|
||||
setSelectedStackIdx(selPrev => {
|
||||
const selNext = [...selPrev];
|
||||
selNext[0] = next.length - 1;
|
||||
return selNext;
|
||||
});
|
||||
// Cache imageIds and load metadata for this stack
|
||||
setLoadedImageIdsAndCacheMeta(imageIds);
|
||||
};
|
||||
return next;
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
const handleToolChange = (mouseButton: string, toolName: string) => {
|
||||
@@ -862,6 +908,13 @@ function App() {
|
||||
updateActiveReferenceLineViewport(mainToolGroup)
|
||||
}, [activeViewport, referenceLinesEnabled]);
|
||||
|
||||
useEffect(() => {
|
||||
if (fileInputRef.current) {
|
||||
fileInputRef.current.setAttribute("webkitdirectory", "true");
|
||||
fileInputRef.current.setAttribute("directory", "true");
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (!orderBySliceLocation) return;
|
||||
|
||||
@@ -1337,7 +1390,8 @@ function App() {
|
||||
<div style={{
|
||||
position: "relative",
|
||||
width: "99vw",
|
||||
height: "99vh",
|
||||
height: "100%", // <-- changed from 500px
|
||||
maxHeight: "100%", // <-- ensures it doesn't overflow parent
|
||||
padding: "12px", // <-- Add this line
|
||||
boxSizing: "border-box", // <-- Ensure padding doesn't shrink content
|
||||
background: "#222",
|
||||
@@ -1427,8 +1481,6 @@ function App() {
|
||||
type="file"
|
||||
style={{ display: "none" }}
|
||||
multiple
|
||||
webkitdirectory="true"
|
||||
directory="true"
|
||||
onChange={handleFilesSelected}
|
||||
accept=".dcm,application/dicom"
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user