网上查了许多资料,比较少有能用Java把普通的图片转成dicom文件(.dcm
)的方法。
这里提供一个自己整合的 直接可用的转换方法,主要用了dcm4che。这是一个现在还在持续更新,功能还算较全面的Java版Dicom处理工具了,里面有很多小工具可以根据自己的项目改编使用。其中就有一个工具是jpg2dcm
,满足从jpg
图片转成.dcm
文件,然后我根据自己的需求改写了方法,使其整合到一个通用的springboot项目中。这个方法其实还可以转视频文件到dicom文件,只不过我这里只满足图片转dicom的需求所以暂时删除了,但可以根据需要很方便的添加上:)
Dependencies
-
JDK 1.8
-
dcm4che-core:5.22.4
-
dcm4che-imageio:5.22.4
-
dcm4che-tool-common:5.22.4
-
commons-cli:1.4
Code
工具类
/*
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is part of dcm4che, an implementation of DICOM(TM) in
* Java(TM), hosted at https://github.com/dcm4che.
*
* The Initial Developer of the Original Code is
* J4Care.
* Portions created by the Initial Developer are Copyright (C) 2015-2019
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* See @authors listed below
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
*/
/**
* Original package:
* https://github.com/dcm4che/dcm4che/blob/master/dcm4che-tool/dcm4che-tool-jpg2dcm/src/main/java/org/dcm4che3/tool/jpg2dcm/Jpg2Dcm.java
*/
package org.demo.com.util;
import org.dcm4che3.data.*;
import org.dcm4che3.imageio.codec.XPEGParser;
import org.dcm4che3.imageio.codec.jpeg.JPEGParser;
import org.dcm4che3.io.DicomOutputStream;
import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.ByteChannel;
import java.nio.channels.SeekableByteChannel;
import java.nio.file.*;
public class Jpg2DcmUtil {
private static final int BUFFER_SIZE = 8162;
private static byte[] buf = new byte[BUFFER_SIZE];
public static void convert(Path srcFilePath, Path destFilePath, Attributes metaData) throws Exception {
Attributes fileMetadata = new Attributes();
fileMetadata.addAll(metaData);
try (SeekableByteChannel channel = Files.newByteChannel(srcFilePath);
DicomOutputStream dos = new DicomOutputStream(destFilePath.toFile())) {
XPEGParser parser = new JPEGParser(channel);
parser.getAttributes(fileMetadata);
dos.writeDataset(fileMetadata.createFileMetaInformation(parser.getTransferSyntaxUID()), fileMetadata);
dos.writeHeader(Tag.PixelData, VR.OB, -1);
dos.writeHeader(Tag.Item, null, 0);
copyPixelData(channel, parser.getCodeStreamPosition(), dos);
dos.writeHeader(Tag.SequenceDelimitationItem, null, 0);
System.out.println("converted");
}
}
private static void copyPixelData(SeekableByteChannel channel, long position, DicomOutputStream dos, byte... prefix)
throws IOException {
long codeStreamSize = channel.size() - position + prefix.length;
dos.writeHeader(Tag.Item, null, (int) ((codeStreamSize + 1) & ~1));
dos.write(prefix);
channel.position(position);
copy(channel, dos);
if ((codeStreamSize & 1) != 0)
dos.write(0);
}
private static void copy(ByteChannel in, OutputStream out) throws IOException {
ByteBuffer bb = ByteBuffer.wrap(buf);
int read;
while ((read = in.read(bb)) > 0) {
out.write(buf, 0, read);
bb.clear();
}
}
}
应用
package org.demo.com.service;
import org.demo.com.util.Jpg2DcmUtil;
import org.dcm4che3.data.*;
import org.dcm4che3.util.UIDUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Map;
@Service
public class DicomService {
private static final ElementDictionary DICT = ElementDictionary.getStandardElementDictionary();
private static final int[] TYPE2_TAGS = {
Tag.ContentDate,
Tag.ContentTime
};
public void convertJpg2Dcm(String srcPath, String destPath) throws Exception {
// 根据需求加入dicom里的tag信息
Attributes staticMetadata = new Attributes();
// set ID
staticMetadata.setString(Tag.StudyInstanceUID, VR.UI, UIDUtils.createUID());
staticMetadata.setString(Tag.SeriesInstanceUID, VR.UI, UIDUtils.createUID());
staticMetadata.setString(Tag.SOPInstanceUID, VR.UI, UIDUtils.createUID());
// patient info
setMetadata(staticMetadata, Tag.PatientName, "Test Patient");
setMetadata(staticMetadata, Tag.PatientID, "Test Patient");
setMetadata(staticMetadata, Tag.PatientSex, "M");
setMetadata(staticMetadata, Tag.PatientAge, "50");
setMetadata(staticMetadata, Tag.PatientBirthDate, "19500101");
// study info
setMetadata(staticMetadata, Tag.StudyDate, "20100101");
setMetadata(staticMetadata, Tag.StudyTime, "123");
setMetadata(staticMetadata, Tag.StudyDescription, "Study Description");
setMetadata(staticMetadata, Tag.StudyID, "123");
// series info
setMetadata(staticMetadata, Tag.SeriesDate, "20100101");
setMetadata(staticMetadata, Tag.SeriesTime, "123");
setMetadata(staticMetadata, Tag.SOPClassUID, UID.SecondaryCaptureImageStorage);
supplementType2Tags(staticMetadata);
// convert jpeg files to dicom files
Path src = Paths.get(srcPath);
Path dest = Paths.get(destPath);
Jpg2DcmUtil.convert(src, dest, staticMetadata);
}
private void setMetadata(Attributes metadata, int tag, String value) {
// if (!metadata.containsValue(tag))
if (value != null)
metadata.setString(tag, DICT.vrOf(tag), value);
}
private void supplementType2Tags(Attributes metadata) {
for (int tag : TYPE2_TAGS)
if (!metadata.contains(tag))
metadata.setNull(tag, DICT.vrOf(tag));
}
}
如果是其它图片格式(比如png
),可以先转成jpeg
或者jpg
,就可以进行一步转化了。