diff --git a/packages/core/src/RenderingEngine/StackViewport.ts b/packages/core/src/RenderingEngine/StackViewport.ts index 2d6021985a..6ddb080863 100644 --- a/packages/core/src/RenderingEngine/StackViewport.ts +++ b/packages/core/src/RenderingEngine/StackViewport.ts @@ -995,6 +995,15 @@ class StackViewport extends Viewport { if (typeof colormap !== 'undefined') { this.setColormap(colormap); + // setColormap rebuilds the RGB transfer function in its default, + // non-inverted state, so `this.invert` no longer reflects the actor's + // actual LUT. Clear the tracked flag so the setInvertColor below actually + // re-applies the inversion instead of being skipped by its no-op guard + // (setInvertColorGPU only flips the TF when the requested value differs + // from this.invert). Without this, invert is lost when scrolling after a + // reset: reset applies a colormap, which is then re-applied on every + // scroll and clobbers the inversion. + this.invert = false; } this.setInterpolationType(interpolationType); diff --git a/packages/core/test/stackViewport_gpu_render_test.js b/packages/core/test/stackViewport_gpu_render_test.js index d0dbda759d..84beec9e26 100644 --- a/packages/core/test/stackViewport_gpu_render_test.js +++ b/packages/core/test/stackViewport_gpu_render_test.js @@ -26,7 +26,8 @@ const { cache, RenderingEngine, utilities, imageLoader, metaData, Enums } = cornerstone3D; const { Events, ViewportType, InterpolationType } = Enums; -const { calibratedPixelSpacingMetadataProvider } = utilities; +const { calibratedPixelSpacingMetadataProvider, transferFunctionUtils } = + utilities; const { fakeImageLoader, fakeMetaDataProvider, compareImages } = testUtils; @@ -916,6 +917,55 @@ describe('renderingCore -- Stack', () => { .catch(done.fail); }); + it('Should preserve inversion when scrolling after resetProperties', function (done) { + testUtils.createViewports(renderingEngine, { + viewportId, + orientation: Enums.OrientationAxis.AXIAL, + }); + + const imageInfo = { + loader: 'fakeImageLoader', + name: 'imageURI', + rows: 64, + columns: 64, + barStart: 20, + barWidth: 5, + xSpacing: 1, + ySpacing: 1, + sliceIndex: 0, + }; + const imageId1 = testUtils.encodeImageIdInfo(imageInfo); + const imageId2 = testUtils.encodeImageIdInfo({ + ...imageInfo, + sliceIndex: 1, + }); + + const vp = renderingEngine.getViewport(viewportId); + const getTransferFunctionColors = () => { + const actor = vp.getDefaultActor().actor; + const transferFunction = actor.getProperty().getRGBTransferFunction(0); + + return transferFunctionUtils + .getTransferFunctionNodes(transferFunction) + .map(([, red, green, blue]) => [red, green, blue]); + }; + + vp.setStack([imageId1, imageId2], 0) + .then(() => { + vp.resetProperties(); + vp.setProperties({ invert: true }); + + const invertedColors = getTransferFunctionColors(); + + return vp.setImageIdIndex(1).then(() => { + expect(vp.getProperties().invert).toBe(true); + expect(getTransferFunctionColors()).toEqual(invertedColors); + }); + }) + .then(done) + .catch(done.fail); + }); + it('Should be able to resetProperties API', function (done) { const element = testUtils.createViewports(renderingEngine, { viewportId,