@cornerstonejs/core 1.61.6 → 1.62.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cornerstonejs/core",
3
- "version": "1.61.6",
3
+ "version": "1.62.0",
4
4
  "description": "",
5
5
  "main": "src/index.ts",
6
6
  "types": "dist/types/index.d.ts",
@@ -47,5 +47,5 @@
47
47
  "type": "individual",
48
48
  "url": "https://ohif.org/donate"
49
49
  },
50
- "gitHead": "4d53b47bb74d03a1858b78489b38996e7d537adc"
50
+ "gitHead": "f42feae4b86eba94ce9ca3b493fb080905241007"
51
51
  }
@@ -62,7 +62,6 @@ import type { vtkSlabCamera as vtkSlabCameraType } from './vtkClasses/vtkSlabCam
62
62
  import vtkSlabCamera from './vtkClasses/vtkSlabCamera';
63
63
  import transformWorldToIndex from '../utilities/transformWorldToIndex';
64
64
  import { getTransferFunctionNodes } from '../utilities/transferFunctionUtils';
65
-
66
65
  /**
67
66
  * Abstract base class for volume viewports. VolumeViewports are used to render
68
67
  * 3D volumes from which various orientations can be viewed. Since VolumeViewports
@@ -282,6 +281,9 @@ abstract class BaseVolumeViewport extends Viewport implements IVolumeViewport {
282
281
  cfun.setMappingRange(range[0], range[1]);
283
282
  volumeActor.getProperty().setRGBTransferFunction(0, cfun);
284
283
 
284
+ // This configures the viewport to use the most recently applied colormap.
285
+ // However, this approach is not optimal when dealing with two volumes, as it prevents retrieval of the
286
+ // colormap for Volume A if Volume B's colormap was the last one applied.
285
287
  this.viewportProperties.colormap = colormap;
286
288
 
287
289
  if (!suppressEvents) {
@@ -789,7 +791,7 @@ abstract class BaseVolumeViewport extends Viewport implements IVolumeViewport {
789
791
  }
790
792
 
791
793
  const {
792
- colormap,
794
+ colormap: latestColormap,
793
795
  VOILUTFunction,
794
796
  interpolationType,
795
797
  invert,
@@ -816,6 +818,16 @@ abstract class BaseVolumeViewport extends Viewport implements IVolumeViewport {
816
818
 
817
819
  const voiRange = voiRanges.length ? voiRanges[0].voiRange : null;
818
820
 
821
+ const volumeColormap = this.getColormap(applicableVolumeActorInfo);
822
+
823
+ let colormap;
824
+ if (volumeId && volumeColormap) {
825
+ colormap = volumeColormap;
826
+ } else {
827
+ colormap = latestColormap;
828
+ }
829
+
830
+
819
831
  return {
820
832
  colormap: colormap,
821
833
  voiRange: voiRange,
@@ -827,6 +839,68 @@ abstract class BaseVolumeViewport extends Viewport implements IVolumeViewport {
827
839
  };
828
840
  };
829
841
 
842
+
843
+ /**
844
+ * This function extracts the nodes from the RGB Transfer Function, transforming each node's x, r, g, b properties
845
+ * into a unified array "RGB Points." Then, it compares these RGB Points—specifically the r, g, b values—with
846
+ * those in the predefined vtk colormap presets. Upon finding a matching set of r, g, b values, the function identifies and selects the
847
+ * corresponding colormap.
848
+ *
849
+ * Next, the function extracts an array of opacity points, formatted as a sequence of [x,y] pairs, where 'x' represents a value and
850
+ * 'y' represents its opacity. It iterates through this array to construct an opacity object that maps each value to its opacity.
851
+ *
852
+ * The function returns an object that includes the name of the identified colormap and the constructed opacity object.
853
+ * @param applicableVolumeActorInfo - The volume actor information for the volume
854
+ * @returns colormap information for the volume if identified
855
+ */
856
+ private getColormap = (applicableVolumeActorInfo) => {
857
+ const { volumeActor } = applicableVolumeActorInfo;
858
+ const cfun = volumeActor.getProperty().getRGBTransferFunction(0);
859
+ const { nodes } = cfun.getState()
860
+ const RGBPoints = nodes.reduce((acc, node) => {
861
+ acc.push(node.x, node.r, node.g, node.b);
862
+ return acc;
863
+ }
864
+ , []);
865
+ const colormaps = vtkColorMaps.rgbPresetNames.map((presetName) =>
866
+ vtkColorMaps.getPresetByName(presetName)
867
+ );
868
+ const matchedColormap = colormaps.find((colormap) => {
869
+ const { RGBPoints: presetRGBPoints } = colormap;
870
+ if (presetRGBPoints.length !== RGBPoints.length) {
871
+ return false;
872
+ }
873
+
874
+ for (let i = 0; i < presetRGBPoints.length; i += 4) {
875
+ if (
876
+ !isEqual(presetRGBPoints.slice(i + 1, i + 4), RGBPoints.slice(i + 1, i + 4))
877
+ ) {
878
+ return false;
879
+ }
880
+ }
881
+
882
+ return true;
883
+ });
884
+
885
+ if (!matchedColormap) {
886
+ return null;
887
+ }
888
+
889
+ const opacityPoints = volumeActor.getProperty().getScalarOpacity(0).getDataPointer()
890
+
891
+ const opacity = []
892
+ for (let i = 0; i < opacityPoints.length; i += 2) {
893
+ opacity.push({ value: opacityPoints[i], opacity: opacityPoints[i + 1] })
894
+ }
895
+
896
+ const colormap = {
897
+ name: matchedColormap.Name,
898
+ opacity: opacity,
899
+ }
900
+
901
+ return colormap;
902
+ }
903
+
830
904
  /**
831
905
  * Creates volume actors for all volumes defined in the `volumeInputArray`.
832
906
  * For each entry, if a `callback` is supplied, it will be called with the new volume actor as input.