Retrieve and Display DICOM JSON from WADO Service - HTML5 JavaScript

This tutorial shows how to retrieve and display a DICOM JSON file from the LEADTOOLS WADO Service API in an HTML5 JavaScript application.

Overview  
Summary This tutorial covers how to retrieve DICOM JSON files and display them in an HTML5 JavaScript application.
Completion Time 30 minutes
Visual Studio Project Download tutorial project (10 KB)
Platform JS Web Application
IDE Visual Studio Code - Client
Development License Download LEADTOOLS

Required Knowledge

Get familiar with the basic steps of creating a project and configuring the LEADTOOLS DicomWeb WADO Service by reviewing the Add References and Set a License and Configure and Run the LEADTOOLS DicomWeb WADO Service tutorials.

Create the Project and Add the LEADTOOLS References

Start with the project created in the Add References and Set a License tutorial. If this project is unavailable, follow the steps in that tutorials to create it.

You will need the following files in the project folder, most of which are created in the tutorial referenced above.

The references needed depend upon the purpose of the project. This tutorial requires the following JS files:

They can be found here: <INSTALL_DIR>\LEADTOOLS23\Bin\JS

Make sure to copy the JS files to the lib folder and to import them in the index.html file.

Set the License File

The License unlocks the features needed for the project. It must be set before any toolkit function is called. For details including tutorials for different platforms, refer to Setting a Runtime License.

There are two types of runtime licenses:

Write the HTML and CSS Files

Open your project's index.html file. Ensure the below code is added to import the LEADTOOLS dependencies, LEADTOOLS logic, and set the container for the Medical Viewer.

Note

For this tutorial the LEADTOOLS DicomWeb WADO Service is running on http://localhost/WadoService/ . Change this path name to use the path that the LEADTOOLS DicomWeb WADO Service is using locally.

