ng-cornerstone
Version:
[](https://github.com/prettier/prettier) [](http://commitizen.git
388 lines • 71.1 kB
JavaScript
import { ChangeDetectionStrategy, Component, Input, ViewChild, ViewChildren, ViewEncapsulation, Output, EventEmitter, } from '@angular/core';
import { Enums as csCoreEnum, imageLoader, volumeLoader } from '@cornerstonejs/core';
import { Enums as csToolEnum, segmentation } from '@cornerstonejs/tools';
import { BehaviorSubject, combineLatest, debounceTime, filter, map, Subject } from 'rxjs';
import { ToolBarComponent } from '../tool';
import { generateRandomString, generateViewportInputs, imageInfoToUniqueId, LayoutEnum, RequestSchema, } from '../core';
import { takeUntil } from 'rxjs/operators';
import { BaseViewportComponent } from '../viewport';
import { createNiftiImageIdsAndCacheMetadata } from '@cornerstonejs/nifti-volume-loader';
import * as i0 from "@angular/core";
import * as i1 from "../core";
import * as i2 from "@angular/common";
import * as i3 from "../tool/tool-bar.component";
import * as i4 from "../viewport/viewport.component";
import * as i5 from "../viewport/stack-viewport.component";
import * as i6 from "../viewport/volume3d-viewport.component";
import * as i7 from "../viewport/orthographic-viewport.component";
export class ViewerComponent {
get renderingEngine() {
return this.csService.getRenderingEngine();
}
get viewportIds() {
return this.viewportInputs.map((value) => value.viewportId);
}
constructor(elementRef, imageIdService, csService, cdr) {
this.elementRef = elementRef;
this.imageIdService = imageIdService;
this.csService = csService;
this.cdr = cdr;
this.Layout = LayoutEnum;
this.toolGroupId = 'TOOL_GROUP_ID';
this.viewportInputs = [];
this.activeViewportId = '';
this.resizeSubject = new Subject();
this.destroy$ = new Subject();
// 跟踪需要渲染的状态
this.pendingImageRender$ = new BehaviorSubject(false);
this.pendingSegmentRender$ = new BehaviorSubject(false);
// 跟踪已初始化的viewport
this.initializedViewports = new Set();
this.viewportsToInit = new Set();
this.viewportInitialized$ = new BehaviorSubject('');
this.viewportDestroyed$ = new Subject();
// 跟踪viewport是否全部已初始化
this.allViewportsInitialized$ = new BehaviorSubject(false);
// 跟踪工具栏是否已初始化
this.toolbarInitialized$ = new BehaviorSubject(false);
// 跟踪所有组件(工具栏和视口)是否都已初始化
this.allComponentsInitialized$ = new BehaviorSubject(false);
this.toolList = [];
this.viewportActivated = new EventEmitter();
this.imageLoaded = new EventEmitter();
}
ngOnInit() {
// 初始化时记录当前的viewportType
this.initResizeObserver();
this.previousViewportType = this.imageInfo?.viewportType;
this.initComponentsTracking();
// this.generateViewports();
// 设置初始化标志,等待viewport初始化后再渲染
if (this.imageInfo) {
this.pendingImageRender$.next(true);
}
if (this.segmentInfo) {
this.pendingSegmentRender$.next(true);
}
}
ngAfterViewInit() {
// ViewChild已经完成初始化
if (this.toolBarComponent) {
// 订阅工具栏的初始化事件
this.toolBarComponent.toolbarInit.pipe(takeUntil(this.destroy$)).subscribe(() => {
console.debug('Toolbar initialized');
this.toolbarInitialized$.next(true);
});
// 订阅工具栏的销毁事件
this.toolBarComponent.toolbarDestroy.pipe(takeUntil(this.destroy$)).subscribe(() => {
console.debug('Toolbar destroyed');
this.toolbarInitialized$.next(false);
});
}
else {
console.warn('ToolBarComponent not found in view children');
}
}
initResizeObserver() {
this.resizeObserver = new ResizeObserver((entries) => {
for (let entry of entries) {
this.resizeSubject.next();
}
});
this.resizeObserver.observe(this.elementRef.nativeElement);
// Add debounce time
this.resizeSubject
.pipe(debounceTime(300), // Set debounce time to 300ms
takeUntil(this.destroy$))
.subscribe(() => {
const renderingEngine = this.csService.getRenderingEngine();
if (renderingEngine) {
renderingEngine.resize(true, false);
}
});
}
initComponentsTracking() {
// 初始化视口跟踪
this.initViewportTracking();
// 监听工具栏初始化状态变化
this.toolbarInitialized$.pipe(takeUntil(this.destroy$)).subscribe((initialized) => {
if (initialized && this.toolBarComponent) {
// 当toolbar初始化后,注册所有已初始化的viewport
console.debug(`Toolbar initialized, registering all viewports`);
this.initializedViewports.forEach((viewportId) => {
this.toolBarComponent.registerViewport(viewportId);
});
}
});
// 监听工具栏和视口的初始化状态
combineLatest([this.toolbarInitialized$, this.allViewportsInitialized$])
.pipe(takeUntil(this.destroy$), map(([toolbarInitialized, viewportsInitialized]) => toolbarInitialized && viewportsInitialized))
.subscribe((allInitialized) => {
console.debug(`All components initialized: ${allInitialized}`);
this.allComponentsInitialized$.next(allInitialized);
});
// 当所有组件都初始化完成且有待处理的渲染任务时执行渲染
combineLatest([this.allComponentsInitialized$, this.pendingImageRender$, this.pendingSegmentRender$])
.pipe(takeUntil(this.destroy$), filter(([allInitialized, pendingImage, pendingSegment]) => allInitialized && (pendingImage || pendingSegment)))
.subscribe(([_, pendingImage, pendingSegment]) => {
console.debug('All components ready, processing pending renders');
if (pendingImage && this.imageInfo) {
this.loadedImageInfo = undefined;
this.loadedSegmentInfo = undefined;
segmentation.state.removeAllSegmentations();
this.retrieveImage(false);
this.pendingImageRender$.next(false);
}
if (pendingSegment && this.segmentInfo) {
this.loadedSegmentInfo = undefined;
segmentation.state.removeAllSegmentations();
this.retrieveImage(true);
this.pendingSegmentRender$.next(false);
}
});
}
initViewportTracking() {
// 处理viewport初始化事件
this.viewportInitialized$.pipe(takeUntil(this.destroy$)).subscribe((viewportId) => {
console.debug(`Viewport initialized: ${viewportId}`);
this.initializedViewports.add(viewportId);
// 如果toolbar已初始化,直接注册viewport
if (this.toolbarInitialized$.value && this.toolBarComponent) {
this.toolBarComponent.registerViewport(viewportId);
}
this.checkAllViewportsInitialized();
});
// 处理viewport销毁事件
this.viewportDestroyed$.pipe(takeUntil(this.destroy$)).subscribe((viewportId) => {
console.debug(`Viewport destroyed: ${viewportId}`);
this.initializedViewports.delete(viewportId);
this.viewportsToInit.delete(viewportId);
// 仅当toolbar已初始化时才注销viewport
if (this.toolbarInitialized$.value && this.toolBarComponent) {
this.toolBarComponent.unregisterViewport(viewportId);
}
this.checkAllViewportsInitialized();
});
}
checkAllViewportsInitialized() {
const allInitialized = this.viewportsToInit.size > 0 && this.initializedViewports.size === this.viewportsToInit.size;
console.debug(`Checking viewports initialized: ${this.initializedViewports.size}/${this.viewportsToInit.size}`);
this.allViewportsInitialized$.next(allInitialized);
// 设置默认的active viewport,如果所有viewport都初始化完成且尚未设置
if (allInitialized && !this.activeViewportId && this.viewportIds.length > 0) {
this.activeViewportId = this.viewportIds[0];
this.cdr.detectChanges();
}
}
onViewportInit(viewportId) {
console.debug('Viewport initialized event received:', viewportId);
this.viewportInitialized$.next(viewportId);
}
onViewportDestroy(viewportId) {
console.debug('Viewport destroyed event received:', viewportId);
this.viewportDestroyed$.next(viewportId);
}
onToolbarInit() {
console.debug('ToolBar initialized event received');
this.toolbarInitialized$.next(true);
// 注册逻辑已移到toolbarInitialized$订阅中处理
}
onToolbarDestroy() {
console.debug('ToolBar destroyed event received');
this.toolbarInitialized$.next(false);
// 销毁逻辑已移到toolbarInitialized$订阅中处理
}
generateViewports() {
// 重置viewport跟踪
this.initializedViewports.clear();
this.viewportsToInit.clear();
this.allViewportsInitialized$.next(false);
if (this.layout !== undefined && this.imageInfo?.viewportType) {
const suffix = generateRandomString();
this.viewportInputs = generateViewportInputs(this.layout, suffix, this.imageInfo);
this.viewportInputs.forEach((viewport) => {
if (viewport.viewportId) {
this.viewportsToInit.add(viewport.viewportId);
}
});
// Reset activeViewportId
this.activeViewportId = '';
}
console.debug(`Generated ${this.viewportsToInit.size} viewports to initialize`);
}
ngOnChanges(changes) {
const { imageInfo, segmentInfo, layout } = changes;
let viewportTypeChanged = false;
// 检查imageInfo的viewportType是否变更
if (imageInfo && this.imageInfo) {
const currentViewportType = this.imageInfo.viewportType;
// 使用SimpleChanges提供的previousValue和currentValue进行比较
if (imageInfo.previousValue?.viewportType !== imageInfo.currentValue?.viewportType) {
viewportTypeChanged = true;
}
// 如果SimpleChanges没有提供足够信息,使用我们自己跟踪的previousViewportType
else if (this.previousViewportType !== currentViewportType) {
viewportTypeChanged = true;
}
// 更新记录的viewportType
this.previousViewportType = currentViewportType;
}
// 布局发生变化或viewportType变更时重新生成viewport
if ((layout && !layout.isFirstChange()) || viewportTypeChanged) {
console.debug(`Layout or ViewportType changed, regenerating viewports`);
this.generateViewports();
// 设置标志表示需要在viewport初始化后渲染
if (this.imageInfo) {
this.pendingImageRender$.next(true);
}
if (this.segmentInfo) {
this.pendingSegmentRender$.next(true);
}
}
else {
// 其他变化情况处理
if (imageInfo && this.imageInfo) {
this.pendingImageRender$.next(true);
}
if (segmentInfo && this.segmentInfo) {
this.pendingSegmentRender$.next(true);
}
// 如果所有组件已初始化,触发状态检查以执行渲染
if (this.allComponentsInitialized$.value) {
// 重新检查所有组件的初始化状态
this.checkAllViewportsInitialized();
}
}
// Change detection - refresh view
this.cdr.detectChanges();
}
onViewportClick(viewportId) {
if (viewportId) {
this.activeViewportId = viewportId;
this.viewportActivated.emit(viewportId);
}
}
/**
* Retrieve image data without rendering
* Rendering is handled by each viewport component
*/
async retrieveImage(isSegment = false) {
const imageInfo = isSegment ? this.segmentInfo : this.imageInfo;
if (!imageInfo) {
return;
}
let imageIds = [];
// 根据不同schema获取imageIds
if (imageInfo.schema === RequestSchema.wadoRs) {
imageIds = await this.imageIdService.wadoRsCreateImageIdsAndCacheMetaData(imageInfo);
}
else if (imageInfo.schema === RequestSchema.nifti) {
imageIds = await createNiftiImageIdsAndCacheMetadata({ url: imageInfo.urlRoot });
}
else {
console.error('Unsupported request schema');
return;
}
// 准备分段和图像数据的处理函数
const processSegmentation = async (labelImages, uniqueId) => {
const derivedSegmentationImages = await imageLoader.createAndCacheDerivedLabelmapImages(imageIds);
const derivedSegmentationImageIds = derivedSegmentationImages.map((image) => image.imageId);
// 处理标签数据
for (let i = 0; i < derivedSegmentationImages.length; i++) {
const voxelManager = derivedSegmentationImages[i].voxelManager;
const scalarData = voxelManager.getScalarData();
const labelImage = labelImages[i];
if (labelImage) {
scalarData.set(labelImage.getPixelData());
voxelManager.setScalarData(scalarData);
}
}
// Check if segmentation already exists and remove it
const existingSegmentation = segmentation.state.getSegmentation(uniqueId);
if (existingSegmentation && segmentation.removeSegmentation) {
segmentation.removeSegmentation(uniqueId);
}
// Add new segmentation
segmentation.addSegmentations([
{
segmentationId: uniqueId,
representation: {
type: csToolEnum.SegmentationRepresentations.Labelmap,
data: {
imageIds: derivedSegmentationImageIds,
},
},
},
]);
return derivedSegmentationImageIds;
};
// Process data based on viewport type
if (imageInfo.viewportType !== csCoreEnum.ViewportType.STACK) {
// Volume rendering processing
const volumeId = imageInfoToUniqueId(imageInfo);
const volume = await volumeLoader.createAndCacheVolume(volumeId, { imageIds });
await volume.load(async () => {
if (isSegment) {
const labelImages = volume.getCornerstoneImages();
const uniqueId = imageInfoToUniqueId(imageInfo);
const derivedSegmentationImageIds = await processSegmentation(labelImages, uniqueId);
// 更新 loadedSegmentInfo 而不是直接修改输入的 segmentInfo
this.loadedSegmentInfo = { ...imageInfo, imageIds: derivedSegmentationImageIds };
}
else {
// 更新 loadedImageInfo 而不是直接修改输入的 imageInfo
this.loadedImageInfo = { ...imageInfo, volumeId, imageIds };
}
this.cdr.detectChanges();
this.imageLoaded.emit();
});
}
else {
// Plane image processing
const images = await imageLoader.loadAndCacheImages(imageIds);
if (isSegment) {
const uniqueId = imageInfoToUniqueId(imageInfo);
const derivedSegmentationImageIds = await processSegmentation(await Promise.all(images), uniqueId);
// 更新 loadedSegmentInfo 而不是直接修改输入的 segmentInfo
this.loadedSegmentInfo = { ...imageInfo, imageIds: derivedSegmentationImageIds };
}
else {
// 更新 loadedImageInfo 而不是直接修改输入的 imageInfo
this.loadedImageInfo = { ...imageInfo, imageIds };
}
this.cdr.detectChanges();
this.imageLoaded.emit();
}
}
ngOnDestroy() {
this.resizeObserver.disconnect();
this.destroy$.next();
this.destroy$.complete();
console.debug('viewer destroyed');
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ViewerComponent, deps: [{ token: i0.ElementRef }, { token: i1.ImageIdService }, { token: i1.CornerstoneService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: ViewerComponent, selector: "nc-viewer", inputs: { layout: "layout", imageInfo: "imageInfo", segmentInfo: "segmentInfo", toolList: "toolList" }, outputs: { viewportActivated: "viewportActivated", imageLoaded: "imageLoaded" }, viewQueries: [{ propertyName: "toolBarComponent", first: true, predicate: ToolBarComponent, descendants: true }, { propertyName: "viewportComponentList", predicate: BaseViewportComponent, descendants: true }], exportAs: ["ncViewer"], usesOnChanges: true, ngImport: i0, template: "<nc-tool-bar\n class=\"dicom-viewer-tool\"\n [toolGroupId]=\"toolGroupId\"\n [toolList]=\"toolList\"\n [activeViewportId]=\"activeViewportId\"\n (toolbarInit)=\"onToolbarInit()\"\n (toolbarDestroy)=\"onToolbarDestroy()\"\n>\n</nc-tool-bar>\n\n<div\n class=\"dicom-viewer-container\"\n [ngClass]=\"{\n 'layout-11': layout === Layout.LAYOUT_1x1,\n 'layout-12': layout === Layout.LAYOUT_1x2,\n 'layout-13': layout === Layout.LAYOUT_1x3,\n 'layout-22': layout === Layout.LAYOUT_2x2,\n }\"\n>\n <!-- \u52A8\u6001\u9009\u62E9\u5408\u9002\u7684\u89C6\u53E3\u7EC4\u4EF6\u7C7B\u578B -->\n <ng-container *ngFor=\"let viewport of viewportInputs\">\n <ng-container [ngSwitch]=\"viewport.type\">\n <!-- Stack\u89C6\u53E3 -->\n <nc-stack-viewport\n class=\"dicom-viewer-viewport\"\n *ngSwitchCase=\"'stack'\"\n [viewportInput]=\"viewport\"\n [active]=\"viewport.viewportId === activeViewportId\"\n [imageInfo]=\"loadedImageInfo\"\n [segmentInfo]=\"loadedSegmentInfo\"\n (viewportUpdated)=\"onViewportInit($event)\"\n (viewportDestroy)=\"onViewportDestroy($event)\"\n (click)=\"onViewportClick(viewport.viewportId)\"\n >\n </nc-stack-viewport>\n\n <!-- Volume3D\u89C6\u53E3 -->\n <nc-volume3d-viewport\n class=\"dicom-viewer-viewport\"\n *ngSwitchCase=\"'volume3d'\"\n [viewportInput]=\"viewport\"\n [active]=\"viewport.viewportId === activeViewportId\"\n [imageInfo]=\"loadedImageInfo\"\n [segmentInfo]=\"loadedSegmentInfo\"\n (viewportUpdated)=\"onViewportInit($event)\"\n (viewportDestroy)=\"onViewportDestroy($event)\"\n (click)=\"onViewportClick(viewport.viewportId)\"\n >\n </nc-volume3d-viewport>\n\n <!-- Orthographic\u89C6\u53E3 -->\n <nc-orthographic-viewport\n class=\"dicom-viewer-viewport\"\n *ngSwitchCase=\"'orthographic'\"\n [viewportInput]=\"viewport\"\n [active]=\"viewport.viewportId === activeViewportId\"\n [imageInfo]=\"loadedImageInfo\"\n [segmentInfo]=\"loadedSegmentInfo\"\n (viewportUpdated)=\"onViewportInit($event)\"\n (viewportDestroy)=\"onViewportDestroy($event)\"\n (click)=\"onViewportClick(viewport.viewportId)\"\n >\n </nc-orthographic-viewport>\n\n <!-- \u9ED8\u8BA4\u89C6\u53E3\uFF08\u517C\u5BB9\u6027\u4FDD\u969C\uFF09 -->\n <nc-viewport\n class=\"dicom-viewer-viewport\"\n *ngSwitchDefault\n [viewportInput]=\"viewport\"\n [active]=\"viewport.viewportId === activeViewportId\"\n [imageInfo]=\"loadedImageInfo\"\n [segmentInfo]=\"loadedSegmentInfo\"\n (viewportUpdated)=\"onViewportInit($event)\"\n (viewportDestroy)=\"onViewportDestroy($event)\"\n (click)=\"onViewportClick(viewport.viewportId)\"\n >\n </nc-viewport>\n </ng-container>\n </ng-container>\n</div>\n", styles: ["nc-viewer{height:100%;width:100%;display:flex;flex-direction:column;background-color:#000}.dicom-viewer-tool{flex:0 0 auto}.dicom-viewer-container{flex:1 1 auto;display:flex;flex-direction:row;height:100%}.layout-11{flex-wrap:nowrap}.layout-11 .dicom-viewer-viewport{width:100%;height:100%}.layout-12{flex-wrap:nowrap;min-height:400px}.layout-12 .dicom-viewer-viewport{width:50%;height:100%}.layout-13{flex-wrap:nowrap;min-height:400px}.layout-13 .dicom-viewer-viewport{width:33.33%;height:100%}.layout-22{flex-wrap:wrap;min-height:700px}.layout-22 .dicom-viewer-viewport{width:50%;height:50%}\n"], dependencies: [{ kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i2.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i2.NgSwitchDefault, selector: "[ngSwitchDefault]" }, { kind: "component", type: i3.ToolBarComponent, selector: "nc-tool-bar", inputs: ["toolGroupId", "toolList", "activeViewportId"], outputs: ["toolbarInit", "toolbarDestroy"], exportAs: ["ncToolBar"] }, { kind: "component", type: i4.ViewportComponent, selector: "nc-viewport", exportAs: ["ncViewport"] }, { kind: "component", type: i5.StackViewportComponent, selector: "nc-stack-viewport" }, { kind: "component", type: i6.Volume3DViewportComponent, selector: "nc-volume3d-viewport", inputs: ["volumeId"] }, { kind: "component", type: i7.OrthographicViewportComponent, selector: "nc-orthographic-viewport" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ViewerComponent, decorators: [{
type: Component,
args: [{ selector: 'nc-viewer', exportAs: 'ncViewer', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<nc-tool-bar\n class=\"dicom-viewer-tool\"\n [toolGroupId]=\"toolGroupId\"\n [toolList]=\"toolList\"\n [activeViewportId]=\"activeViewportId\"\n (toolbarInit)=\"onToolbarInit()\"\n (toolbarDestroy)=\"onToolbarDestroy()\"\n>\n</nc-tool-bar>\n\n<div\n class=\"dicom-viewer-container\"\n [ngClass]=\"{\n 'layout-11': layout === Layout.LAYOUT_1x1,\n 'layout-12': layout === Layout.LAYOUT_1x2,\n 'layout-13': layout === Layout.LAYOUT_1x3,\n 'layout-22': layout === Layout.LAYOUT_2x2,\n }\"\n>\n <!-- \u52A8\u6001\u9009\u62E9\u5408\u9002\u7684\u89C6\u53E3\u7EC4\u4EF6\u7C7B\u578B -->\n <ng-container *ngFor=\"let viewport of viewportInputs\">\n <ng-container [ngSwitch]=\"viewport.type\">\n <!-- Stack\u89C6\u53E3 -->\n <nc-stack-viewport\n class=\"dicom-viewer-viewport\"\n *ngSwitchCase=\"'stack'\"\n [viewportInput]=\"viewport\"\n [active]=\"viewport.viewportId === activeViewportId\"\n [imageInfo]=\"loadedImageInfo\"\n [segmentInfo]=\"loadedSegmentInfo\"\n (viewportUpdated)=\"onViewportInit($event)\"\n (viewportDestroy)=\"onViewportDestroy($event)\"\n (click)=\"onViewportClick(viewport.viewportId)\"\n >\n </nc-stack-viewport>\n\n <!-- Volume3D\u89C6\u53E3 -->\n <nc-volume3d-viewport\n class=\"dicom-viewer-viewport\"\n *ngSwitchCase=\"'volume3d'\"\n [viewportInput]=\"viewport\"\n [active]=\"viewport.viewportId === activeViewportId\"\n [imageInfo]=\"loadedImageInfo\"\n [segmentInfo]=\"loadedSegmentInfo\"\n (viewportUpdated)=\"onViewportInit($event)\"\n (viewportDestroy)=\"onViewportDestroy($event)\"\n (click)=\"onViewportClick(viewport.viewportId)\"\n >\n </nc-volume3d-viewport>\n\n <!-- Orthographic\u89C6\u53E3 -->\n <nc-orthographic-viewport\n class=\"dicom-viewer-viewport\"\n *ngSwitchCase=\"'orthographic'\"\n [viewportInput]=\"viewport\"\n [active]=\"viewport.viewportId === activeViewportId\"\n [imageInfo]=\"loadedImageInfo\"\n [segmentInfo]=\"loadedSegmentInfo\"\n (viewportUpdated)=\"onViewportInit($event)\"\n (viewportDestroy)=\"onViewportDestroy($event)\"\n (click)=\"onViewportClick(viewport.viewportId)\"\n >\n </nc-orthographic-viewport>\n\n <!-- \u9ED8\u8BA4\u89C6\u53E3\uFF08\u517C\u5BB9\u6027\u4FDD\u969C\uFF09 -->\n <nc-viewport\n class=\"dicom-viewer-viewport\"\n *ngSwitchDefault\n [viewportInput]=\"viewport\"\n [active]=\"viewport.viewportId === activeViewportId\"\n [imageInfo]=\"loadedImageInfo\"\n [segmentInfo]=\"loadedSegmentInfo\"\n (viewportUpdated)=\"onViewportInit($event)\"\n (viewportDestroy)=\"onViewportDestroy($event)\"\n (click)=\"onViewportClick(viewport.viewportId)\"\n >\n </nc-viewport>\n </ng-container>\n </ng-container>\n</div>\n", styles: ["nc-viewer{height:100%;width:100%;display:flex;flex-direction:column;background-color:#000}.dicom-viewer-tool{flex:0 0 auto}.dicom-viewer-container{flex:1 1 auto;display:flex;flex-direction:row;height:100%}.layout-11{flex-wrap:nowrap}.layout-11 .dicom-viewer-viewport{width:100%;height:100%}.layout-12{flex-wrap:nowrap;min-height:400px}.layout-12 .dicom-viewer-viewport{width:50%;height:100%}.layout-13{flex-wrap:nowrap;min-height:400px}.layout-13 .dicom-viewer-viewport{width:33.33%;height:100%}.layout-22{flex-wrap:wrap;min-height:700px}.layout-22 .dicom-viewer-viewport{width:50%;height:50%}\n"] }]
}], ctorParameters: () => [{ type: i0.ElementRef }, { type: i1.ImageIdService }, { type: i1.CornerstoneService }, { type: i0.ChangeDetectorRef }], propDecorators: { layout: [{
type: Input
}], imageInfo: [{
type: Input
}], segmentInfo: [{
type: Input
}], toolBarComponent: [{
type: ViewChild,
args: [ToolBarComponent]
}], viewportComponentList: [{
type: ViewChildren,
args: [BaseViewportComponent]
}], toolList: [{
type: Input
}], viewportActivated: [{
type: Output
}], imageLoaded: [{
type: Output
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmlld2VyLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL25nLWNvcm5lcnN0b25lL3NyYy9saWIvdmlld2VyL3ZpZXdlci5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZy1jb3JuZXJzdG9uZS9zcmMvbGliL3ZpZXdlci92aWV3ZXIuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLHVCQUF1QixFQUV2QixTQUFTLEVBRVQsS0FBSyxFQU1MLFNBQVMsRUFDVCxZQUFZLEVBQ1osaUJBQWlCLEVBQ2pCLE1BQU0sRUFDTixZQUFZLEdBRWIsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLEtBQUssSUFBSSxVQUFVLEVBQUUsV0FBVyxFQUFTLFlBQVksRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQzVGLE9BQU8sRUFBRSxLQUFLLElBQUksVUFBVSxFQUFFLFlBQVksRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBRXpFLE9BQU8sRUFBRSxlQUFlLEVBQUUsYUFBYSxFQUFFLFlBQVksRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFLE9BQU8sRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUUxRixPQUFPLEVBQUUsZ0JBQWdCLEVBQVksTUFBTSxTQUFTLENBQUM7QUFDckQsT0FBTyxFQUVMLG9CQUFvQixFQUNwQixzQkFBc0IsRUFHdEIsbUJBQW1CLEVBQ25CLFVBQVUsRUFDVixhQUFhLEdBQ2QsTUFBTSxTQUFTLENBQUM7QUFDakIsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQzNDLE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUNwRCxPQUFPLEVBQUUsbUNBQW1DLEVBQUUsTUFBTSxvQ0FBb0MsQ0FBQzs7Ozs7Ozs7O0FBVXpGLE1BQU0sT0FBTyxlQUFlO0lBeUQxQixJQUFJLGVBQWU7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QUFRLEVBQUUsQ0FBQztRQUN6QixPQUFPLENBQUMsS0FBSyxDQUFDLGtCQUFrQixDQUFDLENBQUM7SUFDcEMsQ0FBQzsrR0E5YVUsZUFBZTttR0FBZixlQUFlLDRSQTZDZixnQkFBZ0IsMkVBR2IscUJBQXFCLDZGQzlGckMsczRGQWdGQTs7NEZEbENhLGVBQWU7a0JBUjNCLFNBQVM7K0JBQ0UsV0FBVyxZQUNYLFVBQVUsbUJBR0gsdUJBQXVCLENBQUMsTUFBTSxpQkFDaEMsaUJBQWlCLENBQUMsSUFBSTs2S0FtQ3JDLE1BQU07c0JBREwsS0FBSztnQkFJTixTQUFTO3NCQURSLEtBQUs7Z0JBSU4sV0FBVztzQkFEVixLQUFLO2dCQVFOLGdCQUFnQjtzQkFEZixTQUFTO3VCQUFDLGdCQUFnQjtnQkFJM0IscUJBQXFCO3NCQURwQixZQUFZO3VCQUFDLHFCQUFxQjtnQkFJbkMsUUFBUTtzQkFEUCxLQUFLO2dCQUdJLGlCQUFpQjtzQkFBMUIsTUFBTTtnQkFDRyxXQUFXO3NCQUFwQixNQUFNIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXG4gIENoYW5nZURldGVjdG9yUmVmLFxuICBDb21wb25lbnQsXG4gIEVsZW1lbnRSZWYsXG4gIElucHV0LFxuICBPbkNoYW5nZXMsXG4gIE9uRGVzdHJveSxcbiAgT25Jbml0LFxuICBRdWVyeUxpc3QsXG4gIFNpbXBsZUNoYW5nZXMsXG4gIFZpZXdDaGlsZCxcbiAgVmlld0NoaWxkcmVuLFxuICBWaWV3RW5jYXBzdWxhdGlvbixcbiAgT3V0cHV0LFxuICBFdmVudEVtaXR0ZXIsXG4gIEFmdGVyVmlld0luaXQsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgRW51bXMgYXMgY3NDb3JlRW51bSwgaW1hZ2VMb2FkZXIsIFR5cGVzLCB2b2x1bWVMb2FkZXIgfSBmcm9tICdAY29ybmVyc3RvbmVqcy9jb3JlJztcbmltcG9ydCB7IEVudW1zIGFzIGNzVG9vbEVudW0sIHNlZ21lbnRhdGlvbiB9IGZyb20gJ0Bjb3JuZXJzdG9uZWpzL3Rvb2xzJztcblxuaW1wb3J0IHsgQmVoYXZpb3JTdWJqZWN0LCBjb21iaW5lTGF0ZXN0LCBkZWJvdW5jZVRpbWUsIGZpbHRlciwgbWFwLCBTdWJqZWN0IH0gZnJvbSAncnhqcyc7XG5cbmltcG9ydCB7IFRvb2xCYXJDb21wb25lbnQsIFRvb2xFbnVtIH0gZnJvbSAnLi4vdG9vbCc7XG5pbXBvcnQge1xuICBDb3JuZXJzdG9uZVNlcnZpY2UsXG4gIGdlbmVyYXRlUmFuZG9tU3RyaW5nLFxuICBnZW5lcmF0ZVZpZXdwb3J0SW5wdXRzLFxuICBJbWFnZUlkU2VydmljZSxcbiAgSW1hZ2VJbmZvLFxuICBpbWFnZUluZm9Ub1VuaXF1ZUlkLFxuICBMYXlvdXRFbnVtLFxuICBSZXF1ZXN0U2NoZW1hLFxufSBmcm9tICcuLi9jb3JlJztcbmltcG9ydCB7IHRha2VVbnRpbCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7IEJhc2VWaWV3cG9ydENvbXBvbmVudCB9IGZyb20gJy4uL3ZpZXdwb3J0JztcbmltcG9ydCB7IGNyZWF0ZU5pZnRpSW1hZ2VJZHNBbmRDYWNoZU1ldGFkYXRhIH0gZnJvbSAnQGNvcm5lcnN0b25lanMvbmlmdGktdm9sdW1lLWxvYWRlcic7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ25jLXZpZXdlcicsXG4gIGV4cG9ydEFzOiAnbmNWaWV3ZXInLFxuICB0ZW1wbGF0ZVVybDogJy4vdmlld2VyLmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmxzOiBbJy4vdmlld2VyLmNvbXBvbmVudC5zY3NzJ10sXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxuICBlbmNhcHN1bGF0aW9uOiBWaWV3RW5jYXBzdWxhdGlvbi5Ob25lLFxufSlcbmV4cG9ydCBjbGFzcyBWaWV3ZXJDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQsIE9uQ2hhbmdlcywgT25EZXN0cm95LCBBZnRlclZpZXdJbml0IHtcbiAgTGF5b3V0ID0gTGF5b3V0RW51bTtcbiAgdG9vbEdyb3VwSWQgPSAnVE9PTF9HUk9VUF9JRCc7XG4gIHZpZXdwb3J0SW5wdXRzOiBQYXJ0aWFsPFR5cGVzLlB1YmxpY1ZpZXdwb3J0SW5wdXQ+W10gPSBbXTtcbiAgYWN0aXZlVmlld3BvcnRJZDogc3RyaW5nID0gJyc7XG5cbiAgcHJpdmF0ZSByZXNpemVPYnNlcnZlciE6IFJlc2l6ZU9ic2VydmVyO1xuICBwcml2YXRlIHJlc2l6ZVN1YmplY3QgPSBuZXcgU3ViamVjdDx2b2lkPigpO1xuICBwcml2YXRlIGRlc3Ryb3kkID0gbmV3IFN1YmplY3Q8dm9pZD4oKTtcblxuICAvLyDot5/ouKrpnIDopoHmuLLmn5PnmoTnirbmgIFcbiAgcHJpdmF0ZSBwZW5kaW5nSW1hZ2VSZW5kZXIkID0gbmV3IEJlaGF2aW9yU3ViamVjdDxib29sZWFuPihmYWxzZSk7XG4gIHByaXZhdGUgcGVuZGluZ1NlZ21lbnRSZW5kZXIkID0gbmV3IEJlaGF2aW9yU3ViamVjdDxib29sZWFuPihmYWxzZSk7XG5cbiAgLy8g6Lef6Liq5bey5Yid5aeL5YyW55qEdmlld3BvcnRcbiAgcHJpdmF0ZSBpbml0aWFsaXplZFZpZXdwb3J0cyA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICBwcml2YXRlIHZpZXdwb3J0c1RvSW5pdCA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICBwcml2YXRlIHZpZXdwb3J0SW5pdGlhbGl6ZWQkID0gbmV3IEJlaGF2aW9yU3ViamVjdDxzdHJpbmc+KCcnKTtcbiAgcHJpdmF0ZSB2aWV3cG9ydERlc3Ryb3llZCQgPSBuZXcgU3ViamVjdDxzdHJpbmc+KCk7XG5cbiAgLy8g6Lef6Liqdmlld3BvcnTmmK/lkKblhajpg6jlt7LliJ3lp4vljJZcbiAgcHJpdmF0ZSBhbGxWaWV3cG9ydHNJbml0aWFsaXplZCQgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PGJvb2xlYW4+KGZhbHNlKTtcblxuICAvLyDot5/ouKrlt6XlhbfmoI/mmK/lkKblt7LliJ3lp4vljJZcbiAgcHJpdmF0ZSB0b29sYmFySW5pdGlhbGl6ZWQkID0gbmV3IEJlaGF2aW9yU3ViamVjdDxib29sZWFuPihmYWxzZSk7XG5cbiAgLy8g6Lef6Liq5omA5pyJ57uE5Lu277yI5bel5YW35qCP5ZKM6KeG5Y+j77yJ5piv5ZCm6YO95bey5Yid5aeL5YyWXG4gIHByaXZhdGUgYWxsQ29tcG9uZW50c0luaXRpYWxpemVkJCA9IG5ldyBCZWhhdmlvclN1YmplY3Q8Ym9vbGVhbj4oZmFsc2UpO1xuXG4gIC8vIOi3n+i4quS4iuS4gOasoeeahHZpZXdwb3J0VHlwZVxuICBwcml2YXRlIHByZXZpb3VzVmlld3BvcnRUeXBlPzogY3NDb3JlRW51bS5WaWV3cG9ydFR5cGU7XG5cbiAgQElucHV0KClcbiAgbGF5b3V0PzogTGF5b3V0RW51bTtcblxuICBASW5wdXQoKVxuICBpbWFnZUluZm8/OiBJbWFnZUluZm87XG5cbiAgQElucHV0KClcbiAgc2VnbWVudEluZm8/OiBJbWFnZUluZm87XG5cbiAgLy8g5paw5aKe5Yqg55qE5bGe5oCn77ya55So5LqO5a2Y5YKo5bey5Yqg6L2955qE5Zu+5YOP5ZKM5YiG5q615L+h5oGvXG4gIGxvYWRlZEltYWdlSW5mbz86IEltYWdlSW5mbztcbiAgbG9hZGVkU2VnbWVudEluZm8/OiBJbWFnZUluZm87XG5cbiAgQFZpZXdDaGlsZChUb29sQmFyQ29tcG9uZW50KVxuICB0b29sQmFyQ29tcG9uZW50ITogVG9vbEJhckNvbXBvbmVudDtcblxuICBAVmlld0NoaWxkcmVuKEJhc2VWaWV3cG9ydENvbXBvbmVudClcbiAgdmlld3BvcnRDb21wb25lbnRMaXN0ITogUXVlcnlMaXN0PEJhc2VWaWV3cG9ydENvbXBvbmVudD47XG5cbiAgQElucHV0KClcbiAgdG9vbExpc3Q6IFRvb2xFbnVtW10gPSBbXTtcblxuICBAT3V0cHV0KCkgdmlld3BvcnRBY3RpdmF0ZWQgPSBuZXcgRXZlbnRFbWl0dGVyPHN0cmluZz4oKTtcbiAgQE91dHB1dCgpIGltYWdlTG9hZGVkID0gbmV3IEV2ZW50RW1pdHRlcjx2b2lkPigpO1xuXG4gIGdldCByZW5kZXJpbmdFbmdpbmUoKSB7XG4gICAgcmV0dXJuIHRoaXMuY3NTZXJ2aWNlLmdldFJlbmRlcmluZ0VuZ2luZSgpO1xuICB9XG5cbiAgZ2V0IHZpZXdwb3J0SWRzKCkge1xuICAgIHJldHVybiB0aGlzLnZpZXdwb3J0SW5wdXRzLm1hcCgodmFsdWUpID0+IHZhbHVlLnZpZXdwb3J0SWQhKTtcbiAgfVxuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgZWxlbWVudFJlZjogRWxlbWVudFJlZixcbiAgICBwcml2YXRlIGltYWdlSWRTZXJ2aWNlOiBJbWFnZUlkU2VydmljZSxcbiAgICBwcml2YXRlIGNzU2VydmljZTogQ29ybmVyc3RvbmVTZXJ2aWNlLFxuICAgIHByaXZhdGUgY2RyOiBDaGFuZ2VEZXRlY3RvclJlZixcbiAgKSB7fVxuXG4gIG5nT25Jbml0KCk6IHZvaWQge1xuICAgIC8vIOWIneWni+WMluaXtuiusOW9leW9k+WJjeeahHZpZXdwb3J0VHlwZVxuICAgIHRoaXMuaW5pdFJlc2l6ZU9ic2VydmVyKCk7XG4gICAgdGhpcy5wcmV2aW91c1ZpZXdwb3J0VHlwZSA9IHRoaXMuaW1hZ2VJbmZvPy52aWV3cG9ydFR5cGU7XG4gICAgdGhpcy5pbml0Q29tcG9uZW50c1RyYWNraW5nKCk7XG4gICAgLy8gdGhpcy5nZW5lcmF0ZVZpZXdwb3J0cygpO1xuXG4gICAgLy8g6K6+572u5Yid5aeL5YyW5qCH5b+X77yM562J5b6Fdmlld3BvcnTliJ3lp4vljJblkI7lho3muLLmn5NcbiAgICBpZiAodGhpcy5pbWFnZUluZm8pIHtcbiAgICAgIHRoaXMucGVuZGluZ0ltYWdlUmVuZGVyJC5uZXh0KHRydWUpO1xuICAgIH1cblxuICAgIGlmICh0aGlzLnNlZ21lbnRJbmZvKSB7XG4gICAgICB0aGlzLnBlbmRpbmdTZWdtZW50UmVuZGVyJC5uZXh0KHRydWUpO1xuICAgIH1cbiAgfVxuXG4gIG5nQWZ0ZXJWaWV3SW5pdCgpOiB2b2lkIHtcbiAgICAvLyBWaWV3Q2hpbGTlt7Lnu4/lrozmiJDliJ3lp4vljJZcbiAgICBpZiAodGhpcy50b29sQmFyQ29tcG9uZW50KSB7XG4gICAgICAvLyDorqLpmIXlt6XlhbfmoI/nmoTliJ3lp4vljJbkuovku7ZcbiAgICAgIHRoaXMudG9vbEJhckNvbXBvbmVudC50b29sYmFySW5pdC5waXBlKHRha2VVbnRpbCh0aGlzLmRlc3Ryb3kkKSkuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgICAgY29uc29sZS5kZWJ1ZygnVG9vbGJhciBpbml0aWFsaXplZCcpO1xuICAgICAgICB0aGlzLnRvb2xiYXJJbml0aWFsaXplZCQubmV4dCh0cnVlKTtcbiAgICAgIH0pO1xuXG4gICAgICAvLyDorqLpmIXlt6XlhbfmoI/nmoTplIDmr4Hkuovku7ZcbiAgICAgIHRoaXMudG9vbEJhckNvbXBvbmVudC50b29sYmFyRGVzdHJveS5waXBlKHRha2VVbnRpbCh0aGlzLmRlc3Ryb3kkKSkuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgICAgY29uc29sZS5kZWJ1ZygnVG9vbGJhciBkZXN0cm95ZWQnKTtcbiAgICAgICAgdGhpcy50b29sYmFySW5pdGlhbGl6ZWQkLm5leHQoZmFsc2UpO1xuICAgICAgfSk7XG4