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) {
|
||||
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
|
||||
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) {
|
||||
loadLocalQuestionSet();
|
||||
@@ -2004,3 +1766,6 @@ function saveSession() {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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