<!DOCTYPE html> 
<html lang="en"> 
  <head> 
    <meta charset="utf-8" /> 
    <title>LEADTOOLS Medical WebViewer Tutorial</title> 
 
    <script type="text/javascript" src="dicomWeb.js"></script> 
    <script type="text/javascript" src="query.js"></script> 
    <script type="text/javascript" src="app.js"></script> 
    <script type="text/javascript" src="toolbar.js"></script> 
 
    <script> 
      // Set your LEADTOOLS DicomWeb service url here. 
      const dicomWeb_url = "http://localhost/WadoService/api"; 
    </script> 
 
    <link rel="stylesheet" type="text/css" href="index.css" /> 
 
    <!-- LEADTOOLS Libraries --> 
    <script type="text/javascript" src="lib/Leadtools.js"></script> 
    <script type="text/javascript" src="lib/Leadtools.Controls.js"></script> 
    <script 
      type="text/javascript" 
      src="lib/Leadtools.Annotations.Engine.js" 
    ></script> 
    <script 
      type="text/javascript" 
      src="lib/Leadtools.Annotations.Designers.js" 
    ></script> 
    <script 
      type="text/javascript" 
      src="lib/Leadtools.Annotations.Rendering.JavaScript.js" 
    ></script> 
    <script 
      type="text/javascript" 
      src="lib/Leadtools.Annotations.Automation.js" 
    ></script> 
    <script 
      type="text/javascript" 
      src="lib/Leadtools.Controls.Medical.js" 
    ></script> 
  </head> 
 
  <body> 
    <div id="query"> 
      <div class="card"> 
        <div class="query-parameter"> 
          <label for="queryParamPatientID">Patient ID:</label> 
          <input type="text" id="queryParamPatientID" /> 
        </div> 
 
        <div class="query-parameter"> 
          <label for="queryParamPatientName">PatientName:</label> 
          <input type="text" id="queryParamPatientName" /> 
        </div> 
 
        <button class="button" onclick="search()">Search</button> 
        <button class="button" onclick="clearSearch()">Clear</button> 
      </div> 
 
      <div class="query-results card"> 
        <fieldset class="group"> 
          <legend>Studies</legend> 
          <table id="studyResults"> 
            <thead> 
              <th scope="col">Patient ID</th> 
              <th scope="col">Patient Name</th> 
              <th scope="col">Accession Number</th> 
              <th scope="col">Study Date</th> 
              <th scope="col">Study Description</th> 
              <th scope="col">Study Instance UID</th> 
            </thead> 
            <tbody></tbody> 
          </table> 
        </fieldset> 
 
        <fieldset class="group"> 
          <legend>Studies</legend> 
          <table id="seriesResults"> 
            <thead> 
              <th scope="col">Series Number</th> 
              <th scope="col">Series Date</th> 
              <th scope="col">Series Description</th> 
              <th scope="col">Modality</th> 
              <th scope="col">Study Instance UID</th> 
              <th scope="col">Series Instance UID</th> 
            </thead> 
            <tbody></tbody> 
          </table> 
        </fieldset> 
      </div> 
    </div> 
 
    <div id="viewer"> 
      <div id="toolbar" class="card"> 
        <fieldset class="group"> 
          <legend>Search</legend> 
          <button id="Search" class="button" onclick="showSearch()"> 
            Search 
          </button> 
        </fieldset> 
 
        <fieldset class="group"> 
          <legend>Interactive Actions</legend> 
          <button id="windowLevel" class="button" onclick="windowLevel()"> 
            window Level 
          </button> 
          <button id="Offset" class="button" onclick="offset()">Offset</button> 
          <button id="Scale" class="button" onclick="scale()">Scale</button> 
          <button id="Scale" class="button" onclick="stack()">Stack</button> 
          <button id="SpyGlass" class="button" onclick="spy()">Spy</button> 
          <button id="ProbeTool" class="button" onclick="probe()">Probe</button> 
        </fieldset> 
 
        <fieldset class="group"> 
          <legend>Image View</legend> 
          <button id="Fit" class="button" onclick="fit()">Fit</button> 
          <button id="OneToOne" class="button" onclick="oneToOne()"> 
            1 - 1 
          </button> 
          <button id="ZoomIn" class="button" onclick="zoomIn()">Zoom In</button> 
          <button id="ZoomOut" class="button" onclick="zoomOut()"> 
            Zoom Out 
          </button> 
          <button id="RotateClockWise" class="button" onclick="rotate()"> 
            Rotate 
          </button> 
          <button 
            id="RotateCounterClockWise" 
            class="button" 
            onclick="rotateCC()" 
          > 
            Rotate CC 
          </button> 
          <button id="Flip" class="button" onclick="flip()">Flip</button> 
          <button id="Reverse" class="button" onclick="reverse()"> 
            Reverse 
          </button> 
          <button id="Invert" class="button" onclick="invert()">Invert</button> 
          <button id="AlignLeft" class="button" onclick="alignLeft()"> 
            Left 
          </button> 
          <button id="AlignTop" class="button" onclick="alignTop()">Top</button> 
        </fieldset> 
 
        <fieldset class="group"> 
          <legend>Annotations</legend> 
          <button id="Rectangle" class="button" onclick="rect()">Rect</button> 
          <button id="Circle" class="button" onclick="circle()">Circle</button> 
          <button id="Arrow" class="button" onclick="arrow()">Arrow</button> 
          <button id="Ruler" class="button" onclick="ruler()">Ruler</button> 
          <button id="Highlight" class="button" onclick="highlight()"> 
            Highlight 
          </button> 
        </fieldset> 
 
        <fieldset class="group"> 
          <legend>Other</legend> 
          <button id="Overlay" class="button" onclick="overlay()"> 
            Overlay 
          </button> 
          <button id="Reload" class="button" onclick="reload()">Reload</button> 
          <button id="Cine" class="button" onclick="cine()">Cine</button> 
          <button id="Explode" class="button" onclick="explode()"> 
            Explode 
          </button> 
          <button id="CTR" class="button" onclick="ctr()">CTR</button> 
        </fieldset> 
      </div> 
 
      <div id="viewer-control" class="med-viewer"></div> 
    </div> 
  </body> 
