feat: demo

This commit is contained in:
mozzie 2023-12-26 17:08:36 +08:00
parent f1824ee928
commit a34b2f725d
5 changed files with 258 additions and 11 deletions

View File

@ -35,7 +35,12 @@
"@cornerstonejs/streaming-image-volume-loader": "1.41.0",
"@cornerstonejs/calculate-suv": "1.1.0",
"vtk.js": "29.2.0",
"itk": "14.1.1"
"itk": "14.1.1",
"@itk-wasm/dicom": "5.0.2",
"itk-wasm": "1.0.0-b.160",
"itk-image-io": "^1.0.0-b.18",
"itk-mesh-io": "^1.0.0-b.18",
"web-workers": "0.9.1"
},
"devDependencies": {
"@babel/core": "^7.21.8",

View File

@ -7,6 +7,7 @@ import jsonLoader from "./loaders/json.loader";
import imgLoader from "./loaders/img.loader";
import babelLoader from "./loaders/babel.loader";
import { cssLoader, lessLoader } from "./loaders/style.loader";
import CopyWebpackPlugin from "copy-webpack-plugin";
// 加载配置文件
const envConfig = dotenv.config({
@ -63,6 +64,22 @@ const baseConfig: Configuration = {
"process.env.BASE_ENV": JSON.stringify(process.env.BASE_ENV),
"process.env.NODE_ENV": JSON.stringify(process.env.NODE_ENV),
}),
new CopyWebpackPlugin({
patterns: [
{
from: path.join(__dirname, "../", "node_modules", "web-workers"),
to: path.join(__dirname, "dist", "itk", "web-workers"),
},
{
from: path.join(__dirname, "../", "node_modules", "itk-image-io"),
to: path.join(__dirname, "dist", "itk", "image-io"),
},
{
from: path.join(__dirname, "../", "node_modules", "itk-mesh-io"),
to: path.join(__dirname, "dist", "itk", "mesh-io"),
},
],
}),
],
};

View File

@ -0,0 +1,87 @@
import macro from "@kitware/vtk.js/macro";
import Helper from "@kitware/vtk.js/Common/DataModel/ITKHelper";
const { convertItkToVtkImage } = Helper;
import readImageDICOMFileSeries from "itk/readImageDICOMFileSeries";
function getArrayName(filename) {
const idx = filename.lastIndexOf(".");
const name = idx > -1 ? filename.substring(0, idx) : filename;
return `Scalars ${name}`;
}
// ----------------------------------------------------------------------------
// vtkITKDicomImageReader methods
// ----------------------------------------------------------------------------
function vtkITKDicomImageReader(publicAPI, model) {
// Set our className
model.classHierarchy.push("vtkITKDicomImageReader");
// Returns a promise to signal when image is ready
publicAPI.readFileSeries = (files, fileName) => {
if (!files || !files.length || files === model.files) {
return Promise.resolve();
}
if (fileName && fileName !== model.fileName) {
model.fileName = fileName;
}
model.files = files;
return readImageDICOMFileSeries(null, files)
.then(({ webWorker, image }) => {
webWorker.terminate();
return image;
})
.then(itkImage => {
const imageData = convertItkToVtkImage(itkImage, {
scalarArrayName: model.arrayName || getArrayName(model.fileName)
});
model.output[0] = imageData;
publicAPI.modified();
return imageData;
});
};
publicAPI.requestData = (/* inData, outData */) => {
publicAPI.readFileSeries(model.files, model.fileName);
};
}
// ----------------------------------------------------------------------------
// Object factory
// ----------------------------------------------------------------------------
const DEFAULT_VALUES = {
fileName: "",
// If null/undefined a unique array will be generated
arrayName: null
};
// ----------------------------------------------------------------------------
export function extend(publicAPI, model, initialValues = {}) {
Object.assign(model, DEFAULT_VALUES, initialValues);
// Build VTK API
macro.obj(publicAPI, model);
macro.algo(publicAPI, model, 0, 1);
macro.setGet(publicAPI, model, ["fileName", "arrayName"]);
// vtkITKDicomImageReader methods
vtkITKDicomImageReader(publicAPI, model);
}
// ----------------------------------------------------------------------------
export const newInstance = macro.newInstance(extend, "vtkITKDicomImageReader");
// ----------------------------------------------------------------------------
export default { newInstance, extend };

View File

