DICOM文件头中,包括128个00H字节的文件前言,和4字节(44,49,43,4D)的DICOM文件前缀,即DICM。我们可以通过魔数校验去判断文件是否是DICOM文件。
步骤如下:
public class DicomTest {
public static void main(String[] args) throws Exception {
// 存放DICOM文件128个00H字节的文件前言 + 4字节的DICOM文件前缀
byte[] b = new byte[132];
FileInputStream fis = new FileInputStream("F:/DicomImage/test.dcm");
fis.read(b, 0, 132);
IOUtils.closeQuietly(fis);
// 存放DICOM文件魔数,结果得到的字节数组为[68, 73, 67, 77]
byte[] dicomMagicNum = new byte[4];
for (int i = 128; i < b.length; i++) {
dicomMagicNum[i - 128] = b[i];
}
// 获取十六进制字符串,即44,49,43,4D
System.out.println(byteToHexString(dicomMagicNum));
// 获取字符串,即DICM
System.out.println(new String(dicomMagicNum, "UTF-8"));
}
public static String byteToHexString(byte[] bytes) {
if (ArrayUtils.isEmpty(bytes)) {
return null;
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < bytes.length; i++) {
int hex = bytes[i] & 0xFF;
String hs = Integer.toHexString(hex);
if (hs.length() < 2) {
sb.append(0);
}
sb.append(hs);
}
return sb.toString();
}
}
通过dcm4che工具上传文件时,也会判断是否是dicom文件。
源码如下:
private void guessTransferSyntax() throws IOException {
byte[] b128 = new byte[128];
byte[] buf = buffer;
mark(132);
int rlen = read(b128);
if (rlen == 128) {
read(buf, 0, 4);
if (buf[0] == 'D' && buf[1] == 'I'
&& buf[2] == 'C' && buf[3] == 'M') {
preamble = b128.clone();
if (!markSupported()) {
hasfmi = true;
tsuid = UID.ExplicitVRLittleEndian;
bigEndian = false;
explicitVR = true;
return;
}
mark(128);
read(b128);
}
}
if (rlen < 8
|| !guessTransferSyntax(b128, rlen, false)
&& !guessTransferSyntax(b128, rlen, true))
throw new DicomStreamException(NOT_A_DICOM_STREAM);
reset();
hasfmi = TagUtils.isFileMetaInformation(
ByteUtils.bytesToTag(b128, 0, bigEndian));
}
private boolean guessTransferSyntax(byte[] b128, int rlen, boolean bigEndian)
throws DicomStreamException {
int tag1 = ByteUtils.bytesToTag(b128, 0, bigEndian);
VR vr = ElementDictionary.vrOf(tag1, null);
if (vr == VR.UN)
return false;
if (ByteUtils.bytesToVR(b128, 4) == vr.code()) {
this.tsuid = bigEndian ? UID.ExplicitVRBigEndianRetired
: UID.ExplicitVRLittleEndian;
this.bigEndian = bigEndian;
this.explicitVR = true;
return true;
}
int len = ByteUtils.bytesToInt(b128, 4, bigEndian);
if (len < 0 || 8 + len > rlen)
return false;
if (bigEndian)
throw new DicomStreamException(IMPLICIT_VR_BIG_ENDIAN);
this.tsuid = UID.ImplicitVRLittleEndian;
this.bigEndian = false;
this.explicitVR = false;
return true;
}