</html> 

Additionally, open your project's index.css file. Ensure the below code is added to update the visuals.

/*  
 * Global variables 
 */ 
:root { 
  --color-primary: hsl(220, 99%, 61%); 
  --color-secondary: #e4f0f5; 
  --color-highlight: hsl(250, 75%, 50%); 
  --color-text: white; 
  --color-background: rgb(70, 67, 67); 
  --color-background-2: hsla(220, 75%, 61%); 
 
  --color-table-row-bg: hsl(220, 45%, 76%); 
  --color-table-row-highlight: #ffff99; 
  --color-table-row-text: black; 
 
  --color-table-header-bg: var(--color-primary); 
  --color-table-header-text: var(--color-text); 
  --color-table-border: black; 
 
  --radius: 0.25rem; 
} 
 
/*  
 * General Styles 
 */ 
*::before, 
*::after { 
  box-sizing: border-box; 
} 
 
html, 
body { 
  margin: 0; 
  padding: 0; 
  background-color: var(--color-background); 
  color: var(--color-text); 
  width: 100%; 
  height: 100%; 
  display: flex; 
  flex-direction: column; 
  box-sizing: border-box; 
} 
 
body { 
  padding: 1rem; 
} 
 
/* 
 * General 'Element' Style 
 */ 
 
/* Card */ 
.card { 
  background-color: var(--color-primary); 
  border: 1px solid var(--color-highlight); 
  border-radius: var(--radius); 
  padding: 1rem; 
  width: 100%; 
  box-sizing: border-box; 
} 
 
/* Group */ 
.group { 
  display: flex; 
  gap: 0.5rem; 
  border: unset; 
  border: 1px solid var(--color-highlight); 
  border-radius: var(--radius); 
  margin: 0; 
  background-color: var(--color-background-2); 
} 
 
.group > legend { 
  color: var(--color-text); 
  user-select: none; 
} 
 
/* Button */ 
.button { 
  all: unset; 
  border: 1px solid var(--color-secondary); 
  border-radius: var(--radius); 
  background-color: var(--color-background-2); 
  color: var(--color-text); 
  padding: 0.25rem; 
  user-select: none; 
} 
 
.button:hover { 
  filter: saturate(50%); 
} 
 
.button:active { 
  scale: 1.1; 
} 
 
/*  
* Viewer Styles 
*/ 
#viewer { 
  width: 100%; 
  height: 100%; 
  flex-grow: 1; 
  display: flex; 
  flex-direction: column; 
  gap: 1rem; 
} 
 
#viewer-control { 
  width: 100%; 
  height: 100%; 
  flex-grow: 1; 
  position: relative; 
  border: 1px solid var(--color-highlight); 
  background-color: black; 
} 
 
/*  
* Query Styles 
*/ 
#query { 
  display: flex; 
  flex-direction: column; 
  gap: 1rem; 
} 
 
.query-parameter { 
  display: flex; 
  justify-content: space-between; 
} 
 
.query-parameter > input { 
  width: clamp(10%, 75%, 100%); 
} 
 
.query-results { 
  display: flex; 
  flex-direction: column; 
  gap: 1rem; 
} 
 
/*  
 * Toolbar Style 
 */ 
#toolbar { 
  width: 100%; 
  display: flex; 
  flex-wrap: wrap; 
  gap: 0.5rem; 
  padding: 0.5rem; 
} 
 
/*  
 * Table Styles 
 */ 
 
table { 
  border-collapse: collapse; 
  border: 2px solid var(--color-table-border); 
  letter-spacing: 1px; 
  font-family: sans-serif; 
  font-size: 0.8rem; 
  width: 100%; 
} 
 