@ -1,11 +1,15 @@
import { useRef, useState } from "react";
import dicomParser from "dicom-parser";
import vtkVolume from '@kitware/vtk.js/Rendering/Core/Volume';
import vtkVolumeMapper from '@kitware/vtk.js/Rendering/Core/VolumeMapper';
import vtkFullScreenRenderWindow from '@kitware/vtk.js/Rendering/Misc/FullScreenRenderWindow';
import readImageDICOMFileSeries from "itk/readImageDICOMFileSeries";
import vtkITKHelper from '@kitware/vtk.js/Common/DataModel/ITKHelper';
import vtkVolume from "@kitware/vtk.js/Rendering/Core/Volume";
import vtkVolumeMapper from "@kitware/vtk.js/Rendering/Core/VolumeMapper";
import vtkFullScreenRenderWindow from "@kitware/vtk.js/Rendering/Misc/FullScreenRenderWindow";
import vtkITKHelper from "@kitware/vtk.js/Common/DataModel/ITKHelper";
import DicomLoader from "./dicomLoader.js";
// import readImageDICOMFileSeries from "itk/readImageDICOMFileSeries";
import { readImageDicomFileSeries } from "@itk-wasm/dicom";
// import { readImageDICOMFileSeries } from "itk-wasm";
interface LocalMprProps {
children?: JSX.Element;
@ -18,12 +22,23 @@ export const LocalMpr = (props: LocalMprProps) => {
) => {
if (event.target.files) {
const files = event.target.files;
const volumeImageData = await readImageDICOMFileSeries(files);
const vtkImage = vtkITKHelper.convertItkToVtkImage(volumeImageData);
if (!files.length) {
return;
}
const fileList: File[] = [];
for (let i = 0; i < files.length; i++) {
fileList.push(files[i]);
}
const image = await readImageDicomFileSeries(null, {
inputImages: fileList,
});
const vtkImage = vtkITKHelper.convertItkToVtkImage(image);
const volume = vtkVolume.newInstance();
const mapper = vtkVolumeMapper.newInstance();
mapper.setInputData(vtkImage);
volume.setMapper(mapper);
mapper.setInputData(vtkImage);
// 创建 vtk 的全屏渲染窗口
const fullScreenRenderer = vtkFullScreenRenderWindow.newInstance({

View File

@ -29,6 +29,9 @@ importers:
'@cornerstonejs/tools':
specifier: 1.41.0
version: 1.41.0(@babel/preset-env@7.21.5)(@kitware/vtk.js@29.2.0)(@types/d3-array@3.2.1)(@types/d3-interpolate@3.0.4)(autoprefixer@10.4.15)(d3-array@3.2.4)(d3-interpolate@3.0.1)(gl-matrix@3.4.3)(webpack@5.75.0)(wslink@1.11.4)
'@itk-wasm/dicom':
specifier: 5.0.2
version: 5.0.2
'@kitware/vtk.js':
specifier: 29.2.0
version: 192.168.4.201+4873/@kitware/vtk.js@29.2.0(@babel/preset-env@7.21.5)(autoprefixer@10.4.15)(webpack@5.75.0)(wslink@1.11.4)
@ -59,6 +62,15 @@ importers:
itk:
specifier: 14.1.1
version: 14.1.1
itk-image-io:
specifier: ^1.0.0-b.18
version: 1.0.0-b.18
itk-mesh-io:
specifier: ^1.0.0-b.18
version: 1.0.0-b.18
itk-wasm:
specifier: 1.0.0-b.160
version: 1.0.0-b.160
js-cookie:
specifier: 3.0.5
version: 3.0.5
@ -98,6 +110,9 @@ importers:
vtk.js:
specifier: 29.2.0
version: 29.2.0(@babel/preset-env@7.21.5)(autoprefixer@10.4.15)(webpack@5.75.0)(wslink@1.11.4)
web-workers:
specifier: 0.9.1
version: 0.9.1
devDependencies:
'@babel/core':
specifier: ^7.21.8
@ -3572,6 +3587,14 @@ packages:
/@ioredis/commands@1.2.0:
resolution: {integrity: sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==}
/@itk-wasm/dicom@5.0.2:
resolution: {integrity: sha512-XA7J+DKtuied0yUNu5MtR4OsOOjZcexLWOdDFHDTWRWufa+/uU+Lux8mDBp3Ljh9qkJ+3ii5LRrXpBAv8ub3MQ==, tarball: http://192.168.4.201:4873/@itk-wasm%2fdicom/-/dicom-5.0.2.tgz}
dependencies:
itk-wasm: 1.0.0-b.160
transitivePeerDependencies:
- debug
dev: false
/@jest/schemas@29.6.3:
resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
@ -4528,6 +4551,10 @@ packages:
resolution: {integrity: sha512-Uy0+khmZqUrUGm5dmMqVlnvufZRSK0FbYzVgp0UMstm+F5+W2/jnEEQyc9vo1ZR/E5ZI/B1WjjoTqBqwJL6Krw==}
dev: false
/@thewtex/zstddec@0.2.0:
resolution: {integrity: sha512-lIS+smrfa48WGlDVQSQSm0jBnwVp5XmfGJWU9q0J0fRFY9ohzK4s27Zg2SFMb1NWMp9RiANAdK+/q86EBGWR1Q==, tarball: http://192.168.4.201:4873/@thewtex%2fzstddec/-/zstddec-0.2.0.tgz}
dev: false
/@trysound/sax@0.2.0:
resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==}
engines: {node: '>=10.13.0'}
@ -4595,6 +4622,10 @@ packages:
'@types/d3-color': 3.1.3
dev: false
/@types/emscripten@1.39.10:
resolution: {integrity: sha512-TB/6hBkYQJxsZHSqyeuO1Jt0AB/bW6G7rHt9g7lML7SOF6lbgcHvw/Lr+69iqN0qxgXLhWKScAon73JNnptuDw==, tarball: http://192.168.4.201:4873/@types%2femscripten/-/emscripten-1.39.10.tgz}
dev: false
/@types/eslint-scope@3.7.4:
resolution: {integrity: sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==}
dependencies:
@ -5832,6 +5863,14 @@ packages:
- debug
dev: false
/axios@0.23.0:
resolution: {integrity: sha512-NmvAE4i0YAv5cKq8zlDoPd1VLKAqX5oLuZKs8xkJa4qi6RGn0uhCYFjWtHHC9EM/MwOwYWOs53W+V0aqEXq1sg==, tarball: http://192.168.4.201:4873/axios/-/axios-0.23.0.tgz}
dependencies:
follow-redirects: 1.15.2
transitivePeerDependencies:
- debug
dev: false
/axios@1.3.6:
resolution: {integrity: sha512-PEcdkk7JcdPiMDkvM4K6ZBRYq9keuVJsToxm2zQIM70Qqo2WHTdJZMXcG9X+RmRp2VPNUQC8W1RAGbgt6b1yMg==}
dependencies:
@ -5862,6 +5901,16 @@ packages:
- debug
dev: false
/axios@1.6.2:
resolution: {integrity: sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A==, tarball: http://192.168.4.201:4873/axios/-/axios-1.6.2.tgz}
dependencies:
follow-redirects: 1.15.2
form-data: 4.0.0
proxy-from-env: 1.1.0
transitivePeerDependencies:
- debug
dev: false
/babel-loader@9.1.2(@babel/core@7.21.8)(webpack@5.75.0):
resolution: {integrity: sha512-mN14niXW43tddohGl8HPu5yfQq70iUThvFL/4QzESA7GcZoC0eVOhvWdQ8+3UlSjaDE9MVtsW9mxDY07W7VpVA==}
engines: {node: '>= 14.15.0'}
@ -6483,6 +6532,11 @@ packages:
resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==}
engines: {node: '>=14'}
/commander@11.1.0:
resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==, tarball: http://192.168.4.201:4873/commander/-/commander-11.1.0.tgz}
engines: {node: '>=16'}
dev: false
/commander@2.20.3:
resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==, tarball: http://192.168.4.201:4873/commander/-/commander-2.20.3.tgz}
@ -6498,7 +6552,6 @@ packages:
/commander@8.3.0:
resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==}
engines: {node: '>= 12'}
dev: true
/commander@9.2.0:
resolution: {integrity: sha512-e2i4wANQiSXgnrBlIatyHtP1odfUp0BbV5Y5nEGbxtIrStkEOAAzCUirvLBNXHLr7kwLvJl6V+4V3XV9x7Wd9w==, tarball: http://192.168.4.201:4873/commander/-/commander-9.2.0.tgz}
@ -8087,7 +8140,15 @@ packages:
graceful-fs: 4.2.11
jsonfile: 6.1.0
universalify: 2.0.0
dev: true
/fs-extra@11.2.0:
resolution: {integrity: sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==, tarball: http://192.168.4.201:4873/fs-extra/-/fs-extra-11.2.0.tgz}
engines: {node: '>=14.14'}
dependencies:
graceful-fs: 4.2.11
jsonfile: 6.1.0
universalify: 2.0.0
dev: false
/fs-extra@7.0.1:
resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==}
@ -9013,6 +9074,56 @@ packages:
resolution: {integrity: sha512-RKYVTCjAnRthyJes037NX/IiqeidgN1xc3j1RjFfECFp28A1GVwK9nA+i0rJPaHqSZwygLzRnFlzUuHFoWWy+Q==}
engines: {node: '>=6'}
/itk-image-io@1.0.0-b.18:
resolution: {integrity: sha512-bvrn7dLdP5AkqpSdai849dzlbsS3YHs098BmKD1ZdfepARDjGs07kEsnSSQmy20CrRbIdG1vHcNkq5U37zWhKQ==, tarball: http://192.168.4.201:4873/itk-image-io/-/itk-image-io-1.0.0-b.18.tgz}
dependencies:
itk-wasm: 1.0.0-b.18
transitivePeerDependencies:
- debug
dev: false
/itk-mesh-io@1.0.0-b.18:
resolution: {integrity: sha512-3iV4Mx2GkXwC18susbRfIrZ4eZFCeM5yCEleALHlMDekrQAv/7Yo/6aq9lrWQN+Q8gGSNf5FE/Yk2bbmTqFcuQ==, tarball: http://192.168.4.201:4873/itk-mesh-io/-/itk-mesh-io-1.0.0-b.18.tgz}
dependencies:
itk-wasm: 1.0.0-b.18
transitivePeerDependencies:
- debug
dev: false
/itk-wasm@1.0.0-b.160:
resolution: {integrity: sha512-yrt0uRukqI9Q5s9HhzArxMNYvyU5CMbI1ddGzH0A4O3JWscnJug7J0RtY+RTl6nTHcqdrppNH7IRbnTXLZ79Rg==, tarball: http://192.168.4.201:4873/itk-wasm/-/itk-wasm-1.0.0-b.160.tgz}
hasBin: true
dependencies:
'@thewtex/zstddec': 0.2.0
'@types/emscripten': 1.39.10
axios: 1.6.2
comlink: 4.4.1
commander: 11.1.0
fs-extra: 11.2.0
glob: 8.1.0
markdown-table: 3.0.3
mime-types: 2.1.35
wasm-feature-detect: 1.6.1
transitivePeerDependencies:
- debug
dev: false
/itk-wasm@1.0.0-b.18:
resolution: {integrity: sha512-k4vSWbHWVoDueZ0wXxfK52qZ/BMjNM0YTKawQKrpsvC2GX7MSVkZpYArZ81XKd8OkTS8uXCWWh+LS0I0otFp2A==, tarball: http://192.168.4.201:4873/itk-wasm/-/itk-wasm-1.0.0-b.18.tgz}
hasBin: true
dependencies:
'@babel/runtime': 7.22.15
'@types/emscripten': 1.39.10
axios: 0.23.0
commander: 8.3.0
fs-extra: 10.1.0
mime-types: 2.1.35
promise-file-reader: 1.0.3
webworker-promise: 0.4.4
transitivePeerDependencies:
- debug
dev: false
/itk@14.1.1:
resolution: {integrity: sha512-gLHkndNe7s00lYzasdM74IgrxryF5PY5uqlTRXlCXK09l095M8Qs6WKhZm/DEavQ+rhE5tQL1qowqmQTIfUM2A==, tarball: http://192.168.4.201:4873/itk/-/itk-14.1.1.tgz}
hasBin: true
@ -9518,6 +9629,10 @@ packages:
engines: {node: '>=8'}
dev: true
/markdown-table@3.0.3:
resolution: {integrity: sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==, tarball: http://192.168.4.201:4873/markdown-table/-/markdown-table-3.0.3.tgz}
dev: false
/md5@2.3.0:
resolution: {integrity: sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==}
dependencies:
@ -13888,6 +14003,10 @@ packages:
- webpack
dev: false
/wasm-feature-detect@1.6.1:
resolution: {integrity: sha512-R1i9ED8UlLu/foILNB1ck9XS63vdtqU/tP1MCugVekETp/ySCrBZRk5I/zI67cI1wlQYeSonNm1PLjDHZDNg6g==, tarball: http://192.168.4.201:4873/wasm-feature-detect/-/wasm-feature-detect-1.6.1.tgz}
dev: false
/watchpack@2.4.0:
resolution: {integrity: sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==}
engines: {node: '>=10.13.0'}
@ -13914,6 +14033,10 @@ packages:
'@zxing/text-encoding': 0.9.0
dev: false
/web-workers@0.9.1:
resolution: {integrity: sha512-tbUQc2CmCppjIM2kX2Nq4L9I8DDzQBEEGLyyoaf0a5dogG1aPh1BgmUqPSsy/CK2A4X3sJ8G1svqnnrVoCqSSA==, tarball: http://192.168.4.201:4873/web-workers/-/web-workers-0.9.1.tgz}
dev: false
/webgl-constants@1.1.1:
resolution: {integrity: sha512-LkBXKjU5r9vAW7Gcu3T5u+5cvSvh5WwINdr0C+9jpzVB41cjQAP5ePArDtk/WHYdVj0GefCgM73BA7FlIiNtdg==, tarball: http://192.168.4.201:4873/webgl-constants/-/webgl-constants-1.1.1.tgz}
dev: false