-
Notifications
You must be signed in to change notification settings - Fork 475
Description
Describe the Bug
In a multi-viewport setup, calling renderingEngine.resize(true) can be silently dropped if any viewport has a pending render (_animationFrameSet === true).
The _resizeVTKViewports method in ContextPoolRenderingEngine has an early return when _animationFrameSet is true, which causes the resize to be lost entirely — it is never retried or deferred.
This causes
- Mispositioned annotations — Tools like probe, length, angle, and segmentation overlays which uses world-to-canvas transformation . When the canvas dimensions don't match the actual container size, all annotations are placed at wrong positions, and existing annotations appear shifted or scaled incorrectly.
Root Cause
In ContextPoolRenderingEngine._resizeVTKViewports(), when this._animationFrameSet is true, the method returns early without performing the resize and without scheduling a retry:
if (this._animationFrameSet) {
return; // resize is silently dropped
}In a multi-viewport scenario, where 1st viewport is resized, enabling or rendering a second viewport sets _animationFrameSet = true on the shared rendering engine making the 'resize()' call to be dropped silently on viewport 1.
Steps to Reproduce
- Open https://www.cornerstonejs.org/live-examples/annotationtoolmodes
- Wait for the image to load.
- Draw an annotation.
- Paste the following script in DevTools Console:
(function reproduceBug() {
const cs = window.cornerstone;
const renderingEngine = cs.getRenderingEngines()[0];
const viewport1 = renderingEngine.getViewports()[0];
const element2 = document.createElement('div');
element2.style.width = '400px';
element2.style.height = '400px';
document.getElementById('content').appendChild(element2);
renderingEngine.enableElement({
viewportId: 'VIEWPORT_2',
type: cs.Enums.ViewportType.STACK,
element: element2,
defaultOptions: { background: [0, 0, 0] },
});
const canvasBefore = { w: viewport1.canvas.width, h: viewport1.canvas.height };
viewport1.element.style.width = '250px';
viewport1.element.style.height = '250px';
renderingEngine.renderViewport('VIEWPORT_2');
renderingEngine.resize(true);
const canvasAfter = { w: viewport1.canvas.width, h: viewport1.canvas.height };
console.log('Canvas BEFORE:', canvasBefore.w, 'x', canvasBefore.h);
console.log('Canvas AFTER: ', canvasAfter.w, 'x', canvasAfter.h);
console.log('Container NOW: 250 x 250');
if (canvasAfter.w === canvasBefore.w && canvasAfter.h === canvasBefore.h) {
console.error(
'🐛 BUG: resize() was silently dropped.',
'Canvas is', canvasAfter.w + 'x' + canvasAfter.h,
'but container is 250x250.',
'canvasToWorld / worldToCanvas will return wrong coordinates.',
'All annotations will be mispositioned.'
);
} else {
console.log('✅ resize() worked correctly');
}
})();
The current behavior
RenderingEngine.resize() does not resize Canvas post resizing the viewport.
Annotation stays at same position and not at moved to anatomically correct position
The expected behavior
RenderingEngine.resize() should update viewport1's canvas dimensions to match its new 250×250 container, keeping canvasToWorld / worldToCanvas transforms correct and annotations accurately positioned.
System Information
chrome
window 11