table tbody tr:hover { 
  background-color: var(--color-table-row-highlight); 
  color: var(--color-background); 
  cursor: pointer; 
} 
 
tr { 
  color: var(--color-table-row-text); 
  background-color: var(--color-table-row-bg); 
} 
 
th { 
  color: var(--color-table-header-text); 
  background-color: var(--color-table-header-bg); 
} 
 
td, 
th { 
  border: 1px solid var(--color-background); 
} 
 
td { 
  text-align: center; 
} 

Write the JS Files

app.js

Open your project's app.js file. Input the code below to create the MedicalViewer.

let viewer; 
 
window.onload = () => { 
  setLicense(); 
  initViewer(); 
  showSearch(); 
}; 
 
function showViewer() { 
  document.getElementById("viewer").style.display = ""; 
  document.getElementById("query").style.display = "none"; 
} 
 
function showSearch() { 
  document.getElementById("viewer").style.display = "none"; 
  document.getElementById("query").style.display = ""; 
} 
 
function initViewer() { 
  // Get the parent DIV 
  let imageViewerDiv = document.getElementById("viewer-control"); 
 
  // Create the medical viewer control, and specify the number of rows and columns. 
  viewer = new lt.Controls.Medical.MedicalViewer(imageViewerDiv, 1, 1); 
 
  viewer.set_enableLazyLoad(true); //enable lazy loading 
  viewer.set_marginFramesCount(5); 
 
  // Add callbacks 
  viewer.add_loadMetadata(async (sender, args) => { 
    args.frame.JSON = await retrieveInstanceMetadata( 
      args.studyInstanceUID, 
      args.seriesInstanceUID, 
      args.sopInstanceUID 
    ); 
  }); 
 
  viewer.add_loadInstance(async (sender, args) => { 
    args.frame.pixelData = await retrieveFrameData( 
      args.studyInstanceUID, 
      args.seriesInstanceUID, 
      args.sopInstanceUID, 
      0 
    ); 
  }); 
} 
 
function getSelectedCells() { 
  return viewer.layout.selectedItems.toArray(); 
} 
 
// Optional 
const initOverlay = () => { 
  viewer.layout.cells.toArray().forEach((cell) => { 
    cell.set_overlayTextVisible(true); 
 
    // [optional] Select the cell (it can also be selected by clicking on it.) 
    cell.set_selected(true); 
 
    // [optional] Create an overlay text that will appear at the top of the loaded image. 
    const overlay = new lt.Controls.Medical.OverlayText(); 
 
    // [optional] Set the alignment for the overlay text. 
    overlay.set_alignment(lt.Controls.Medical.Alignment.topLeft); 
 
    // [optional] Set the row index of overlay text. 
    overlay.set_positionIndex(0); 
 
    // [optional] add window level overlay text, this will change when you click and drag the mouse. 
    overlay.set_type(lt.Controls.Medical.OverlayTextType.windowLevel); 
 
    // [optional] Add this overlay to the overlay list of the cell. Currently there is only one overlay, but the user can add multiple overlay texts. 
    cell.get_overlays().add(overlay); 
  }); 
}; 
 
async function loadSeries(studyID, seriesUID) { 
  var seriesMetadata = await retrieveSeriesMetadata(studyID, seriesUID); 
  viewer.layout.cells.clear(); 
  viewer.load(seriesMetadata); 
  initOverlay(); 
} 

dicomWeb.js

Next, open your project's dicomWeb.js file. Input the code below.

/* 
 * Refer to DICOM PS3.18 2022d - Web Services 
 */ 
 
const headerOptions = { 
  headers: { 
    Accept: "application/dicom+json", 
  }, 
}; 
 
const queryPatients = async (queryParams) => { 
  const params = Object.keys(queryParams) 
    .map((key) => key + "=" + queryParams[key]) 
    .join("&"); 
  const response = await fetch( 
    `${dicomWeb_url}/qido-rs/patients?${params}`, 
    headerOptions 
  ); 
  const data = await response.json(); 
 
  return data; 
}; 
 
