|
| 1 | +<!doctype html> |
| 2 | +<html class="h-100 overflow-hidden"> |
| 3 | + <head> |
| 4 | + <meta charset="UTF-8" /> |
| 5 | + |
| 6 | + <!-- Include the Larvitar script --> |
| 7 | + <script> |
| 8 | + // Check the host and set the script source dynamically |
| 9 | + const script = document.createElement("script"); |
| 10 | + if (window.location.host === "larvitar.dvisionlab.com") { |
| 11 | + document.write( |
| 12 | + '<script src="https://larvitar.dvisionlab.com/assets/larvitar.js"><\/script>' |
| 13 | + ); |
| 14 | + } else { |
| 15 | + document.write('<script src="../../dist/larvitar.js"><\/script>'); |
| 16 | + } |
| 17 | + // Append the script to the document |
| 18 | + document.head.appendChild(script); |
| 19 | + </script> |
| 20 | + |
| 21 | + <!-- Add the Bootstrap CSS and Prism CSS for code modal --> |
| 22 | + <link |
| 23 | + rel="stylesheet" |
| 24 | + href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" |
| 25 | + /> |
| 26 | + <link |
| 27 | + rel="stylesheet" |
| 28 | + href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/themes/prism-tomorrow.min.css" |
| 29 | + /> |
| 30 | + |
| 31 | + <!-- Include the CSS file --> |
| 32 | + <link rel="stylesheet" href="resources/styles.css" /> |
| 33 | + |
| 34 | + <!-- custom styles for the example --> |
| 35 | + <style></style> |
| 36 | + |
| 37 | + <!-- Add the Bootstrap JS and Prism JS for code modal --> |
| 38 | + <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js"></script> |
| 39 | + <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/prism.min.js"></script> |
| 40 | + <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-javascript.min.js"></script> |
| 41 | + |
| 42 | + <!-- Code to be displayed as source example code --> |
| 43 | + <!-- <script> |
| 44 | + document.addEventListener("DOMContentLoaded", () => { |
| 45 | + const showCodeBtn = document.getElementById("showCodeBtn"); |
| 46 | + const codeSnippet = document.getElementById("codeSnippet"); |
| 47 | + const copyCodeBtn = document.getElementById("copyCodeBtn"); |
| 48 | +
|
| 49 | + // TODO Code snippet to be displayed and updated for the example |
| 50 | + const code = ``; |
| 51 | +
|
| 52 | + // Show the modal and populate code snippet |
| 53 | + showCodeBtn.addEventListener("click", () => { |
| 54 | + codeSnippet.textContent = code; |
| 55 | + Prism.highlightElement(codeSnippet); // Highlight the code |
| 56 | + const codeModal = new bootstrap.Modal( |
| 57 | + document.getElementById("codeModal") |
| 58 | + ); |
| 59 | + codeModal.show(); |
| 60 | + }); |
| 61 | +
|
| 62 | + // Copy the code to clipboard |
| 63 | + copyCodeBtn.addEventListener("click", () => { |
| 64 | + navigator.clipboard.writeText(code); |
| 65 | + }); |
| 66 | + }); |
| 67 | + </script> --> |
| 68 | + |
| 69 | + <title>Larvitar - Filters</title> |
| 70 | + </head> |
| 71 | + |
| 72 | + <body class="h-100" style="background-color: #000000"> |
| 73 | + <div class="row h-100"> |
| 74 | + <div |
| 75 | + id="viewer" |
| 76 | + class="col-12 h-100" |
| 77 | + style="background-color: black" |
| 78 | + ></div> |
| 79 | + <p style="position: absolute; top: 0px; color: white"> |
| 80 | + Press "1" to remove filter |
| 81 | + </p> |
| 82 | + <p style="position: absolute; top: 20px; color: white"> |
| 83 | + Press "2" to apply filter |
| 84 | + </p> |
| 85 | + <!-- <button id="showCodeBtn" class="open-button" style="position: absolute; top: 165px"> |
| 86 | + Show Code |
| 87 | + </button> --> |
| 88 | + |
| 89 | + <!-- Modal --> |
| 90 | + <div |
| 91 | + class="modal fade" |
| 92 | + id="codeModal" |
| 93 | + tabindex="-1" |
| 94 | + aria-labelledby="codeModalLabel" |
| 95 | + aria-hidden="true" |
| 96 | + > |
| 97 | + <div class="modal-dialog modal-lg modal-dialog-centered"> |
| 98 | + <div class="modal-content"> |
| 99 | + <div class="modal-header"> |
| 100 | + <h5 class="modal-title" id="codeModalLabel">JavaScript Code</h5> |
| 101 | + <button |
| 102 | + type="button" |
| 103 | + class="btn-close" |
| 104 | + data-bs-dismiss="modal" |
| 105 | + aria-label="Close" |
| 106 | + ></button> |
| 107 | + </div> |
| 108 | + <div class="modal-body" style="max-height: 70vh; overflow-y: auto"> |
| 109 | + <pre><code id="codeSnippet" class="language-javascript"></code></pre> |
| 110 | + </div> |
| 111 | + <div class="modal-footer"> |
| 112 | + <button id="copyCodeBtn" class="btn btn-success"> |
| 113 | + Copy Code |
| 114 | + </button> |
| 115 | + <button |
| 116 | + type="button" |
| 117 | + class="btn btn-secondary" |
| 118 | + data-bs-dismiss="modal" |
| 119 | + > |
| 120 | + Close |
| 121 | + </button> |
| 122 | + </div> |
| 123 | + </div> |
| 124 | + </div> |
| 125 | + </div> |
| 126 | + |
| 127 | + <!-- Spinner icon --> |
| 128 | + <div id="spinner"></div> |
| 129 | + </div> |
| 130 | + |
| 131 | + <script> |
| 132 | + const spinner = document.getElementById("spinner"); |
| 133 | + |
| 134 | + // Show spinner |
| 135 | + function showSpinner() { |
| 136 | + spinner.style.display = "block"; |
| 137 | + } |
| 138 | + |
| 139 | + // Hide spinner |
| 140 | + function hideSpinner() { |
| 141 | + spinner.style.display = "none"; |
| 142 | + } |
| 143 | + |
| 144 | + // init all |
| 145 | + larvitar.initializeImageLoader(); |
| 146 | + larvitar.registerMultiFrameImageLoader(); |
| 147 | + larvitar.initializeCSTools(); |
| 148 | + larvitar.store.initialize(); |
| 149 | + larvitar.store.addViewport("viewer"); |
| 150 | + |
| 151 | + larvitar.addCustomKernel("sharpening.low.3", { |
| 152 | + Label: "Low", |
| 153 | + Size: 3, |
| 154 | + Kernel: [ |
| 155 | + [-1, -1, -1], |
| 156 | + [-1, 8, -1], |
| 157 | + [-1, -1, -1] |
| 158 | + ], |
| 159 | + modalities: ["CT", "MR"], |
| 160 | + type: "sharpening" |
| 161 | + }); |
| 162 | + |
| 163 | + // set log level to debug |
| 164 | + larvitar.setLogLevel("debug"); |
| 165 | + |
| 166 | + let demoFiles = []; |
| 167 | + |
| 168 | + showSpinner(); |
| 169 | + |
| 170 | + async function resetFilter(multiFrameSerie, frameId) { |
| 171 | + larvitar.store.setImageFilter("viewer", ""); |
| 172 | + const imageIds = Object.keys(multiFrameSerie.instances); |
| 173 | + const imageIdAtSlice = imageIds[frameId]; |
| 174 | + const imageInstance = multiFrameSerie.instances[imageIdAtSlice]; |
| 175 | + await larvitar.renderImage(multiFrameSerie, "viewer", { |
| 176 | + imageIndex: frameId, |
| 177 | + voi: { |
| 178 | + windowWidth: imageInstance.metadata.windowWidth, |
| 179 | + windowCenter: imageInstance.metadata.windowCenter |
| 180 | + } |
| 181 | + }); |
| 182 | + } |
| 183 | + |
| 184 | + async function applyFilter(multiFrameSerie, frameId) { |
| 185 | + await resetFilter(multiFrameSerie, frameId); |
| 186 | + |
| 187 | + const element = document.getElementById("viewer"); |
| 188 | + const image = larvitar.cornerstone.getEnabledElement(element)?.image; |
| 189 | + const filteredImage = larvitar.applyConvolutionFilter( |
| 190 | + image, |
| 191 | + "sharpening.low.3", |
| 192 | + true |
| 193 | + ); |
| 194 | + larvitar.store.setImageFilter(element.id, "sharpening.low.3"); |
| 195 | + larvitar.cornerstone.displayImage(element, filteredImage); |
| 196 | + larvitar.setImageCustomPreset(["viewer"], { |
| 197 | + ww: filteredImage.windowWidth, |
| 198 | + wl: filteredImage.windowCenter |
| 199 | + }); |
| 200 | + } |
| 201 | + |
| 202 | + async function renderSerie() { |
| 203 | + const seriesStack = await larvitar.readFiles(demoFiles); |
| 204 | + // render the first series of the study |
| 205 | + let seriesId = Object.keys(seriesStack)[0]; |
| 206 | + let serie = seriesStack[seriesId]; |
| 207 | + larvitar.populateImageManager(seriesId, serie); |
| 208 | + let manager = larvitar.getImageManager(); |
| 209 | + let multiFrameSerie = manager[seriesId]; |
| 210 | + |
| 211 | + let frameId = 0; |
| 212 | + await larvitar.renderImage(multiFrameSerie, "viewer", { |
| 213 | + imageIndex: frameId |
| 214 | + }); |
| 215 | + hideSpinner(); |
| 216 | + larvitar.logger.debug("Image has been rendered"); |
| 217 | + |
| 218 | + larvitar.addDefaultTools("viewer"); |
| 219 | + larvitar.setToolActive("Wwwc"); |
| 220 | + |
| 221 | + await larvitar.loadAndCacheImageStack(multiFrameSerie); |
| 222 | + |
| 223 | + document.onkeypress = function (e) { |
| 224 | + e = e || window.event; |
| 225 | + switch (e.keyCode) { |
| 226 | + case 49: // 1 |
| 227 | + resetFilter(multiFrameSerie, frameId); |
| 228 | + break; |
| 229 | + case 50: // 2 |
| 230 | + applyFilter(multiFrameSerie, frameId); |
| 231 | + break; |
| 232 | + } |
| 233 | + }; |
| 234 | + } |
| 235 | + |
| 236 | + async function createFile(fileName, cb) { |
| 237 | + let response = await fetch("./demo/DSA/" + fileName); |
| 238 | + let data = await response.blob(); |
| 239 | + let file = new File([data], fileName); |
| 240 | + demoFiles.push(file); |
| 241 | + cb(); |
| 242 | + } |
| 243 | + |
| 244 | + createFile("XA-DSA-Shutter.dcm", renderSerie); |
| 245 | + </script> |
| 246 | + </body> |
| 247 | +</html> |
0 commit comments