当前位置: 首页 > news >正文

Cornerstone加载本地Dicom文件第二弹 - Blob篇

🍀 引言

当我们刚接触Cornerstone或拿到一组Dicom文件时,如果没有ImageID和后台接口,可能只是想简单测试Cornerstone能否加载这些Dicom文件。在这种情况下,可以使用本地文件加载的方法。之前我们介绍了通过node启动服务器请求文件,在本地提供接口的方式。今天,我们再介绍一下另一种实现方式——直接使用文件输入框点击上传文件,通过文件流让Cornerstone加载并渲染这些Dicom文件。以下将围绕实现效果、实现思路及具体流程展开。

🔥 效果速览

本篇整体相关代码已更新至代码库:https://github.com/jianyaoo/vue-cornerstone-demo/blob/main/src/views/basicUsage/LocalFile.vue,欢迎Star。
实现效果如下:
请添加图片描述

⛳️ 具体实现流程

实现流程

我们想要通过点击input文件框上传本地的文件进行渲染,在进行实际开发前,我们先梳理一下大概的思路:

  1. 需要一个 type 为file 的 input 输入框组件,点击上传选择本地要渲染的Dicom文件

  2. 我们可能想要展示一张Dicom或者一组Dicom文件,所以 input 需要设置多选属性

  3. 监听文件更改事件,当上传文件后进行渲染

  4. 将本地上传的file文件流传递给Cornerstone进行渲染(核心步骤,Cornerstone如何渲染Blob文件流

按照上面的流程,我们就开始准备写代码

UI组件

<div class="form"><label for="">点击上传文件:</label><inputtype="file"multiple@change="handleChange">
</div>

监听文件改变

function handleChange(evt) {// 阻止事件冒泡evt.stopPropagation();// 阻止默认事件evt.preventDefault();// 更新文件前清除之前的缓存,避免更新上传文件时直接从缓存中获取Volume对象cache.purgeCache();const files = evt.target.files;const imageIds = [];Array.from(files).forEach(file => {// 将文件流放到dicomLoader的文件管理器中并返回对应的ImageID => Blob流加载的核心代码1const imageId = cornerstoneDICOMImageLoader.wadouri.fileManager.add(file);imageIds.push(imageId);});// 渲染ImageidloadAndViewImage(imageIds);
}

在监听文件改变的代码中,核心代码主要有2点:

  • 在每次更新文件时进行缓存清除:cache.purgeCache(),避免再次上传文件时由于VolumeId没有改变而导致直接从缓存中获取数据

  • 获取到file文件流后,可以通过 cornerstoneDICOMImageLoader 的fileManager对象将文件流转换成ImageId,我们可以看一下fileManager中的相关方法,通过add方法将我们上传的文件流添加到文件列表中,并获取到以 dicomfile 为前缀的ImageId

// 单例文件列表,用于管理上传的文件列表
let files: Blob[] = [];// add:向文件列表中添加文件并返回指定格式的ImageId
// 注意这里返回的id前缀,后面解析的代码中会用这个前缀作为本地文件加载的标志。
function add(file: Blob): string {const fileIndex = files.push(file);return `dicomfile:${fileIndex - 1}`;
}// get: 根据文件索引值获取文件流
function get(index: number): Blob {return files[index];
}// remove: 根据文件索引值删除文件
function remove(index: number): void {files[index] = undefined;
}// purge: 清空文件列表
function purge(): void {files = [];
}export default {add,get,remove,purge,
};

根据ImageId加载渲染影像

  • 加载图像
async function loadAndViewImage(imageIds) {await prefetchMetadataInformation(imageIds);if (type.value === "stack") {await renderStack(imageIds);} else {await renderVolume(imageIds);}
}async function prefetchMetadataInformation(imageIdsToPrefetch) {for (let i = 0; i < imageIdsToPrefetch.length; i++) {// 通过loadImage加载文件await cornerstoneDICOMImageLoader.wadouri.loadImage(imageIdsToPrefetch[i]).promise;}
}
  • 渲染栈图像
async function renderStack(imageIds) {if (imageIds?.length === 0) {return;}const renderingEngine = getRenderingEngine(renderingEngineId);const viewportInput = {viewportId: viewportId0,type: csEnums.ViewportType.STACK,element: document.querySelector("#element0")};renderingEngine.enableElement(viewportInput);const toolGroup = ToolGroupManager.getToolGroup(groupId);toolGroup.addViewport(viewportId0, renderingEngineId);const viewport = renderingEngine.getViewport(viewportId0);await viewport.setStack(imageIds);activeTools();viewport.render();
}
  • 渲染Volume图像
async function renderVolume(imageIds) {...以上初始化内容省略,完整代码可在git中查看const volume = await volumeLoader.createAndCacheVolume(volumeId, {imageIds});volume.load();await setVolumesForViewports(renderingEngine,[{volumeId}],[viewportId1, viewportId2, viewportId3]);activeTools();renderingEngine.render();
}

我们在使用 add() 函数返回的ImageId直接渲染前,还需要使用loadImage加载图像 cornerstoneDICOMImageLoader.wadouri.loadImage(imageId),那接下来我们看一下loadImage函数是如何执行并获取到文件的。以下是loadImage函数的简约版代码(整体源码可在Cornerstone 官方git:https://github.com/cornerstonejs/cornerstone3D/blob/d8f12e46d478b251c5515b3ee960629dd4e5d6e2/packages/dicomImageLoader/src/imageLoader/wadouri/loadImage.ts文件中查看)

function loadImage(imageId: string,options: DICOMLoaderImageOptions = {}
): Types.IImageLoadObject {const parsedImageId = parseImageId(imageId);... const schemeLoader = getLoaderForScheme(parsedImageId.scheme);...const dataSetPromise = dataSetCacheManager.load(parsedImageId.url,schemeLoader,imageId);return loadImageFromPromise(dataSetPromise,imageId,parsedImageId.frame,parsedImageId.url,options);
}
  • 对ImageId进行解析,获取到ImageId的加载规则等信息
    请添加图片描述

  • 根据解析到的ImageId theme属性获取加载方式,如果是正常接口的ImageId,使用的是xhrRequest HTTP请求,对于我们上传文件的为loadFileRequest请求,由上文我们可以得到add()函数返回的ImageId格式为dicomfile:${fileIndex - 1}
    请添加图片描述

  • 获取到加载方式后,我们可以看一下loadFileRequest函数是如何加载文件的。通过解析ImageId可以获取到对应的文件Blob,读取并返回文件流

请添加图片描述

在获取到文件流后还会有一系列的dicom文件处理与从接口返回操作一致,这里就不展开详细说明了,大致流程如下,后续学习源码时会展开详细说明。

请添加图片描述

🌾 结语

由此,一个点击上传本地文件的Demo演示就结束了,主要知识点为

  • cornerstoneDICOMImageLoader.wadouri.fileManager对象管理本地上传的文件并可以返回ImageId

  • cornerstoneDICOMImageLoader.wadouri.loadImage 可以根据不同的请求规则调用不同的请求方式,用于加载处理文件

配套可运行代码演示:https://github.com/jianyaoo/vue-cornerstone-demo clone到本地后直接运行 npm run serve 即可启动,持续更新,欢迎star~

相关文章:

Cornerstone加载本地Dicom文件第二弹 - Blob篇

&#x1f340; 引言 当我们刚接触Cornerstone或拿到一组Dicom文件时&#xff0c;如果没有ImageID和后台接口&#xff0c;可能只是想简单测试Cornerstone能否加载这些Dicom文件。在这种情况下&#xff0c;可以使用本地文件加载的方法。之前我们介绍了通过node启动服务器请求文件…...

C语言中整数类型及其类型转换

1.数据的存储和排列 是的&#xff0c;在C语言中&#xff0c;整数类型通常以补码&#xff08;twos complement&#xff09;形式存储在内存中。这是因为补码表示法在处理有符号整数的加减运算上更为简便和高效。 2.有符号数和无符号数之间的转换 在C语言中&#xff0c;有符号数和…...

powerjob连接postgresql数据库(支持docker部署)

1.先去pg建一个powerjob-product库 2.首先去拉最新的包&#xff0c;然后找到server模块&#xff0c;把mysql的配置文件信息替换成pg的 spring.datasource.hikari.auto-committrue spring.datasource.remote.hibernate.properties.hibernate.dialecttech.powerjob.server.pers…...

浅谈位运算及其应用(c++)

目录 一、位运算的基础&#xff08;一&#xff09;位与&#xff08;&&#xff09;&#xff08;二&#xff09;位或&#xff08;|&#xff09;&#xff08;三&#xff09;位异或&#xff08;^&#xff09;&#xff08;四&#xff09;位取反&#xff08;~&#xff09;&#x…...

Git版本管理中下列不适于Git的本地工作区域的是

Git版本管理中下列不适于Git的本地工作区域的是 A. 工作目录 B. 代码区 C. 暂存区 D. 资源库 选择B Git本地有四个工作区域&#xff1a; 工作目录&#xff08;Working Directory&#xff09;、 暂存区(Stage/Index)、 资源库(Repository或Git Directory)、 git仓库(Remote Di…...

webGL + WebGIS + 数据可视化

webGL&#xff1a; 解释&#xff1a;用于在浏览器中渲染 2D 和 3D 图形。它是基于 OpenGL ES 的&#xff0c;提供了直接操作 GPU 的能力。 库&#xff1a; Three.jsBabylon.jsPixiJSReglGlMatrixOsgjs WebGIS&#xff1a; 解释&#xff1a;用于在 Web 浏览器中处理和展示地…...

职场“老油条”的常规操作,会让你少走许多弯路,尤其这三点

有句话说得好&#xff1a;“在成长的路上&#xff0c;要么受教育&#xff0c;要么受教训。” 挨过打才知道疼&#xff0c;吃过亏才变聪明&#xff0c;从职场“老油条”身上能学到很多经验&#xff0c;不一定全对&#xff0c;但至少有可以借鉴的地方&#xff0c;至少能让你少走…...

Ceres Cuda加速

文章目录 一、简介二、准备工作三、实现代码四、实现效果参考资料一、简介 字Ceres2.2.1版本之后,作者针对于稠密矩阵的分解计算等操作进行了Cuda加速,因此这里就基于此项改动测试一下效果。 二、准备工作 1、首先是需要安装Cuda这个英伟达第三方库,https://developer.nvidi…...

微信小程序生成小程序转发链接,携带参数跳转到另外一个页面

🤵 作者:coderYYY 🧑 个人简介:前端程序媛,目前主攻web前端,后端辅助,其他技术知识也会偶尔分享🍀欢迎和我一起交流!🚀(评论和私信一般会回!!) 👉 个人专栏推荐:《前端项目教程以及代码》 ✨一、前言 需求:在页面A生成分享链接(携带参数),分享到微信…...

图解RocketMQ之消息如何存储

大家好&#xff0c;我是苍何。 人一辈子最值得炫耀的不应该是你的财富有多少&#xff08;虽然这话说得有点违心&#xff0c;呵呵&#xff09;&#xff0c;而是你的学习能力。技术更新迭代的速度非常快&#xff0c;那作为程序员&#xff0c;我们就应该拥有一颗拥抱变化的心&…...

2024年中国信创产业发展白皮书精简版

获取方式&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1rEHMfcCfJm4A40vzrewoCw?pwda5u1 提取码&#xff1a;a5u1 得益于中国数字经济的迅猛发展&#xff0c;2023年中国信创产业规模达20961.9亿元&#xff0c;2027年有望达到37011.3亿元&#xff0c;中国信创市场…...

Redis2-Redis常见命令

目录 Redis数据结构介绍 Redis通用命令 KEYS DEL EXISTS EXPIRE String类型 Key的层级格式 Hash类型 List类型 Set类型 SortedSet类型 Redis数据结构介绍 Redis是一个key-value的数据库&#xff0c;key一般是String数据库&#xff0c;value的类型多种多样 可以通过…...

一天攻克一个知识点 —— 设计模式之动态代理

一、设计模式之代理设计 代理设计是在Java开发中使用较多的一种设计模式&#xff0c;所谓的代理设计模式就是指一个代理主体操作真实主体&#xff0c;真实主体操作具体业务&#xff0c;代理主体负责给具体业务添砖加瓦。 就好比在生活中你有一套房子想要出租(你真实主体)&…...

数据采集与预处理【大数据导论】

各位大佬好 &#xff0c;这里是阿川的博客&#xff0c;祝您变得更强 个人主页&#xff1a;在线OJ的阿川 大佬的支持和鼓励&#xff0c;将是我成长路上最大的动力 阿川水平有限&#xff0c;如有错误&#xff0c;欢迎大佬指正 数据采集与预处理前 必看 【大数据导论】—大数据序…...

白骑士的PyCharm教学进阶篇 2.2 高级调试技术

系列目录 上一篇&#xff1a;白骑士的PyCharm教学进阶篇 2.1 高效编码技巧 在Python开发中&#xff0c;调试是一个非常重要的环节。PyCharm作为一款功能强大的IDE&#xff0c;不仅提供了基本的调试功能&#xff0c;还包含了许多高级调试工具与技巧。本篇将详细介绍这些高级调试…...

[网鼎杯]2018Unfinish

使用ctf在线靶场https://adworld.xctf.org.cn/home/index。 进入靶场&#xff0c;发现是一个登录页面。 使用awvs进行扫描&#xff0c;发现存在login.php和register.php&#xff0c;并且register.php存在sql注入漏洞。 访问一下register.php试试&#xff0c;发现是一个注册页面…...

Java算法-力扣leetcode-383. 赎金信

383. 赎金信 给你两个字符串&#xff1a;ransomNote 和 magazine &#xff0c;判断 ransomNote 能不能由 magazine 里面的字符构成。 如果可以&#xff0c;返回 true &#xff1b;否则返回 false 。 magazine 中的每个字符只能在 ransomNote 中使用一次。 示例 1&#xff1a…...

使用idea对spring全家桶的各种项目进行创建

目录 1. 简介2. spring2.1 简介2.2 创建 3. springmvc3.1 介绍3.2 创建 4. springboot4.1 简介4.2 创建&#xff08;仅仅就其中一种&#xff09; 5. 其他&#xff1a;maven6. 参考链接 1. 简介 因为总是分不清spring全家桶&#xff0c;所以就在这里进行一个总结。 2. spring …...

FAT32、NTFS、FAT的区别

FAT&#xff08;File Allocation Table&#xff09; 特点 簇大小限制&#xff1a;FAT文件系统的簇大小是固定的&#xff0c;这限制了单个文件的大小和文件系统的效率。 存储效率&#xff1a;由于簇大小的限制&#xff0c;FAT文件系统在存储小文件时可能会浪费空间。 文件系统结…...

捉虫笔记(二)之 杀软请你自重点

捉虫笔记&#xff08;二&#xff09;之 杀软请你自重点 前一篇文章介绍了如何配置符号&#xff0c;这一篇文章我们来个实战。 1 现象 在我们的程序中利用robocopy进行文件的复制。但是QA反馈&#xff0c;只要进行了备份操作&#xff0c;整个进程就会卡住。但是奇怪的是只有他…...

Python|GIF 解析与构建(5):手搓截屏和帧率控制

目录 Python&#xff5c;GIF 解析与构建&#xff08;5&#xff09;&#xff1a;手搓截屏和帧率控制 一、引言 二、技术实现&#xff1a;手搓截屏模块 2.1 核心原理 2.2 代码解析&#xff1a;ScreenshotData类 2.2.1 截图函数&#xff1a;capture_screen 三、技术实现&…...

C++初阶-list的底层

目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...

PPT|230页| 制造集团企业供应链端到端的数字化解决方案:从需求到结算的全链路业务闭环构建

制造业采购供应链管理是企业运营的核心环节&#xff0c;供应链协同管理在供应链上下游企业之间建立紧密的合作关系&#xff0c;通过信息共享、资源整合、业务协同等方式&#xff0c;实现供应链的全面管理和优化&#xff0c;提高供应链的效率和透明度&#xff0c;降低供应链的成…...

连锁超市冷库节能解决方案:如何实现超市降本增效

在连锁超市冷库运营中&#xff0c;高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术&#xff0c;实现年省电费15%-60%&#xff0c;且不改动原有装备、安装快捷、…...

定时器任务——若依源码分析

分析util包下面的工具类schedule utils&#xff1a; ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类&#xff0c;封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz&#xff0c;先构建任务的 JobD…...

智能在线客服平台:数字化时代企业连接用户的 AI 中枢

随着互联网技术的飞速发展&#xff0c;消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁&#xff0c;不仅优化了客户体验&#xff0c;还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用&#xff0c;并…...

Mac软件卸载指南,简单易懂!

刚和Adobe分手&#xff0c;它却总在Library里给你写"回忆录"&#xff1f;卸载的Final Cut Pro像电子幽灵般阴魂不散&#xff1f;总是会有残留文件&#xff0c;别慌&#xff01;这份Mac软件卸载指南&#xff0c;将用最硬核的方式教你"数字分手术"&#xff0…...

自然语言处理——Transformer

自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效&#xff0c;它能挖掘数据中的时序信息以及语义信息&#xff0c;但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN&#xff0c;但是…...

OpenLayers 分屏对比(地图联动)

注&#xff1a;当前使用的是 ol 5.3.0 版本&#xff0c;天地图使用的key请到天地图官网申请&#xff0c;并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能&#xff0c;和卷帘图层不一样的是&#xff0c;分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...

【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具

第2章 虚拟机性能监控&#xff0c;故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令&#xff1a;jps [options] [hostid] 功能&#xff1a;本地虚拟机进程显示进程ID&#xff08;与ps相同&#xff09;&#xff0c;可同时显示主类&#x…...