const queryStudies = async (queryParams) => { 
  const params = Object.keys(queryParams) 
    .map((key) => key + "=" + queryParams[key]) 
    .join("&"); 
  const response = await fetch( 
    `${dicomWeb_url}/qido-rs/studies?${params}`, 
    headerOptions 
  ); 
  const data = await response.json(); 
 
  return data; 
}; 
 
const querySeries = async (studyUID) => { 
  const response = await fetch( 
    `${dicomWeb_url}/qido-rs/studies/${studyUID}/series`, 
    headerOptions 
  ); 
  const data = await response.json(); 
  return data; 
}; 
 
const queryInstances = async (studyUID, seriesUID) => { 
  const url = `${dicomWeb_url}/qido-rs/studies/${studyUID}/series/${seriesUID}/instances`; 
  const response = await fetch(url, headerOptions); 
  const data = await response.json(); 
 
  return data; 
}; 
 
const retrieveSeriesMetadata = async (studyUID, seriesUID) => { 
  const url = `${dicomWeb_url}/wado-rs/studies/${studyUID}/series/${seriesUID}/metadata`; 
  const response = await fetch(url, headerOptions); 
  const data = await response.json(); 
 
  return data; 
}; 
 
const retrieveInstanceMetadata = async (studyUID, seriesUID, instanceUID) => { 
  const url = `${dicomWeb_url}/wado-rs/studies/${studyUID}/series/${seriesUID}/instances/${instanceUID}/metadata`; 
  const response = await fetch(url, headerOptions); 
  const data = await response.json(); 
 
  return data?.[0]; 
}; 
 
const trimMultipartHeader = async (response) => { 
  const blob = await response.blob(); 
 
  const ct = response.headers.get("content-type"); 
  const isMultipartRelated = ct?.toLowerCase().includes("multipart/related"); 
  const boundary = new RegExp("boundary=[\"|'](.*)[\"|']", "i").exec(ct)?.[1]; 
 
  if (!isMultipartRelated || !boundary) return await blob.arrayBuffer(); 
 
  const text = await blob.text(); 
 
  const newLine = "\\r?\\n"; 
  const header = new RegExp(`--${boundary}[\\s\\S]*?${newLine}${newLine}`).exec( 
    text 
  )?.[0]; 
  const footer = new RegExp( 
    `${newLine}${newLine}[\\s\\S]*?([${newLine}]*?--${boundary}--)` 
  ).exec(text)?.[1]; 
 
  const te = new TextEncoder(); 
  const newBlob = await blob.slice( 
    te.encode(header).length, 
    blob.arrayBuffer.length - te.encode(footer).length 
  ); 
 
  return await newBlob.arrayBuffer(); 
}; 
 
const retrieveFrameData = async ( 
  studyUID, 
  seriesUID, 
  instanceUID, 
  frameNumber 
) => { 
  const url = `${dicomWeb_url}/wado-rs/studies/${studyUID}/series/${seriesUID}/instances/${instanceUID}/frames/${frameNumber}`; 
  const response = await fetch(url, { 
    headers: { 
      accept: 'multipart/related; type="application/octet-stream"', 
    }, 
  }); 
 
  let data = await trimMultipartHeader(response); 
 
  return new Uint8Array(data); 
}; 

query.js

Next, open your project's query.js file. Input the code below to parse the query results into the frontend table.

/* 
 * Updates the results query results table in index.html 
 * Refer to PS3.18 2022d - F.2 DICOM JSON Model 
 */ 
 
async function removeResults(tableID) { 
  const table = document.getElementById(tableID); 
  const tbody = table.getElementsByTagName("tbody")[0]; 
 
  // Remove existing results. 
  while (tbody.firstChild) tbody.removeChild(tbody.lastChild); 
} 
 
