Skip to content

Commit 051d540

Browse files
dakerfloryst
authored andcommitted
feat(TIFFReader): add vtkTIFFReader
This PR adds support for loading TIFF image format fixes #3169
1 parent 1f92f84 commit 051d540

File tree

8 files changed

+437
-1
lines changed

8 files changed

+437
-1
lines changed
13.9 KB
Loading

Documentation/content/examples/index.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,8 @@ This will allow you to see the some live code running in your browser. Just pick
188188
[![OfflineLocalView Example][OfflineLocalViewWithIcon]](./OfflineLocalView.html "Load a serialized scene (VTKSZ)")
189189
[![G-Code Example][GCodeReaderWithIcon]](./GCodeReader.html "G-Code reader(gcode)")
190190
[![HDRReader Example][HDRReaderWithIcon]](./HDRReader.html "Load an HDR image")
191-
[![TGAReader Example][TGAReaderWithIcon]](./TGAReader.html "Load an TGA image")
191+
[![TGAReader Example][TGAReaderWithIcon]](./TGAReader.html "Load a TGA image")
192+
[![TIFFReader Example][TIFFReaderWithIcon]](./TGAReader.html "Load a TIFF image")
192193

193194
</div>
194195

@@ -213,6 +214,7 @@ This will allow you to see the some live code running in your browser. Just pick
213214
[GCodeReaderWithIcon]: ../docs/gallery/GCodeReaderWithIcon.jpg
214215
[HDRReaderWithIcon]: ../docs/gallery/HDRReaderWithIcon.jpg
215216
[TGAReaderWithIcon]: ../docs/gallery/TGAReaderWithIcon.jpg
217+
[TIFFReaderWithIcon]: ../docs/gallery/TIFFReaderWithIcon.jpg
216218

