dicom-parser结合canvas渲染影像

4 阅读2分钟

dicom-parser

dicom-parser 是一个轻量级库,用于解析 DICOM P10 字节流,以及原始(未封装在第 10 部分)字节流,适用于基于 HTML5 的现代浏览器(IE10+)。 Node.js和流星。dicomParser 快速、易用,且没有必要的外部依赖。

安装

1. yarn add dicom-parser
or
2.npm i dicom-parser

用法

dicom-parser核心作用就是在网页中解析原始的、二进制的DICOM文件,把人类看不懂的字节码,转换成程序可读的JavaScript对象

const byteArray = new Uint8Array(arrayBuffer)
const dataSet = dicomParser.parseDicom(byteArray);

dataSet就是dicom-parser解析 DICOM 二进制文件后返回的核心结果,并返回四个东西

  1. byteArray原始二进制数据
  2. byteArrayParser二进制解析工具
  3. elements解析出的所有 DICOM 标签
  4. warnings解析过程中的警告

代码

 const rows = dataSet.uint16('x00280010');   // 图像高度
 const cols = dataSet.uint16('x00280011');   // 图像宽度
 const bitsAllocated = dataSet.uint16('x00280100'); // 每个像素占用的位数,通常是 8 或 16
 const pixelRepresentation = dataSet.uint16('x00280103'); // 0=无符号,1=有符号
 const pixelDataElement = dataSet.elements.x7fe00010;
 let pixelData;
 if (bitsAllocated === 16) {
    // 根据像素表示选择有符号或无符号的 16 位数组
    pixelData = pixelRepresentation === 1 ?
    new Int16Array(dataSet.byteArray.buffer, pixelDataElement.dataOffset, pixelDataElement.length / 2) :
    new Uint16Array(dataSet.byteArray.buffer, pixelDataElement.dataOffset, pixelDataElement.length / 2);
 } else if (bitsAllocated === 8) {
    pixelData = new Uint8Array(dataSet.byteArray.buffer, pixelDataElement.dataOffset, pixelDataElement.length);
 } else {
    throw new Error('不支持的 BitsAllocated 值');
 }
 
// 获取 Canvas 元素并设置其尺寸
const canvas = document.getElementById('myCanvas');
canvas.width = cols;
canvas.height = rows;
const ctx = canvas.getContext('2d');

// 创建一个 ImageData 对象,用于存放 RGBA 值
const imageData = ctx.createImageData(cols, rows);
console.log(imageData, cols, rows)
// 计算最小和最大像素值,用于归一化(这里以 16 位图像为例)
let min = Infinity, max = -Infinity;
for (let i = 0; i < pixelData.length; i++) {
  const val = pixelData[i];
  if (val < min) min = val;
  if (val > max) max = val;
}
const range = max - min;

// 将像素数据转换为 RGBA 值并填入 imageData
for (let i = 0; i < pixelData.length; i++) {
  // 将像素值归一化到 0-255 范围
  const normalized = ((pixelData[i] - min) / range) * 255;
  // 灰度图像的 R, G, B 通道值相同
  imageData.data[i * 4] = normalized;     // R
  imageData.data[i * 4 + 1] = normalized; // G
  imageData.data[i * 4 + 2] = normalized; // B
  imageData.data[i * 4 + 3] = 255;        // Alpha (不透明)
}

// 将处理好的 imageData 绘制到 Canvas 上
ctx.putImageData(imageData, 0, 0);

最终效果

image.png

地址