const updateSeriesResults = async (series) => { 
  removeResults("seriesResults"); 
 
  let table = document.getElementById("seriesResults"); 
  let tbody = table.getElementsByTagName("tbody")[0]; 
 
  if (!tbody) { 
    tbody = document.createElement("tbody"); 
    table.appendChild(tbody); 
  } 
 
  series.forEach((series) => { 
    let seriesNumber = series["00200011"]["Value"]; 
 
    let seriesDate = series?.["00080021"]?.["Value"] ?? ""; 
    let seriesDescription = series?.["0008103E"]?.["Value"] ?? ""; 
    let modality = series?.["00080060"]?.["Value"]; 
    let studyUID = series?.["0020000D"]?.["Value"]?.[0]; 
    let seriesUID = series?.["0020000E"]?.["Value"]?.[0]; 
 
    let row = tbody.insertRow(0); 
    row.insertCell(0).innerHTML = seriesUID; 
    row.insertCell(0).innerHTML = studyUID; 
    row.insertCell(0).innerHTML = modality; 
    row.insertCell(0).innerHTML = seriesDescription; 
    row.insertCell(0).innerHTML = seriesDate; 
    row.insertCell(0).innerHTML = seriesNumber; 
 
    row.onclick = () => { 
      showViewer(); 
      loadSeries(studyUID, seriesUID); 
    }; 
  }); 
}; 
 
const updateStudyResults = (studies) => { 
  removeResults("studyResults"); 
  removeResults("seriesResults"); 
 
  const table = document.getElementById("studyResults"); 
 
  let tbody = table.getElementsByTagName("tbody")[0]; 
  if (!tbody) { 
    tbody = document.createElement("tbody"); 
    table.appendChild(tbody); 
  } 
 
  studies.forEach((study) => { 
    const patientID = study?.["00100020"]?.["Value"]; 
    const patientName = 
      study?.["00100010"]?.["Value"]?.[0]?.["Alphabetic"] ?? ""; 
    const accessionNumber = study?.["00080050"]?.["Value"] ?? ""; 
    const studyDate = study?.["00080020"]?.["Value"]?.[0] ?? ""; 
    const studyDescription = study?.["00081030"]?.["Value"] ?? ""; 
    const studyUID = study?.["0020000D"]?.["Value"]?.[0]; 
 
    const row = tbody.insertRow(0); 
    row.insertCell(0).innerHTML = studyUID; 
    row.insertCell(0).innerHTML = studyDescription; 
    row.insertCell(0).innerHTML = studyDate; 
    row.insertCell(0).innerHTML = accessionNumber; 
    row.insertCell(0).innerHTML = patientName; 
    row.insertCell(0).innerHTML = patientID; 
 
    row.onclick = async () => { 
      let series = await querySeries(studyUID); 
      updateSeriesResults(series); 
    }; 
  }); 
}; 
 
const search = async () => { 
  let studies = await queryStudies({ 
    PatientID: document.getElementById("queryParamPatientID").value, 
    PatientName: document.getElementById("queryParamPatientName").value, 
  }); 
 
  updateStudyResults(studies); 
}; 
 
const clearSearch = () => { 
  removeResults("studyResults"); 
  removeResults("seriesResults"); 
 
  document.getElementById("queryParamPatientID").value = ""; 
  document.getElementById("queryParamPatientName").value = ""; 
}; 

toolbar.js

Finally, open your project's toolbar.js file. Input the below code to enable all of the interactive/annotation actions that can be used.

const actionID = { 
  // Interactive actions. 
  windowLevel: 1, 
  offset: 2, 
  scale: 3, 
  stack: 4, 
  spy: 5, 
  probe: 6, 
 
  // Annotation actions. 
  rect: 7, 
  circle: 8, 
  arrow: 9, 
  ruler: 10, 
  highlight: 11, 
}; 
 
