further abstract dicom viewer
This commit is contained in:
+4
-239
@@ -498,95 +498,11 @@ function loadQuestion(n, section = 1, force_reload = false) {
|
|||||||
|
|
||||||
$(".thumbs .figure").each(function handleThumbnailClicks(id, thumbnail) {
|
$(".thumbs .figure").each(function handleThumbnailClicks(id, thumbnail) {
|
||||||
thumbnail.onclick = function (event) {
|
thumbnail.onclick = function (event) {
|
||||||
view(event, this);
|
viewer.openMainImage(current_question, event, this);
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
|
||||||
* View cornstone image
|
|
||||||
* @param {*} t
|
|
||||||
* @param {*} source
|
|
||||||
*/
|
|
||||||
function view(t, source) {
|
|
||||||
/**
|
|
||||||
* Load image
|
|
||||||
* @param {*} images - list of images
|
|
||||||
*/
|
|
||||||
async function load(images) {
|
|
||||||
const imageIds = [];
|
|
||||||
for (let i = 0; i < images.length; i++) {
|
|
||||||
const data_url = images[i];
|
|
||||||
// check stack type
|
|
||||||
if (data_url.startsWith("data:image")) {
|
|
||||||
const imageId = "base64://" + data_url.split(",")[1];
|
|
||||||
|
|
||||||
imageIds.push(imageId);
|
|
||||||
} else if (data_url.startsWith("data:application/dicom")) {
|
|
||||||
// stack = stack.split(";")[1];
|
|
||||||
|
|
||||||
const dfile = await helper.urltoFile(
|
|
||||||
data_url,
|
|
||||||
"dicom",
|
|
||||||
"application/dicom"
|
|
||||||
);
|
|
||||||
|
|
||||||
const imageId = cornerstoneWADOImageLoader.wadouri.fileManager.add(
|
|
||||||
dfile
|
|
||||||
);
|
|
||||||
imageIds.push(imageId);
|
|
||||||
// cornerstone.loadImage(imageId).then(function(image) {
|
|
||||||
// tempFunction(image);
|
|
||||||
// });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const stack = {
|
|
||||||
currentImageIdIndex: 0,
|
|
||||||
imageIds,
|
|
||||||
};
|
|
||||||
cornerstone.loadAndCacheImage(imageIds[0]).then(function (image) {
|
|
||||||
viewer.loadMainImage(image, stack);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (current_question) {
|
|
||||||
// Check if the figure is already loaded (or if another one is)
|
|
||||||
const open_figure = $("#dicom-image").data("figure");
|
|
||||||
const figure_to_load = source.id;
|
|
||||||
|
|
||||||
if (open_figure != undefined) {
|
|
||||||
// No full size figure / dicom loaded yet
|
|
||||||
if (figure_to_load == open_figure) {
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
el = document.getElementById("dicom-image");
|
|
||||||
if (el != undefined) {
|
|
||||||
cornerstone.disable(el);
|
|
||||||
$(".canvas-panel").remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$(".figure-open").removeClass("figure-open").addClass("figure");
|
|
||||||
|
|
||||||
source.className = "figure-open";
|
|
||||||
|
|
||||||
$(".question").append(
|
|
||||||
'<div class= "canvas-panel"><div id="dicom-image" data-figure="' +
|
|
||||||
figure_to_load +
|
|
||||||
'"></div></div>'
|
|
||||||
);
|
|
||||||
|
|
||||||
let images = current_question.images[figure_to_load.split("-")[1]];
|
|
||||||
// images = current_question.images
|
|
||||||
|
|
||||||
// Make sure we have an array
|
|
||||||
if (!Array.isArray(images)) {
|
|
||||||
images = [images];
|
|
||||||
}
|
|
||||||
|
|
||||||
load(images);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Answer setup
|
// Answer setup
|
||||||
const ap = $(".answer-panel");
|
const ap = $(".answer-panel");
|
||||||
@@ -1026,160 +942,6 @@ function createQuestionListPanel() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle key button events
|
|
||||||
* These are the same as in the RCR pratique implementation
|
|
||||||
* @param {*} event - KeyEvent
|
|
||||||
*/
|
|
||||||
function keydown_handler(event) {
|
|
||||||
const target_element = event.target.tagName;
|
|
||||||
|
|
||||||
// Catch all keypresses unless user is typing
|
|
||||||
if (target_element == "INPUT" || target_element == "TEXTAREA") {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const sel = $(".control-overlay").get(0);
|
|
||||||
switch (event.code) {
|
|
||||||
case "KeyP":
|
|
||||||
sel.selectedIndex = viewer.find_option(sel, "pan");
|
|
||||||
viewer.changeControlSelection();
|
|
||||||
break;
|
|
||||||
case "KeyZ":
|
|
||||||
sel.selectedIndex = viewer.find_option(sel, "zoom");
|
|
||||||
viewer.changeControlSelection();
|
|
||||||
break;
|
|
||||||
case "KeyR":
|
|
||||||
sel.selectedIndex = viewer.find_option(sel, "rotate");
|
|
||||||
viewer.changeControlSelection();
|
|
||||||
break;
|
|
||||||
case "KeyS":
|
|
||||||
sel.selectedIndex = viewer.find_option(sel, "scroll");
|
|
||||||
viewer.changeControlSelection();
|
|
||||||
break;
|
|
||||||
case "KeyW":
|
|
||||||
sel.selectedIndex = viewer.find_option(sel, "window");
|
|
||||||
viewer.changeControlSelection();
|
|
||||||
break;
|
|
||||||
case "KeyA":
|
|
||||||
sel.selectedIndex = viewer.find_option(sel, "abdomen");
|
|
||||||
viewer.changeControlSelection();
|
|
||||||
break;
|
|
||||||
case "KeyU":
|
|
||||||
sel.selectedIndex = viewer.find_option(sel, "pulmonary");
|
|
||||||
viewer.changeControlSelection();
|
|
||||||
break;
|
|
||||||
case "KeyB":
|
|
||||||
sel.selectedIndex = viewer.find_option(sel, "brain");
|
|
||||||
viewer.changeControlSelection();
|
|
||||||
break;
|
|
||||||
case "KeyO":
|
|
||||||
sel.selectedIndex = viewer.find_option(sel, "bone");
|
|
||||||
viewer.changeControlSelection();
|
|
||||||
break;
|
|
||||||
case "KeyE":
|
|
||||||
sel.selectedIndex = viewer.find_option(sel, "reset");
|
|
||||||
// $("#dicom-image").get(0).scrollIntoView(false);
|
|
||||||
viewer.changeControlSelection();
|
|
||||||
break;
|
|
||||||
// Escape and C do the same
|
|
||||||
case "KeyC":
|
|
||||||
case "Escape":
|
|
||||||
sel.selectedIndex = viewer.find_option(sel, "close");
|
|
||||||
viewer.changeControlSelection();
|
|
||||||
break;
|
|
||||||
case "Enter":
|
|
||||||
t.focus();
|
|
||||||
break;
|
|
||||||
// TODO: implement arrow stuff
|
|
||||||
//
|
|
||||||
case "ArrowUp": {
|
|
||||||
// Arrow function depends on the currently selected option
|
|
||||||
switch (sel.options[sel.selectedIndex].value) {
|
|
||||||
case "pan":
|
|
||||||
viewer.manualPanDicom(0, -1);
|
|
||||||
break;
|
|
||||||
case "zoom":
|
|
||||||
// _this.current_dicom.current_view.pre_scale_at(1.01, 1.01, _this.current_dicom.cols / 2, _this.current_dicom.rows / 2);
|
|
||||||
viewer.manualZoomDicom(1);
|
|
||||||
break;
|
|
||||||
case "rotate":
|
|
||||||
viewer.manualRotateDicom(-1);
|
|
||||||
break;
|
|
||||||
case "scroll":
|
|
||||||
viewer.manualScrollDicom(-1);
|
|
||||||
break;
|
|
||||||
case "window":
|
|
||||||
viewer.manualWindowDicom(1, 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "ArrowDown": {
|
|
||||||
switch (sel.options[sel.selectedIndex].value) {
|
|
||||||
case "pan":
|
|
||||||
viewer.manualPanDicom(0, 1);
|
|
||||||
break;
|
|
||||||
case "zoom":
|
|
||||||
viewer.manualZoomDicom(-1);
|
|
||||||
break;
|
|
||||||
case "rotate":
|
|
||||||
viewer.manualRotateDicom(1);
|
|
||||||
break;
|
|
||||||
case "scroll":
|
|
||||||
viewer.manualScrollDicom(1);
|
|
||||||
break;
|
|
||||||
case "window":
|
|
||||||
viewer.manualWindowDicom(-1, 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "ArrowLeft": {
|
|
||||||
switch (sel.options[sel.selectedIndex].value) {
|
|
||||||
case "pan":
|
|
||||||
viewer.manualPanDicom(-1, 0);
|
|
||||||
break;
|
|
||||||
case "zoom":
|
|
||||||
viewer.manualZoomDicom(-1);
|
|
||||||
break;
|
|
||||||
case "rotate":
|
|
||||||
viewer.manualRotateDicom(1);
|
|
||||||
break;
|
|
||||||
case "scroll":
|
|
||||||
viewer.manualScrollDicom(1);
|
|
||||||
break;
|
|
||||||
case "window":
|
|
||||||
viewer.manualWindowDicom(0, -1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "ArrowRight": {
|
|
||||||
switch (sel.options[sel.selectedIndex].value) {
|
|
||||||
case "pan":
|
|
||||||
viewer.manualPanDicom(1, 0);
|
|
||||||
break;
|
|
||||||
case "zoom":
|
|
||||||
viewer.manualZoomDicom(1);
|
|
||||||
break;
|
|
||||||
case "rotate":
|
|
||||||
viewer.manualRotateDicom(-1);
|
|
||||||
break;
|
|
||||||
case "scroll":
|
|
||||||
viewer.manualScrollDicom(-1);
|
|
||||||
break;
|
|
||||||
case "window":
|
|
||||||
viewer.manualWindowDicom(0, 1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
event.preventDefault();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Register Key Event Listener
|
|
||||||
window.addEventListener("keydown", keydown_handler);
|
|
||||||
|
|
||||||
$("#btn-local-file-load").click(function (evt) {
|
$("#btn-local-file-load").click(function (evt) {
|
||||||
loadLocalQuestionSet();
|
loadLocalQuestionSet();
|
||||||
@@ -2004,3 +1766,6 @@ function saveSession() {
|
|||||||
total_questions: window.number_of_questions,
|
total_questions: window.number_of_questions,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Register Key Event Listener
|
||||||
|
window.addEventListener("keydown", viewer.keydown_handler);
|
||||||
+238
@@ -328,3 +328,241 @@ export function changeControlSelection() {
|
|||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle key button events
|
||||||
|
* These are the same as in the RCR pratique implementation
|
||||||
|
* @param {*} event - KeyEvent
|
||||||
|
*/
|
||||||
|
export function keydown_handler(event) {
|
||||||
|
const target_element = event.target.tagName;
|
||||||
|
|
||||||
|
// Catch all keypresses unless user is typing
|
||||||
|
if (target_element == "INPUT" || target_element == "TEXTAREA") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const sel = $(".control-overlay").get(0);
|
||||||
|
switch (event.code) {
|
||||||
|
case "KeyP":
|
||||||
|
sel.selectedIndex = find_option(sel, "pan");
|
||||||
|
changeControlSelection();
|
||||||
|
break;
|
||||||
|
case "KeyZ":
|
||||||
|
sel.selectedIndex = find_option(sel, "zoom");
|
||||||
|
changeControlSelection();
|
||||||
|
break;
|
||||||
|
case "KeyR":
|
||||||
|
sel.selectedIndex = find_option(sel, "rotate");
|
||||||
|
changeControlSelection();
|
||||||
|
break;
|
||||||
|
case "KeyS":
|
||||||
|
sel.selectedIndex = find_option(sel, "scroll");
|
||||||
|
changeControlSelection();
|
||||||
|
break;
|
||||||
|
case "KeyW":
|
||||||
|
sel.selectedIndex = find_option(sel, "window");
|
||||||
|
changeControlSelection();
|
||||||
|
break;
|
||||||
|
case "KeyA":
|
||||||
|
sel.selectedIndex = find_option(sel, "abdomen");
|
||||||
|
changeControlSelection();
|
||||||
|
break;
|
||||||
|
case "KeyU":
|
||||||
|
sel.selectedIndex = find_option(sel, "pulmonary");
|
||||||
|
changeControlSelection();
|
||||||
|
break;
|
||||||
|
case "KeyB":
|
||||||
|
sel.selectedIndex = find_option(sel, "brain");
|
||||||
|
changeControlSelection();
|
||||||
|
break;
|
||||||
|
case "KeyO":
|
||||||
|
sel.selectedIndex = find_option(sel, "bone");
|
||||||
|
changeControlSelection();
|
||||||
|
break;
|
||||||
|
case "KeyE":
|
||||||
|
sel.selectedIndex = find_option(sel, "reset");
|
||||||
|
// $("#dicom-image").get(0).scrollIntoView(false);
|
||||||
|
changeControlSelection();
|
||||||
|
break;
|
||||||
|
// Escape and C do the same
|
||||||
|
case "KeyC":
|
||||||
|
case "Escape":
|
||||||
|
sel.selectedIndex = find_option(sel, "close");
|
||||||
|
changeControlSelection();
|
||||||
|
break;
|
||||||
|
case "Enter":
|
||||||
|
t.focus();
|
||||||
|
break;
|
||||||
|
// TODO: implement arrow stuff
|
||||||
|
//
|
||||||
|
case "ArrowUp": {
|
||||||
|
// Arrow function depends on the currently selected option
|
||||||
|
switch (sel.options[sel.selectedIndex].value) {
|
||||||
|
case "pan":
|
||||||
|
manualPanDicom(0, -1);
|
||||||
|
break;
|
||||||
|
case "zoom":
|
||||||
|
// _this.current_dicom.current_view.pre_scale_at(1.01, 1.01, _this.current_dicom.cols / 2, _this.current_dicom.rows / 2);
|
||||||
|
manualZoomDicom(1);
|
||||||
|
break;
|
||||||
|
case "rotate":
|
||||||
|
manualRotateDicom(-1);
|
||||||
|
break;
|
||||||
|
case "scroll":
|
||||||
|
manualScrollDicom(-1);
|
||||||
|
break;
|
||||||
|
case "window":
|
||||||
|
manualWindowDicom(1, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "ArrowDown": {
|
||||||
|
switch (sel.options[sel.selectedIndex].value) {
|
||||||
|
case "pan":
|
||||||
|
manualPanDicom(0, 1);
|
||||||
|
break;
|
||||||
|
case "zoom":
|
||||||
|
manualZoomDicom(-1);
|
||||||
|
break;
|
||||||
|
case "rotate":
|
||||||
|
manualRotateDicom(1);
|
||||||
|
break;
|
||||||
|
case "scroll":
|
||||||
|
manualScrollDicom(1);
|
||||||
|
break;
|
||||||
|
case "window":
|
||||||
|
manualWindowDicom(-1, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "ArrowLeft": {
|
||||||
|
switch (sel.options[sel.selectedIndex].value) {
|
||||||
|
case "pan":
|
||||||
|
manualPanDicom(-1, 0);
|
||||||
|
break;
|
||||||
|
case "zoom":
|
||||||
|
manualZoomDicom(-1);
|
||||||
|
break;
|
||||||
|
case "rotate":
|
||||||
|
manualRotateDicom(1);
|
||||||
|
break;
|
||||||
|
case "scroll":
|
||||||
|
manualScrollDicom(1);
|
||||||
|
break;
|
||||||
|
case "window":
|
||||||
|
manualWindowDicom(0, -1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "ArrowRight": {
|
||||||
|
switch (sel.options[sel.selectedIndex].value) {
|
||||||
|
case "pan":
|
||||||
|
manualPanDicom(1, 0);
|
||||||
|
break;
|
||||||
|
case "zoom":
|
||||||
|
manualZoomDicom(1);
|
||||||
|
break;
|
||||||
|
case "rotate":
|
||||||
|
manualRotateDicom(-1);
|
||||||
|
break;
|
||||||
|
case "scroll":
|
||||||
|
manualScrollDicom(-1);
|
||||||
|
break;
|
||||||
|
case "window":
|
||||||
|
manualWindowDicom(0, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* View cornstone image
|
||||||
|
* @param {*} t
|
||||||
|
* @param {*} source
|
||||||
|
*/
|
||||||
|
export function openMainImage(current_question, t, source) {
|
||||||
|
/**
|
||||||
|
* Load image
|
||||||
|
* @param {*} images - list of images
|
||||||
|
*/
|
||||||
|
async function load(images) {
|
||||||
|
const imageIds = [];
|
||||||
|
for (let i = 0; i < images.length; i++) {
|
||||||
|
const data_url = images[i];
|
||||||
|
// check stack type
|
||||||
|
if (data_url.startsWith("data:image")) {
|
||||||
|
const imageId = "base64://" + data_url.split(",")[1];
|
||||||
|
|
||||||
|
imageIds.push(imageId);
|
||||||
|
} else if (data_url.startsWith("data:application/dicom")) {
|
||||||
|
// stack = stack.split(";")[1];
|
||||||
|
|
||||||
|
const dfile = await helper.urltoFile(
|
||||||
|
data_url,
|
||||||
|
"dicom",
|
||||||
|
"application/dicom"
|
||||||
|
);
|
||||||
|
|
||||||
|
const imageId = cornerstoneWADOImageLoader.wadouri.fileManager.add(
|
||||||
|
dfile
|
||||||
|
);
|
||||||
|
imageIds.push(imageId);
|
||||||
|
// cornerstone.loadImage(imageId).then(function(image) {
|
||||||
|
// tempFunction(image);
|
||||||
|
// });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const stack = {
|
||||||
|
currentImageIdIndex: 0,
|
||||||
|
imageIds,
|
||||||
|
};
|
||||||
|
cornerstone.loadAndCacheImage(imageIds[0]).then(function (image) {
|
||||||
|
loadMainImage(image, stack);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current_question) {
|
||||||
|
// Check if the figure is already loaded (or if another one is)
|
||||||
|
const open_figure = $("#dicom-image").data("figure");
|
||||||
|
const figure_to_load = source.id;
|
||||||
|
|
||||||
|
if (open_figure != undefined) {
|
||||||
|
// No full size figure / dicom loaded yet
|
||||||
|
if (figure_to_load == open_figure) {
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
el = document.getElementById("dicom-image");
|
||||||
|
if (el != undefined) {
|
||||||
|
cornerstone.disable(el);
|
||||||
|
$(".canvas-panel").remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$(".figure-open").removeClass("figure-open").addClass("figure");
|
||||||
|
|
||||||
|
source.className = "figure-open";
|
||||||
|
|
||||||
|
$(".question").append(
|
||||||
|
'<div class= "canvas-panel"><div id="dicom-image" data-figure="' +
|
||||||
|
figure_to_load +
|
||||||
|
'"></div></div>'
|
||||||
|
);
|
||||||
|
|
||||||
|
let images = current_question.images[figure_to_load.split("-")[1]];
|
||||||
|
// images = current_question.images
|
||||||
|
|
||||||
|
// Make sure we have an array
|
||||||
|
if (!Array.isArray(images)) {
|
||||||
|
images = [images];
|
||||||
|
}
|
||||||
|
|
||||||
|
load(images);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user