How to apply a colour map to a texture?

Hi I am using a png image as such:

const image0 = new Image();
image0.src = pngImage0;

const planeSource = vtkPlaneSource.newInstance();
const mapper = vtkMapper.newInstance();
const actor = vtkActor.newInstance();
actor.setMapper(mapper);
mapper.setInputConnection(planeSource.getOutputPort());

const texture0 = vtkTexture.newInstance();
const imageData = imageHelpers.imageToImageData(image0); // this is a png image
texture0.setInterpolate(true);
texture0.setInputData(imageData);
actor.addTexture(texture0);
actor.addMapper(mapper);

I ignored some bits about waiting for the image to load but the question I have is how can I apply a colour map to my output? My input image is a greyscale and I wish to use that range to apply the colour map.

Any help would be welcomed.

To add a bit more information I am doing:
const ctf = vtkColorTransferFunction.newInstance();

  const ctf = vtkColorTransferFunction.newInstance();

  // Cool to warm.
  ctf.addRGBPoint(0.0, 0.23, 0.299, 0.754);
  ctf.addRGBPoint(0.5, 0.865, 0.865, 0.865);
  ctf.addRGBPoint(1.0, 0.706, 0.016, 0.15);

  const tableSize = 32;
  const lut = vtkLookupTable.newInstance();
  lut.setNumberOfColors(tableSize);
  lut.build();

  const table = vtkDataArray.newInstance({
    numberOfComponents: 4,
    size: 4 * tableSize,
    dataType: "Uint8Array",
  });

  for (let i = 0; i < tableSize; i++) {
    const rgba: number[] = [];
    ctf.getColor(i / tableSize, rgba);

    table.setTuple(i, rgba);
  }

  lut.setTable(table);

  mapper.setScalarModeToUsePointFieldData();
  mapper.setColorModeToMapScalars();
  console.log(mapper.getInputData().getNumberOfPoints());
  // prints a different number to number to the actual number of points in my image
  mapper.setColorByArrayName("scalars"); // from imageToImageData
  mapper.setLookupTable(lut);

I don’t know if this approach works for this case, I have used something similar for polydata but I think because it’s a texture of the actor it doesn’t work.

I think you need to convert the image to RGBA before you create the texture. Probably with ScalarToRGBA.

Using mapper.setLookupTable() will not work, because the mapper’s lookup table applies to the scalars of the mapper’s input (in your case, the plane). It does not apply to the texture.

1 Like

Thank you David.

I tried to use vtkImageSlice and vtkImageMapper, but I couldn’t see anything represented on the screen, I am not sure if I can just setInputData of the imageMapper with the imageData from the helper. Are there any extra steps to ensure is visible on the screen?
And would this approach using vtkImageSlice and vtkImageMapper work without the scalarToRGBA?

For vtkImageSlice, are you using code from the example as a starting point? I’d guess that you can add color by setting a vtkImageProperty for the vtkImageSlice object (which is what is done in C++ VTK), but I defer to the vtk.js experts.

Yes, I was using that same example as a starting point, but I don’t see anything on the screen not even the original image. I am unsure how the setSlice (I/J/X/Y/Z) work when I have a imageData that was created from a PNG image.
I tried setting everyone of those but still couldn’t see it. Not sure if I need to change my camera properties or if it’s just not visible at all.

For a 2D image, you would only use one slice and one mapper, with setKSlice(0) or perhaps just setSlice(0).

@dgobbi this is related but not the main topic but since you work more on VTK than VTK.js:
Is there a way to go from a VTK polydata (which is a slice already) and downsample (convert) it to a grid with a specific resolution where each point in that grid reflects a scalar value instead of the pixel value that I would get when converting to a greyscale image.
I hope I explained myself well enough and thank you for your help.

In VTK C++, vtkProbeFilter is used to resample scalars from one data set to another data set. This includes resampling scalars from a polydata to an image grid or vice-versa. In general, this makes the most sense if the polydata is dense (composed of many small polygons). I don’t know if vtk.js has a probe filter.

In order to not ignore the original topic, textures aren’t involved with vtkProbeFilter, since textures are associated with the actor but not with the polydata itself.

1 Like