function windowLevel() { 
  getSelectedCells().forEach((c) => { 
    if (!c.actions.lookup[actionID.windowLevel]) 
      c.actions.add( 
        new lt.Controls.Medical.WindowLevelAction(actionID.windowLevel) 
      ); 
 
    c.actions.lookup[actionID.windowLevel].run(null); 
  }); 
} 
 
function offset() { 
  getSelectedCells().forEach((c) => { 
    if (!c.actions.lookup[actionID.offset]) 
      c.actions.add(new lt.Controls.Medical.OffsetAction(actionID.offset)); 
 
    c.actions.lookup[actionID.offset].run(null); 
  }); 
} 
 
function scale() { 
  getSelectedCells().forEach((c) => { 
    if (!c.actions.lookup[actionID.scale]) 
      c.actions.add(new lt.Controls.Medical.ScaleAction(actionID.scale)); 
 
    c.actions.lookup[actionID.scale].run(null); 
  }); 
} 
 
function stack() { 
  getSelectedCells().forEach((c) => { 
    if (!c.actions.lookup[actionID.stack]) 
      c.actions.add(new lt.Controls.Medical.StackAction(actionID.stack, c)); 
 
    c.actions.lookup[actionID.stack].run(null); 
  }); 
} 
 
function spy() { 
  getSelectedCells().forEach((c) => { 
    if (!c.actions.lookup[actionID.spy]) 
      c.actions.add(new lt.Controls.Medical.SpyGlassAction(actionID.spy)); 
 
    c.actions.lookup[actionID.spy].run(null); 
  }); 
} 
 
function probe() { 
  getSelectedCells().forEach((c) => { 
    if (!c.actions.lookup[actionID.probe]) 
      c.actions.add(new lt.Controls.Medical.ProbeToolAction(actionID.probe, c)); 
 
    c.actions.lookup[actionID.probe].run(null); 
  }); 
} 
 
function ctr() { 
  getSelectedCells().forEach((c) => { 
    c.drawables["CTRTool"] = new lt.Controls.Medical.CTRTool( 
      c.selectedItem.attachedFrame 
    ); 
    c.invalidate(null); 
  }); 
} 
 
function rect() { 
  getSelectedCells().forEach((c) => { 
    if (!c.actions.lookup[actionID.rect]) 
      c.actions.add( 
        new lt.Controls.Medical.AutomationInteractiveAction( 
          actionID.rect, 
          lt.Annotations.Engine.AnnObject.rectangleObjectId, 
          c.automation 
        ) 
      ); 
 
    c.actions.lookup[actionID.rect].run(null); 
  }); 
} 
 
function circle() { 
  getSelectedCells().forEach((c) => { 
    if (!c.actions.lookup[actionID.circle]) 
      c.actions.add( 
        new lt.Controls.Medical.AutomationInteractiveAction( 
          actionID.circle, 
          lt.Annotations.Engine.AnnObject.ellipseObjectId, 
          c.automation 
        ) 
      ); 
 
    c.actions.lookup[actionID.circle].run(null); 
  }); 
} 
 
function arrow() { 
  getSelectedCells().forEach((c) => { 
    if (!c.actions.lookup[actionID.arrow]) 
      c.actions.add( 
        new lt.Controls.Medical.AutomationInteractiveAction( 
          actionID.arrow, 
          lt.Annotations.Engine.AnnObject.pointerObjectId, 
          c.automation 
        ) 
      ); 
 
    c.actions.lookup[actionID.arrow].run(null); 
  }); 
} 
 
function ruler() { 
  getSelectedCells().forEach((c) => { 
    if (!c.actions.lookup[actionID.ruler]) 
      c.actions.add( 
        new lt.Controls.Medical.AutomationInteractiveAction( 
          actionID.ruler, 
          lt.Annotations.Engine.AnnObject.rulerObjectId, 
          c.automation 
        ) 
      ); 
 
    c.actions.lookup[actionID.ruler].run(null); 
  }); 
} 
 