217219
# Actors
218220

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
import '@kitware/vtk.js/favicon';
2+
3+
// Load the rendering pieces we want to use (for both WebGL and WebGPU)
4+
import '@kitware/vtk.js/Rendering/Profiles/Geometry';
5+
6+
import vtkFullScreenRenderWindow from '@kitware/vtk.js/Rendering/Misc/FullScreenRenderWindow';
7+
import vtkActor from '@kitware/vtk.js/Rendering/Core/Actor';
8+
import vtkMapper from '@kitware/vtk.js/Rendering/Core/Mapper';
9+
import vtkPlaneSource from '@kitware/vtk.js/Filters/Sources/PlaneSource';
10+
import vtkTIFFReader from '@kitware/vtk.js/IO/Image/TIFFReader';
11+
import vtkTexture from '@kitware/vtk.js/Rendering/Core/Texture';
12+
import vtkURLExtract from '@kitware/vtk.js/Common/Core/URLExtract';
13+
14+
// ----------------------------------------------------------------------------
15+
// Example code
16+
// ----------------------------------------------------------------------------
17+
const userParams = vtkURLExtract.extractURLParameters();
18+
19+
const reader = vtkTIFFReader.newInstance();
20+
const texture = vtkTexture.newInstance();
21+
const planeSource = vtkPlaneSource.newInstance();
22+
const mapper = vtkMapper.newInstance();
23+
const actor = vtkActor.newInstance();
24+
mapper.setInputConnection(planeSource.getOutputPort());
25+
actor.setMapper(mapper);
26+
27+
// ----------------------------------------------------------------------------
28+
// Use a file reader to load a local file
29+
// ----------------------------------------------------------------------------
30+
31+
const myContainer = document.querySelector('body');
32+
const fileContainer = document.createElement('div');
33+
fileContainer.innerHTML =
34+
'<div>Select a tiff file.<br/><input type="file" class="file"/></div>';
35+
myContainer.appendChild(fileContainer);
36+
37+
const fileInput = fileContainer.querySelector('input');
38+
39+
function zoomCameraToFitPlane(camera, planeWidth, planeHeight) {
40+
const fov = 60; // Field of view in degrees
41+
42+
// Calculate the distance needed to fit the plane in view
43+
const distance =
44+
Math.max(planeWidth, planeHeight) /
45+
(2 * Math.tan((fov * Math.PI) / 180 / 2));
46+
47+
// Set camera position
48+
camera.setPosition(planeWidth / 2, planeHeight / 2, distance);
49+
camera.setFocalPoint(planeWidth / 2, planeHeight / 2, 0);
50+
camera.setViewUp(0, 1, 0);
51+
52+
// Set parallel scale for orthographic projection
53+
camera.setParallelScale(planeHeight / 2);
54+
}
55+
56+
function update() {
57+
// Get the vtkImageData from the reader
58+
const imageData = reader.getOutputData(0);
59+
60+
// Set the vtkImageData as the texture input
61+
texture.setInputData(imageData);
62+
63+
// // Get the image's extent and spacing
64+
const [xMin, xMax, yMin, yMax] = imageData.getExtent();
65+
const [spacingX, spacingY] = imageData.getSpacing();
66+
67+
// // Calculate the plane's width and height based on the image's dimensions
68+
const planeWidth = (xMax - xMin + 1) * spacingX;
69+
const planeHeight = (yMax - yMin + 1) * spacingY;
70+
71+
// Set the plane's origin and corners based on calculated width and height
72+
planeSource.setOrigin(0, 0, 0);
73+
planeSource.setPoint1(planeWidth, 0, 0); // Horizontal edge
74+
planeSource.setPoint2(0, planeHeight, 0); // Vertical edge
75+
76+
actor.addTexture(texture);
77+
78+
const fullScreenRenderer = vtkFullScreenRenderWindow.newInstance();
79+
const renderer = fullScreenRenderer.getRenderer();
80+
const renderWindow = fullScreenRenderer.getRenderWindow();
81+
const camera = renderer.getActiveCamera();
82+
const interactor = renderWindow.getInteractor();
83+
84+
// Disable default interactor style
85+
interactor.setInteractorStyle(null);
86+
87+
renderer.addActor(actor);
88+
89+
// Adjust the camera to fit the plane in the view
90+
zoomCameraToFitPlane(camera, planeWidth, planeHeight);
91+
renderer.resetCameraClippingRange();
92+
93+
renderWindow.render();
94+
}
95+
96+
function handleFile(event) {
97+
event.preventDefault();
98+
const dataTransfer = event.dataTransfer;
99+
const files = event.target.files || dataTransfer.files;
100+
if (files.length === 1) {
101+
const file = files[0];
102+
const fileReader = new FileReader();
103+
fileReader.onload = () => {
104+
reader.parse(fileReader.result);
105+
update();
106+
};
107+
fileReader.readAsArrayBuffer(file);
108+
}
109+
}
110+
111+
fileInput.addEventListener('change', handleFile);
112+
113+
// ----------------------------------------------------------------------------
114+
// Use the reader to download a file
115+
// ----------------------------------------------------------------------------
116+
if (userParams.fileURL) {
117+
reader.setUrl(userParams.fileURL).then(() => {
118+
reader.loadData().then(() => {
119+
update();
120+
});
121+
});
122+
}
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
import { vtkAlgorithm, vtkObject } from '../../../interfaces';
2+
import HtmlDataAccessHelper from '../../Core/DataAccessHelper/HtmlDataAccessHelper';
3+
import HttpDataAccessHelper from '../../Core/DataAccessHelper/HttpDataAccessHelper';
4+
import JSZipDataAccessHelper from '../../Core/DataAccessHelper/JSZipDataAccessHelper';
5+
import LiteHttpDataAccessHelper from '../../Core/DataAccessHelper/LiteHttpDataAccessHelper';
6+
7+
interface ITIFFReaderOptions {
8+
compression?: string;
9+
progressCallback?: any;
10+
flipY?: boolean;
11+
}
12+
13+
/**
14+
*
15+
*/
16+
export interface ITIFFReaderInitialValues {}
17+
18+
type vtkTIFFReaderBase = vtkObject &
19+
Omit<
20+
vtkAlgorithm,
21+
| 'getInputData'
22+
| 'setInputData'
23+
| 'setInputConnection'
24+
| 'getInputConnection'
25+
| 'addInputConnection'
26+
| 'addInputData'
27+
>;
28+
29+
export interface vtkTIFFReader extends vtkTIFFReaderBase {
30+
/**
31+
* Get the base url.
32+
*/
33+
getBaseURL(): string;
34+
35+
/**
36+
* Get if the image is flipped vertically.
37+
*/
38+
getFlipY(): boolean;
39+
40+
/**
41+
* Get the dataAccess helper.
42+
*/
43+
getDataAccessHelper():
44+
| HtmlDataAccessHelper
45+
| HttpDataAccessHelper
46+
| JSZipDataAccessHelper
47+
| LiteHttpDataAccessHelper;
48+
49+
/**
50+
* Get the url of the object to load.
51+
*/
52+
getUrl(): string;
53+
54+
/**
55+
* Load the object data.
56+
* @param {ITIFFReaderOptions} [options]
57+
*/
58+
loadData(options?: ITIFFReaderOptions): Promise<any>;
59+
60+
/**
61+
* Parse data.
62+
* @param {ArrayBuffer} content The content to parse.
63+
*/
64+
parse(content: ArrayBuffer): void;
65+
66+
/**
67+
* Parse data as ArrayBuffer.
68+
* @param {ArrayBuffer} content The content to parse.
69+
*/
70+
parseAsArrayBuffer(content: ArrayBuffer): void;
71+
72+
/**
73+
*
74+
* @param inData
75+
* @param outData
76+
*/
77+
requestData(inData: any, outData: any): void;
78+
79+
/**
80+
* Flip the image vertically.
81+
* @param {String} flipY If true, flip the image vertically.
82+
*/
83+
setFlipY(flipY: boolean): boolean;
84+
85+
/**
86+
*
87+
* @param dataAccessHelper
88+
*/
89+
setDataAccessHelper(
90+
dataAccessHelper:
91+
| HtmlDataAccessHelper
92+
| HttpDataAccessHelper
93+
| JSZipDataAccessHelper
94+
| LiteHttpDataAccessHelper
95+
): boolean;
96+
97+
/**
98+
* Set the url of the object to load.
99+
* @param {String} url the url of the object to load.
100+
* @param {ITIFFReaderOptions} [option] The PLY reader options.
101+
*/
102+
setUrl(url: string, option?: ITIFFReaderOptions): Promise<string | any>;
103+
}
104+
105+
/**
106+
* Method used to decorate a given object (publicAPI+model) with vtkTIFFReader characteristics.
107+
*
108+
* @param publicAPI object on which methods will be bounds (public)
109+
* @param model object on which data structure will be bounds (protected)
110+
* @param {ITIFFReaderInitialValues} [initialValues] (default: {})
111+
*/
112+
export function extend(
113+
publicAPI: object,
114+
model: object,
115+
initialValues?: ITIFFReaderInitialValues
116+
): void;
117+
118+
/**
119+
* Method used to create a new instance of vtkTIFFReader
120+
* @param {ITIFFReaderInitialValues} [initialValues] for pre-setting some of its content
121+
*/
122+
export function newInstance(
123+
initialValues?: ITIFFReaderInitialValues
124+
): vtkTIFFReader;
125+
126+
/**
127+
* vtkTIFFReader is a source object that reads TIFF files.
128+
*/
129+
export declare const vtkTIFFReader: {
130+
newInstance: typeof newInstance;
131+
extend: typeof extend;
132+
};
133+
export default vtkTIFFReader;

0 commit comments

Comments
 (0)