先上代码
引用依赖
<dependency>
<groupId>org.dcm4che</groupId>
<artifactId>dcm4che-core</artifactId>
<version>5.24.0</version>
</dependency>
try (DicomInputStream dis = openDicomInputStream()) {
dis.readDataset(-1, Tag.PixelData);
if (dis.tag() != Tag.PixelData || dis.length() != -1 || !dis.readItemHeader())
throw new IOException("No or incorrect encapsulated compressed pixel data in requested object");
dis.skipFully(dis.length());
LOG.debug("Start writing compressed pixel data");
while (dis.readItemHeader())
StreamUtils.copy(dis, out, dis.length());
LOG.debug("Finished writing compressed pixel data ");
} catch (Exception e) {
throw new IOException(e.getMessage());
}
如下是dicom查看器看到的数据:
上面代码里openDicomInputStream()方法是获取Dicom输入流,这里不做过多讲解,若想了解,有其他博文详细讲解。下面说明一下代码逻辑。
dis.readDataset(-1, Tag.PixelData);
设置将读取的指针指向指定的tag位置。len:最大读取字节数,若为-1则读取到最后。tag:读取截至到的tag。
dis.tag()
获取当前正在读取tag。
dis.length()
获取当前tag对应数据字节数。初始值为-1。
第一个 dis.readItemHeader()
在调用此方法前,输入流读取的指针已经读取到图像数据tag对应的value处了。上面两个方法就是用来判断此要求的。
同时此方法会读取图像数据中的第一个item数据包括tag(4B)、length(4B) 共8个字节,并设置当前length为读出的数值。
dis.skipFully(dis.length())
此步骤是跳过当前tag对应的value数据字节。
while (dis.readItemHeader())
此处的dis.readItemHeader(),是为了读取第二个item中的tag(4B)、length(4B) 共8个字节,读出的length数值就是图像数据总字节数,完成此方法后,输入流的指针便指向了图像数据的第一个字节了。
StreamUtils.copy(dis, out, dis.length());
将从dicom输出流中,从图像数据开始位置,读取上面获取到的length长度的字节数,再输出到输出流写出。
以上是自己通过看源码得到理解,若有不对之处,欢迎指正。更详细的原理请查看源码。