跳到主要内容

进阶选项

取回阶段和取回选项都还有一些更进阶的选项, 可以用来定制渐进式加载的行为。

提示

如果你(暂时)对进阶选项不感兴趣,可以跳过本节, 直接去看用法一节。基本上,这里的一部分选项 (position、decimate、offset、priority 和 nearbyFrames) 用在了「体数据渐进式加载」那个示例中,你之后可以再回来看。

进阶的取回阶段选项​

positions?: number[];​

用于体数据渐进式加载——这时我们需要指定想取回的确切影像索引。 在通用的挂片协议中一般都是这样,因为初始影像通常位于堆栈的中间、顶部或底部。

你可以用绝对位置,也可以用 [0, 1] 之间的相对位置。 小于 0 的位置是相对末尾而言的,所以可以用 -1 表示堆栈中的最后一张影像。

示例

stages: [
{
id: 'initialImages',
positions: [0.5, 0, -1],
retrieveType: 'initial', // 如前所述,名字可以随意取
},
];

上面这个例子里,我们请求的是堆栈中间那张、第一张,以及最后一张影像。

提示

若要根据初始显示位置自动取回另一张初始影像, 可以把这些阶段复制一份,并在最前面加上一个带有你所需位置的新阶段。 这可以用来确保那张初始影像被取到。

decimate?: number 与 offset?: number;​

借助 decimate 和 offset 这两个特性,我们可以更灵活地指定要取回哪些影像。 例如,如果一份体数据包含 100 张影像,那么 decimate 取 2、offset 取 0 会取回影像 0、2、4、6、8、10、12、14、16、18……; 同理,decimate 取 2、offset 取 1 会取回影像 1、3、5、7、9、11、13、15、17、19…… 这就展示了如何通过不同的 offset 和 decimate 取值来有效地交错取回影像。

重复取回同一张影像是安全的:当该影像的质量状态已经优于所指定的那次取回时, 这次取回会被丢弃。

stages: [
{
id: 'initialImages',
positions: [0.5, 0, -1],
retrieveType: 'initial', // 如前所述,名字可以随意取
},
{
id: 'initialPass',
decimate: 2,
offset: 0,
retrieveType: 'fast', // 如前所述,名字可以随意取
},
{
id: 'secondPass',
decimate: 2,
offset: 1,
retrieveType: 'fast', // 如前所述,名字可以随意取
},
];

上面有三个阶段:先取回初始影像,然后分两趟取回其余影像。 第一趟取回影像 0、2、4、6、8、10、12、14、16、18……; 第二趟取回影像 1、3、5、7、9、11、13、15、17、19……

priority?: number 与 requestType​

组合使用 requestType(thumbnail、prefetch、interaction) 和 priority(数值越小优先级越高),就能有效地为请求排定优先级。 例如你可以把初始影像的优先级设得比其余影像更高(数值更小), 这样就能保证初始影像在队列中被最先取回。

stages: [
{
id: 'initialImages',
positions: [0.5, 0, -1],
retrieveType: 'initial',
requestType: RequestType.INTERACTION,
priority: -1,
},
{
id: 'initialPass',
decimate: 2,
offset: 0,
retrieveType: 'fast',
priority: 2,
requestType: RequestType.PREFETCH,
},
{
id: 'secondPass',
decimate: 2,
offset: 1,
retrieveType: 'fast',
priority: 3,
requestType: RequestType.PREFETCH,
},
];
提示

把可同时运行的最大请求数设小一些,以确保你真正需要的那些请求被优先执行。例如:

imageLoadPoolManager.setMaxSimultaneousRequests(RequestType.INTERACTION, 6);

nearbyFrames?: NearbyFrames[];​

借助 nearbyFrames,你可以把邻近的帧填上, 从而瞬时填补并渲染出体数据中的空白处。

示例

stages: [
{
id: 'initialPass',
decimate: 2,
offset: 0,
retrieveType: 'fast',
priority: 2,
requestType: RequestType.PREFETCH,
nearbyFrames: [
{
offset: +1,
imageQualityStatus: ImageQualityStatus.ADJACENT_REPLICATE,
},
],
},
{
id: 'secondPass',
decimate: 2,
offset: 1,
retrieveType: 'fast',
priority: 3,
requestType: RequestType.PREFETCH,
},
];

上面我们指定了希望把当前帧的相邻帧(+1)复制出来。这样一来, 在下一阶段(secondPass)到来之前,我们就已经有可供渲染和显示的相邻帧了。 secondPass 随后会用真实数据把它们覆盖掉。

进阶的取回选项​

urlArguments​

  • urlArguments —— 要附加到 URL 上的一组参数
    • 它把这次请求与其他无法与之合并的请求区分开
    • DICOMweb 标准允许用 accept 参数来指定内容类型
    • HTJ2K 的内容类型是 image/jhc

对应的配置是(假定服务端支持基于标准的 DICOMweb):

retrieveOptions: {
default: {
urlArguments: 'accept=image/jhc',
rangeIndex: -1,
},
multipleFast: {
urlArguments: 'accept=image/jhc',
rangeIndex: 0,
decodeLevel: 0,
},
},
注意

在一次范围请求的各个阶段中,你必须重复写上相同的 framesPath 和 urlArguments;否则系统会认为第一个范围取到的数据与第二个范围取到的 不是同一份数据,于是第二次范围请求会直接把整个请求重新取一遍。

framePath​

  • framesPath —— 用于改写 URL 的路径部分

这在需要取回另一条可用路径时很有用,例如缩略图、JPIP, 或用于有损编码取回的 rendered 端点——因为它们所在的路径 与无损编码影像的路径不同。

它同样有助于与那些「固定路径的替代编码服务器」集成—— 那类服务器依据 URL 路径来决定返回哪个响应, 并把各种有损渲染结果存放在不同路径上。

imageQualityStatus​

  • imageQualityStatus —— 用于把取回状态设为有损或亚分辨率

它通常用在这种情形:URL 或取回参数指定了该路径下某种有损的最终渲染结果, 例如有损编码的 HTJ2K 影像。

为亚分辨率影像使用独立 URL​

字节范围请求之外的另一种做法,是为一张完整但有损 / 低分辨率的影像 发出一个不同的请求。如果 DICOMweb 支持 JPIP,这可以是基于标准的; 但更常见的是非标准做法——为低分辨率取回使用一条单独的路径。

对这里展示的 JPIP 做法来说,JPIP 服务器必须暴露一个端点, 其路径与普通像素数据端点完全一致,只是结尾改为 /jpip?target=<FRAMENO>,并且支持 fsiz 参数。参见 DICOM 标准的 Part 5 和 Part 18。

对非标准路径的做法来说,前提假设是:除了常规的 /frames 端点之外, 还存在与之相关的其他端点,只是 URL 中 /frames/ 那一段被换成了别的值。 例如可以借此取回 stackProgressive 示例中所用的 /jlsThumbnail/ 数据。

JPIP 的一份配置示例:

retrieveOptions: {
default: {
// 需要在这里注明这是有损编码,因为仅凭这里的通用配置
// 是无法检测出来的。
imageQualityStatus: ImageQualityStatus.SUBRESOLUTION,
// 一个假想的 JPIP 服务器,其路径就是常规 DICOMweb 路径,
// 只是把 /frames 那一段换成了 /jpip?target=
// 这里用的是基于标准的 JPIP target 参数,
// 并把帧号作为它的取值。
framesPath: '/jpip?target=',
// 基于标准的 fsiz 参数用于取回一张亚分辨率影像
urlArguments: 'fsiz=128,128',
},
},