Skip to main content

Migration Guides

As we are moving to the Cornerstone3D library, we are introducing a new set of APIs that are not backwards compatible with the old Cornerstone library. In this page, we will provide a migration guide for users who are already using the old Cornerstone library.

Important

Please note that this is a work in progress and we are still working on completing the migration guides.

init

Cornerstone (legacy) didn't need to be initialized, but CornerstoneTools (legacy) should have been initialized. In Cornerstone3D both core and tools should be initialized before using the libraries.

cornerstoneTools.init();

enabledElement

Enabled elements in Cornerstone3D don’t exist in isolation as in Cornerstone. When setting a layout, elements are tied to a rendering engine as output targets. When this happens they are considered “enabled”.

In Cornerstone3D we have two APIs for this:

  • setViewports: enables a list of viewports at once
  • enableElement: enables one viewport at a time
const element = document.getElementById('div-element');
cornerstone.enable(element);

// Triggers ELEMENT_ENABLED event

loadAndCacheImage

In Cornerstone (legacy), you would load an image and cache it using the loadAndCacheImage API. However, in Cornerstone3D you should use the viewports API to load and cache images.

cornerstone.loadAndCacheImage(imageId).then((image) => {
// Do things, e.g. display an image
});

displayImage

This is a bit different in that you now set the data per viewport rather than per element, as in Cornerstone. When a viewport is later rendered, you are returned the viewport instance, which has helpers to access the HTML element, the renderer, etc.

cornerstone.displayImage(image, element);

// Triggers cornerstone.events.IMAGE_RENDERED
// with eventDetail as follows
const eventDetail = {
viewport: enabledElement.viewport,
element,
image,
enabledElement,
canvasContext: enabledElement.canvas.getContext('2d'),
renderTimeInMs,
};

updateImage

We have effectively the same approach right now, but we have three different helpers that can be called to render:

  • All viewports associated with a rendering engine.
  • A single viewport.

These are useful convenience helpers when using tools that may affect multiple viewports that all need to update (e.g. jump to a crosshair position on all three orthogonal MPR views).

cornerstone.updateImage(element, invalidated);

disable

The rendering engine controls when viewports are enabled/disabled, and will fire appropriate events as needed.

cornerstone.disable(element);
// Triggers ELEMENT_DISABLED event

pageToPixel and pixelToCanvas

We are no longer rendering a single image at a time. In Cornerstone3D, the viewport renders a specific plane in 3D space, determined by the camera parameters (e.g. focal point, frustum, clipping range). Data and annotations will be stored in 3D space ('world space', per frame of reference), and so in order to interact with, and render representations of annotations on the screen, you need to be able to convert between canvas space and world space. It should be noted that, in order to share tools between Stack and Volume viewports, we also render StackViewports in 3D space. So basically, they are 2D images positioned and oriented based on their metadata in space.

// Coordinate mapping functions
cornerstone.pageToPixel(element, pageX, pageY);
cornerstone.pixelToCanvas(element, { x, y });

getPixels

The getPixels approach is no longer valid in 3D, as you may be viewing the data at any (oblique) plane. Additionally, the viewport may be rendering a fusion with more than one volume (e.g., PET/CT) in it. The developer must now fetch the data array itself and use this data as necessary for their specific use case.

cornerstone.getPixels(element, x, y, width, height);

events

The following table demonstrates some expected schema changes for events. The key differences are that:

  • Several IDs will function as lookup keys for core API methods (renderingEngineId, viewportId, volumeId). This is similar to the enabledElement property currently provided in custom events, and can be used to obtain all of the imaging data that is being visualized.
  • Snapshots of state at time of interaction return camera properties and coordinates in world space within the viewports's frame of reference.
CornerstoneToolsCornerstoneTools3DExplanation for schema change
N/ArenderingEngineIdThe Id of the rendering engine instance driving the viewport.
N/AviewportIdThe Id of the viewport itself.
viewport: {
scale,
translation: { x, y },
voi: { windowWidth, windowCenter, windowWidth, windowCenter},
invert,
pixelReplication,
rotation,
hflip,
vflip,
modalityLUT,
voiLUT,
colormap,
labelmap,
displayedArea: {
tlhc: { x, y },
brhc: { x, y },
rowPixelSpacing,
columnPixelSpacing,
presentationSizeMode: 'NONE'
}
}
camera: {
viewUp,
viewPlaneNormal,
position,
focalPoint,
orthogonalOrPerspective,
viewAngle;
}
The viewport previously described the state in 2D, and we need additional information to uniquely define 3D views. Horizontal and vertical flipping is no longer a change to the view, but rather a transform applied to the volume actor itself in the scene.
// Location in 2D within the image

startPoints / lastPoints / currentPoints / deltaPoints: {
Page,
Image,
Client,
}
// Location in 3D in world space
{
CanvasCoord, WorldCoord;
}
The canvas coordinates define where on the 2D canvas the event occurred. We also give the projected world coordinate (3D) at the plane defined by the focal point and the camera normal.