UNPKG

@cornerstonejs/core

Version:
114 lines (113 loc) 4.86 kB
import { vec3 } from 'gl-matrix'; import getOrCreateCanvas, { EPSILON, } from '../RenderingEngine/helpers/getOrCreateCanvas.js'; import { ViewportType, Events } from '../enums/index.js'; import { getRenderingEngine } from '../RenderingEngine/getRenderingEngine.js'; import TiledRenderingEngine from '../RenderingEngine/TiledRenderingEngine.js'; import isPTPrescaledWithSUV from './isPTPrescaledWithSUV.js'; export default function renderToCanvasGPU(canvas, imageOrVolume, modality = undefined, renderingEngineId = '_thumbnails', viewportOptions = { displayArea: { imageArea: [1, 1] }, }) { if (!canvas || !(canvas instanceof HTMLCanvasElement)) { throw new Error('canvas element is required'); } const isVolume = !imageOrVolume.imageId; const image = !isVolume && imageOrVolume; const volume = isVolume && imageOrVolume; const imageIdToPrint = image.imageId || volume.volumeId; const viewportId = `renderGPUViewport-${imageIdToPrint}`; const element = document.createElement('div'); const devicePixelRatio = window.devicePixelRatio || 1; if (!viewportOptions.displayArea) { viewportOptions.displayArea = { imageArea: [1, 1] }; } const originalWidth = canvas.width; const originalHeight = canvas.height; element.style.width = `${originalWidth / devicePixelRatio + EPSILON}px`; element.style.height = `${originalHeight / devicePixelRatio + EPSILON}px`; element.style.visibility = 'hidden'; element.style.position = 'absolute'; document.body.appendChild(element); const uniqueId = viewportId.split(':').join('-'); element.setAttribute('viewport-id-for-remove', uniqueId); const temporaryCanvas = getOrCreateCanvas(element); const renderingEngine = getRenderingEngine(renderingEngineId) || new TiledRenderingEngine(renderingEngineId); let viewport = renderingEngine.getViewport(viewportId); if (!viewport) { const viewportInput = { viewportId, type: isVolume ? ViewportType.ORTHOGRAPHIC : ViewportType.STACK, element, defaultOptions: { ...viewportOptions, suppressEvents: true, }, }; renderingEngine.enableElement(viewportInput); viewport = renderingEngine.getViewport(viewportId); } return new Promise((resolve) => { let elementRendered = false; let { viewReference } = viewportOptions; const onImageRendered = (eventDetail) => { if (elementRendered) { return; } if (viewReference) { const useViewRef = viewReference; viewReference = null; viewport.setViewReference(useViewRef); viewport.render(); return; } const context = canvas.getContext('2d'); context.drawImage(temporaryCanvas, 0, 0, temporaryCanvas.width, temporaryCanvas.height, 0, 0, canvas.width, canvas.height); const origin = viewport.canvasToWorld([0, 0]); const topRight = viewport.canvasToWorld([ temporaryCanvas.width / devicePixelRatio, 0, ]); const bottomLeft = viewport.canvasToWorld([ 0, temporaryCanvas.height / devicePixelRatio, ]); const rightVector = vec3.sub([0, 0, 0], viewport.canvasToWorld([1 / devicePixelRatio, 0]), origin); const downVector = vec3.sub([0, 0, 0], viewport.canvasToWorld([0, 1 / devicePixelRatio]), origin); const thicknessMm = 1; elementRendered = true; element.removeEventListener(Events.IMAGE_RENDERED, onImageRendered); setTimeout(() => { renderingEngine.disableElement(viewportId); const elements = document.querySelectorAll(`[viewport-id-for-remove="${uniqueId}"]`); elements.forEach((element) => { element.remove(); }); }, 0); resolve({ origin, bottomLeft, topRight, thicknessMm, rightVector, downVector, }); }; element.addEventListener(Events.IMAGE_RENDERED, onImageRendered); if (isVolume) { viewport.setVolumes([volume], false, true); } else { viewport.renderImageObject(imageOrVolume); } viewport.resetCamera(); if (modality === 'PT' && !isPTPrescaledWithSUV(image)) { viewport.setProperties({ voiRange: { lower: image.minPixelValue, upper: image.maxPixelValue, }, }); } viewport.render(); }); }