Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

wip Feat/norm16 textures #336

Closed
wants to merge 10 commits into from
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 21 additions & 2 deletions common/reviews/api/core.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,14 @@ declare namespace CONSTANTS {
}
export { CONSTANTS }

// @public (undocumented)
type Cornerstone3DConfig = {
rendering: {
preferSizeOverAccuracy: boolean;
useCPURendering: boolean;
};
};

// @public (undocumented)
interface CPUFallbackColormap {
// (undocumented)
Expand Down Expand Up @@ -450,6 +458,9 @@ interface CustomEvent_2<T = any> extends Event {
initCustomEvent(typeArg: string, canBubbleArg: boolean, cancelableArg: boolean, detailArg: T): void;
}

// @public (undocumented)
const deepMerge: (target?: {}, source?: {}, optionsArgument?: any) => any;

// @public (undocumented)
type ElementDisabledEvent = CustomEvent_2<ElementDisabledEventDetail>;

Expand Down Expand Up @@ -601,6 +612,9 @@ function getClosestImageId(imageVolume: IImageVolume, worldPos: Point3, viewPlan
// @public (undocumented)
function getClosestStackImageIndexForPoint(point: Point3, viewport: IStackViewport): number | null;

// @public (undocumented)
export function getConfiguration(): Cornerstone3DConfig;

// @public (undocumented)
export function getEnabledElement(element: HTMLDivElement | undefined): IEnabledElement | undefined;

Expand Down Expand Up @@ -1134,7 +1148,7 @@ type ImageVolumeModifiedEventDetail = {
function indexWithinDimensions(index: Point3, dimensions: Point3): boolean;

// @public (undocumented)
export function init(defaultConfiguration?: {}): Promise<boolean>;
export function init(configuration?: {}): Promise<boolean>;

// @public (undocumented)
enum InterpolationType {
Expand Down Expand Up @@ -1736,6 +1750,9 @@ type ScalingParameters = {
suvbsa?: number;
};

// @public (undocumented)
export function setConfiguration(newConfig: Cornerstone3DConfig): void;

// @public (undocumented)
export class Settings {
constructor(base?: Settings);
Expand Down Expand Up @@ -1931,6 +1948,7 @@ export function triggerEvent(el: EventTarget, type: string, detail?: unknown): b

declare namespace Types {
export {
Cornerstone3DConfig,
ICamera,
IStackViewport,
IVolumeViewport,
Expand Down Expand Up @@ -2037,7 +2055,8 @@ declare namespace utilities {
spatialRegistrationMetadataProvider,
getViewportImageCornersInWorld,
hasNaNValues,
applyPreset
applyPreset,
deepMerge
}
}
export { utilities }
Expand Down
20 changes: 20 additions & 0 deletions common/reviews/api/streaming-image-volume-loader.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,26 @@ type CameraModifiedEventDetail = {
rotation?: number;
};

// @public (undocumented)
type Cornerstone3DConfig = {
rendering: {
// vtk.js supports 8bit integer textures and 32bit float textures.
// However, if the client has norm16 textures (it can be seen by visiting
// the webGl report at https://webglreport.com/?v=2), vtk will be default
// to use it to improve memory usage. However, if the client don't have
// it still another level of optimization can happen by setting the
// preferSizeOverAccuracy since it will reduce the size of the texture to half
// float at the cost of accuracy in rendering. This is a tradeoff that the
// client can decide.
//
// Read more in the following Pull Request:
// 1. HalfFloat: https://github.com/Kitware/vtk-js/pull/2046
// 2. Norm16: https://github.com/Kitware/vtk-js/pull/2058
preferSizeOverAccuracy: boolean;
useCPURendering: boolean;
};
};

// @public (undocumented)
export function cornerstoneStreamingImageVolumeLoader(volumeId: string, options: {
imageIds: string[];
Expand Down
24 changes: 20 additions & 4 deletions common/reviews/api/tools.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -709,6 +709,26 @@ declare namespace CONSTANTS {
}
export { CONSTANTS }

// @public (undocumented)
type Cornerstone3DConfig = {
rendering: {
// vtk.js supports 8bit integer textures and 32bit float textures.
// However, if the client has norm16 textures (it can be seen by visiting
// the webGl report at https://webglreport.com/?v=2), vtk will be default
// to use it to improve memory usage. However, if the client don't have
// it still another level of optimization can happen by setting the
// preferSizeOverAccuracy since it will reduce the size of the texture to half
// float at the cost of accuracy in rendering. This is a tradeoff that the
// client can decide.
//
// Read more in the following Pull Request:
// 1. HalfFloat: https://github.com/Kitware/vtk-js/pull/2046
// 2. Norm16: https://github.com/Kitware/vtk-js/pull/2058
preferSizeOverAccuracy: boolean;
useCPURendering: boolean;
};
};

// @public (undocumented)
const CORNERSTONE_COLOR_LUT: number[][];

Expand Down Expand Up @@ -1200,9 +1220,6 @@ function debounce(func: Function, wait?: number, options?: {
trailing?: boolean;
}): Function;

// @public (undocumented)
function deepmerge(target?: {}, source?: {}, optionsArgument?: any): any;

// @public (undocumented)
const _default: {
filterAnnotationsWithinSlice: typeof filterAnnotationsWithinSlice;
Expand Down Expand Up @@ -4614,7 +4631,6 @@ declare namespace utilities {
viewportFilters,
drawing_2 as drawing,
debounce,
deepmerge as deepMerge,
throttle,
orientation_2 as orientation,
isObject,
Expand Down
4 changes: 2 additions & 2 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,15 @@
"webpack:watch": "webpack --mode development --progress --watch --config ./.webpack/webpack.dev.js"
},
"peerDependencies": {
"@kitware/vtk.js": "25.9.0",
"@kitware/vtk.js": "25.15.1",
"gl-matrix": "^3.4.3"
},
"dependencies": {
"detect-gpu": "^4.0.45",
"lodash.clonedeep": "4.5.0"
},
"devDependencies": {
"@kitware/vtk.js": "25.9.0",
"@kitware/vtk.js": "25.15.1",
"detect-gpu": "^4.0.45",
"gl-matrix": "^3.4.3",
"resemblejs": "^4.1.0"
Expand Down
26 changes: 14 additions & 12 deletions packages/core/src/RenderingEngine/StackViewport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { vec2, vec3, mat4 } from 'gl-matrix';
import vtkImageMapper from '@kitware/vtk.js/Rendering/Core/ImageMapper';
import vtkImageSlice from '@kitware/vtk.js/Rendering/Core/ImageSlice';
import vtkColorTransferFunction from '@kitware/vtk.js/Rendering/Core/ColorTransferFunction';
import { getConfiguration } from '../init';
import * as metaData from '../metaData';
import Viewport from './Viewport';
import eventTarget from '../eventTarget';
Expand Down Expand Up @@ -74,7 +75,7 @@ interface ImagePixelModule {
samplesPerPixel: number;
highBit: number;
photometricInterpretation: string;
pixelRepresentation: string;
pixelRepresentation: number;
windowWidth: number;
windowCenter: number;
modality: string;
Expand Down Expand Up @@ -1203,15 +1204,19 @@ class StackViewport extends Viewport implements IStackViewport {
bitsAllocated,
numComps,
numVoxels,
isSigned,
}): void {
let pixelArray;
switch (bitsAllocated) {
case 8:
pixelArray = new Uint8Array(numVoxels * numComps);
break;

case 16:
pixelArray = new Float32Array(numVoxels * numComps);
if (getConfiguration().rendering.hasNorm16TextureSupport) {
pixelArray = new Uint16Array(numVoxels * numComps);
} else {
pixelArray = new Float32Array(numVoxels * numComps);
}

break;
case 24:
Expand Down Expand Up @@ -1501,19 +1506,15 @@ class StackViewport extends Viewport implements IStackViewport {
);
}

// Todo: Note that eventually all viewport data is converted into Float32Array,
// we use it here for the purpose of scaling for now.
const type = 'Float32Array';

const priority = -5;
const requestType = RequestType.Interaction;
const additionalDetails = { imageId };
const options = {
targetBuffer: {
type,
offset: null,
length: null,
},
// targetBuffer: {
// type: getScalarDataType()
// offset: null,
// length: null,
// },
preScale: {
enabled: true,
},
Expand Down Expand Up @@ -1731,6 +1732,7 @@ class StackViewport extends Viewport implements IStackViewport {
bitsAllocated,
numComps,
numVoxels,
isSigned: imagePixelModule.pixelRepresentation === 1,
});

// Set the scalar data of the vtkImageData object from the Cornerstone
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { vtkSharedVolumeMapper } from '../vtkClasses';

import { getConfiguration } from '../../init';
/**
* Given an imageData and a vtkOpenGLTexture, it creates a "shared" vtk volume mapper
* from which various volume actors can be created.
Expand All @@ -16,6 +16,10 @@ export default function createVolumeMapper(
): any {
const volumeMapper = vtkSharedVolumeMapper.newInstance();

if (getConfiguration().rendering.preferSizeOverAccuracy) {
volumeMapper.setPreferSizeOverAccuracy(true);
}

volumeMapper.setInputData(imageData);

const spacing = imageData.getSpacing();
Expand All @@ -24,10 +28,9 @@ export default function createVolumeMapper(
const sampleDistance = (spacing[0] + spacing[1] + spacing[2]) / 6;

// This is to allow for good pixel level image quality.
// Todo: why we are setting this to 4000? Is this a good number? it should be configurable
volumeMapper.setMaximumSamplesPerRay(4000);

volumeMapper.setSampleDistance(sampleDistance);

volumeMapper.setScalarTexture(vtkOpenGLTexture);

return volumeMapper;
Expand Down
12 changes: 6 additions & 6 deletions packages/core/src/RenderingEngine/helpers/setDefaultVolumeVOI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,12 +161,12 @@ async function getVOIFromMinMax(imageVolume: IImageVolume): Promise<VOIRange> {
const byteOffset = imageIdIndex * bytesPerImage;

const options = {
targetBuffer: {
arrayBuffer: scalarData.buffer,
offset: byteOffset,
length: voxelsPerImage,
type,
},
// targetBuffer: {
// arrayBuffer: scalarData.buffer,
// offset: byteOffset,
// length: voxelsPerImage,
// type,
// },
priority: PRIORITY,
requestType: REQUEST_TYPE,
preScale: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ function vtkStreamingOpenGLTexture(publicAPI, model) {
depth,
numComps,
dataType,
data
data,
preferSizeOverAccuracy
) => {
model.inputDataType = dataType;
model.inputNumComps = numComps;
Expand All @@ -32,7 +33,8 @@ function vtkStreamingOpenGLTexture(publicAPI, model) {
depth,
numComps,
dataType,
data
data,
preferSizeOverAccuracy
);
};

Expand All @@ -48,7 +50,6 @@ function vtkStreamingOpenGLTexture(publicAPI, model) {
if (!updatedFrames.length) {
return;
}

model._openGLRenderWindow.activateTexture(publicAPI);
publicAPI.createTexture();
publicAPI.bind();
Expand All @@ -62,6 +63,9 @@ function vtkStreamingOpenGLTexture(publicAPI, model) {
} else if (data instanceof Int16Array) {
bytesPerVoxel = 2;
TypedArrayConstructor = Int16Array;
} else if (data instanceof Uint16Array) {
bytesPerVoxel = 2;
TypedArrayConstructor = Uint16Array;
} else if (data instanceof Float32Array) {
bytesPerVoxel = 4;
TypedArrayConstructor = Float32Array;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,10 @@ function vtkStreamingOpenGLVolumeMapper(publicAPI, model) {
}

if (shouldReset) {
model.scalarTexture.setOglNorm16Ext(
model.context.getExtension('EXT_texture_norm16')
);

model.scalarTexture.releaseGraphicsResources(model._openGLRenderWindow);
model.scalarTexture.resetFormatAndType();

Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/cache/classes/ImageVolume.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export class ImageVolume implements IImageVolume {
/** volume origin, Note this is an opinionated origin for the volume */
origin: Point3;
/** volume scalar data */
scalarData: Float32Array | Uint8Array;
scalarData: Float32Array | Uint8Array | Uint16Array | Int16Array;
/** Whether preScaling has been performed on the volume */
isPrescaled = false;
/** volume scaling parameters if it contains scaled data */
Expand Down
13 changes: 9 additions & 4 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ import {
isCornerstoneInitialized,
setUseCPURendering,
resetUseCPURendering,
setPreferSizeOverAccuracy,
getConfiguration,
} from './init';

// Classes
Expand All @@ -54,8 +56,15 @@ import {
export type { Types };

export {
// init
init,
isCornerstoneInitialized,
// configs
getConfiguration,
setPreferSizeOverAccuracy,
getShouldUseCPURendering,
setUseCPURendering,
resetUseCPURendering,
// enums
Enums,
CONSTANTS,
Expand Down Expand Up @@ -98,8 +107,4 @@ export {
imageLoadPoolManager as requestPoolManager,
imageRetrievalPoolManager,
imageLoadPoolManager,
// CPU Rendering
getShouldUseCPURendering,
setUseCPURendering,
resetUseCPURendering,
};
Loading