function highlight() { 
  getSelectedCells().forEach((c) => { 
    if (!c.actions.lookup[actionID.highlight]) 
      c.actions.add( 
        new lt.Controls.Medical.AutomationInteractiveAction( 
          actionID.highlight, 
          lt.Annotations.Engine.AnnObject.hiliteObjectId, 
          c.automation 
        ) 
      ); 
 
    c.actions.lookup[actionID.highlight].run(null); 
  }); 
} 
 
function fit() { 
  getSelectedCells().forEach((c) => { 
    c.zoom(lt.Controls.Medical.MedicalViewerSizeMode.fit, 1); 
  }); 
} 
 
function oneToOne() { 
  getSelectedCells().forEach((c) => { 
    c.zoom(lt.Controls.Medical.MedicalViewerSizeMode.actualSize, 1); 
  }); 
} 
 
function zoomIn() { 
  getSelectedCells().forEach((c) => { 
    c.zoom(c.get_scaleMode(), c.get_scale() * 2); 
  }); 
} 
 
function zoomOut() { 
  getSelectedCells().forEach((c) => { 
    c.zoom(c.get_scaleMode(), c.get_scale() / 2); 
  }); 
} 
 
function rotate() { 
  getSelectedCells().forEach((c) => { 
    c.set_rotateAngle(c.get_rotateAngle() + 90); 
  }); 
} 
 
function rotateCC() { 
  getSelectedCells().forEach((c) => { 
    c.set_rotateAngle(c.get_rotateAngle() - 90); 
  }); 
} 
 
function flip() { 
  getSelectedCells().forEach((c) => { 
    c.set_flipped(!c.get_flipped()); 
  }); 
} 
 
function reverse() { 
  getSelectedCells().forEach((c) => { 
    c.set_reversed(!c.get_reversed()); 
  }); 
} 
 
function invert() { 
  getSelectedCells().forEach((c) => { 
    c.set_inverted(!c.get_inverted()); 
  }); 
} 
 
function alignLeft() { 
  getSelectedCells().forEach((c) => { 
    c.horizontalAlignment = lt.Controls.Medical.HorizontalAlignmentType.left; 
  }); 
} 
 
function alignTop() { 
  getSelectedCells().forEach((c) => { 
    c.verticalAlignment = lt.Controls.Medical.VerticalAlignmentType.top; 
  }); 
} 
 
function overlay() { 
  getSelectedCells().forEach((c) => { 
    c.set_overlayTextVisible(!c.get_overlayTextVisible()); 
  }); 
} 
 
function reload() { 
  getSelectedCells().forEach((c) => { 
    c.reset(); 
  }); 
} 
 
function cine() { 
  getSelectedCells().forEach((c) => { 
    if (c.cinePlayer.isPlaying) c.cinePlayer.stop(); 
    else c.cinePlayer.play(); 
  }); 
} 
 
function explode() { 
  getSelectedCells().forEach((c) => { 
    c.viewer.set_exploded(!c.viewer.get_exploded()); 
  }); 
} 

Run the Project

Ensure that the LEADTOOLS DicomWeb WADO Service is configured and running first.

Open the command line console, then cd into the root of the project. Use the following command to run a static file server:

http-server .

The server should start and run on http:localhost:8080. A message should appear in the console indicating all the ports that the server is available on. Open your browser and navigate to:

http://localhost:8080/index.html

Wrap-up

This tutorial showed how to retrieve and display DICOM JSON files from the WADO Service API in a JavaScript MedicalViewer object.

See Also

Help Version 23.0.2024.5.22
Products | Support | Contact Us | Intellectual Property Notices
© 1991-2024 LEAD Technologies, Inc. All Rights Reserved.

Products | Support | Contact Us | Intellectual Property Notices
© 1991-2023 LEAD Technologies, Inc. All Rights Reserved.