新增 dcm 等医疗数位影像预览

This commit is contained in:
gaoxiongzaq
2023-04-20 16:06:01 +08:00
parent 76043a5b46
commit 83e20ac83c
19 changed files with 86959 additions and 1 deletions

View File

@ -0,0 +1,159 @@
class DICOMZero {
constructor(options={}) {
this.status = options.status || function() {};
this.reset();
}
reset() {
this.mappingLog = [];
this.dataTransfer = undefined;
this.datasets = [];
this.readers = [];
this.arrayBuffers = [];
this.files = [];
this.fileIndex = 0;
this.context = {patients: []};
}
static datasetFromArrayBuffer(arrayBuffer) {
let dicomData = dcmjs.data.DicomMessage.readFile(arrayBuffer);
let dataset = dcmjs.data.DicomMetaDictionary.naturalizeDataset(dicomData.dict);
dataset._meta = dcmjs.data.DicomMetaDictionary.namifyDataset(dicomData.meta);
return(dataset);
}
// return a function to use as the 'onload' callback for the file reader.
// The function takes a progress event argument and it knows (from this class instance)
// when all files have been read so it can invoke the doneCallback when all
// have been read.
getReadDICOMFunction(doneCallback, statusCallback) {
statusCallback = statusCallback || console.log;
return progressEvent => {
let reader = progressEvent.target;
let arrayBuffer = reader.result;
this.arrayBuffers.push(arrayBuffer);
let dicomData;
try {
dicomData = dcmjs.data.DicomMessage.readFile(arrayBuffer);
let dataset = dcmjs.data.DicomMetaDictionary.naturalizeDataset(dicomData.dict);
dataset._meta = dcmjs.data.DicomMetaDictionary.namifyDataset(dicomData.meta);
this.datasets.push(dataset);
} catch (error) {
console.error(error);
statusCallback("skipping non-dicom file");
}
let readerIndex = this.readers.indexOf(reader);
if (readerIndex < 0) {
reject("Logic error: Unexpected reader!");
} else {
this.readers.splice(readerIndex, 1); // remove the reader
}
if (this.fileIndex === this.dataTransfer.files.length) {
statusCallback(`Normalizing...`);
try {
this.multiframe = dcmjs.normalizers.Normalizer.normalizeToDataset(this.datasets);
} catch (e) {
console.error('Could not convert to multiframe');
console.error(e);
}
if (this.multiframe.SOPClassUID == dcmjs.data.DicomMetaDictionary.sopClassUIDsByName['Segmentation']){
statusCallback(`Creating segmentation...`);
try {
this.seg = new dcmjs.derivations.Segmentation([this.multiframe]);
statusCallback(`Created ${this.multiframe.NumberOfFrames} frame multiframe object and segmentation.`);
} catch (e) {
console.error('Could not create segmentation');
console.error(e);
}
} else if (this.multiframe.SOPClassUID == dcmjs.data.DicomMetaDictionary.sopClassUIDsByName['ParametricMapStorage']){
statusCallback(`Creating parametric map...`);
try {
this.pm = new dcmjs.derivations.ParametricMap([this.multiframe]);
statusCallback(`Created ${this.multiframe.NumberOfFrames} frame multiframe object and parametric map.`);
} catch (e) {
console.error('Could not create parametric map');
console.error(e);
}
}
doneCallback();
} else {
statusCallback(`Reading... (${this.fileIndex+1}).`);
this.readOneFile(doneCallback, statusCallback);
}
};
}
// Used for file selection button or drop of file list
readOneFile(doneCallback, statusCallback) {
let file = this.dataTransfer.files[this.fileIndex];
this.fileIndex++;
let reader = new FileReader();
reader.onload = this.getReadDICOMFunction(doneCallback, statusCallback);
reader.readAsArrayBuffer(file);
this.files.push(file);
this.readers.push(reader);
}
handleDataTransferFileAsDataset(file, options={}) {
options.doneCallback = options.doneCallback || function(){};
let reader = new FileReader();
reader.onload = (progressEvent) => {
let dataset = DICOMZero.datasetFromArrayBuffer(reader.result);
options.doneCallback(dataset);
}
reader.readAsArrayBuffer(file);
}
extractDatasetFromZipArrayBuffer(arrayBuffer) {
this.status(`Extracting ${this.datasets.length} of ${this.expectedDICOMFileCount}...`);
this.datasets.push(DICOMZero.datasetFromArrayBuffer(arrayBuffer));
if (this.datasets.length == this.expectedDICOMFileCount) {
this.status(`Finished extracting`);
this.zipFinishCallback();
}
};
handleZip(zip) {
this.zip = zip;
this.expectedDICOMFileCount = 0;
Object.keys(zip.files).forEach(fileKey => {
this.status(`Considering ${fileKey}...`);
if (fileKey.endsWith('.dcm')) {
this.expectedDICOMFileCount += 1;
zip.files[fileKey].async('arraybuffer').then(this.extractDatasetFromZipArrayBuffer.bind(this));
}
});
}
extractFromZipArrayBuffer(arrayBuffer, finishCallback=function(){}) {
this.zipFinishCallback = finishCallback;
this.status("Extracting from zip...");
JSZip.loadAsync(arrayBuffer)
.then(this.handleZip.bind(this));
}
organizeDatasets() {
this.datasets.forEach(dataset => {
let patientName = dataset.PatientName;
let studyTag = dataset.StudyDate + ": " + dataset.StudyDescription;
let seriesTag = dataset.SeriesNumber + ": " + dataset.SeriesDescription;
let patientNames = this.context.patients.map(patient => patient.name);
let patientIndex = patientNames.indexOf(dataset.PatientName);
if (patientIndex == -1) {
this.context.patients.push({
name: dataset.PatientName,
id: this.context.patients.length,
studies: {}
});
}
let studyNames; // TODO - finish organizing
});
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,43 @@
cornerstoneTools.external.cornerstone = cornerstone;
cornerstoneTools.external.Hammer = Hammer;
cornerstoneTools.external.cornerstoneMath = cornerstoneMath;
cornerstoneTools.init();
cornerstoneTools.addTool(cornerstoneTools.BidirectionalTool);
cornerstoneTools.addTool(cornerstoneTools.ArrowAnnotateTool);
cornerstoneTools.addTool(cornerstoneTools.EllipticalRoiTool);
function getBlobUrl(url) {
const baseUrl = window.URL || window.webkitURL;
const blob = new Blob([`importScripts('${url}')`], {
type: "application/javascript"
});
return baseUrl.createObjectURL(blob);
}
const config = {
maxWebWorkers: navigator.hardwareConcurrency || 1,
startWebWorkersOnDemand: true,
webWorkerPath: getBlobUrl(
"https://unpkg.com/cornerstone-wado-image-loader/dist/cornerstoneWADOImageLoaderWebWorker.min.js"
),
webWorkerTaskPaths: [],
taskConfiguration: {
decodeTask: {
loadCodecsOnStartup: true,
initializeCodecsOnStartup: false,
codecsPath: getBlobUrl(
"https://unpkg.com/cornerstone-wado-image-loader/dist/cornerstoneWADOImageLoaderCodecs.min.js"
),
usePDFJS: false,
strict: false
}
}
};
cornerstoneWADOImageLoader.webWorkerManager.initialize(config);
cornerstoneWADOImageLoader.external.cornerstone = cornerstone;
cornerstoneWADOImageLoader.external.dicomParser = dicomParser;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff