我正在使用dcm4che3开发DICOM应用程序,但是,多帧DICOM文件存在问题。我只想在一个DICOM文件(多帧DICOm文件)中转换几个JPEG图像。
我从dicom中提取了所有帧作为Jpeg图像并进行了遮罩。我想重新设置蒙版框架。
class Jpg2Dcm {
def FF = 255;
def SOF = 192;
def DHT = 196;
def DAC = 204;
def SOI = 216;
def SOS = 218;
def APP = 224;
private String charset = "ISO_IR 100";
private String transferSyntax = "1.2.840.10008.1.2.4.50";
private byte[] buffer = new byte[8192];
private int jpgHeaderLen;
private int jpgLen;
private boolean noAPPn = false;
private Attributes attrs = null;
public final void setCharset(String charset) {
this.charset = charset;
}
private final void setTransferSyntax(String uid) {
this.transferSyntax = uid;
}
private final void setNoAPPn(boolean noAPPn) {
this.noAPPn = noAPPn;
}
def convertJpegToDicom(List<String>frames,File dcmFile,isClip) {
try {
String args = [];
Jpg2Dcm jpg2Dcm = new Jpg2Dcm();
jpg2Dcm.setNoAPPn(true);
jpg2Dcm.setMetaData(dcmFile,isClip);
long start = System.currentTimeMillis();
for(int i=0;i<frames.size();i++){
jpg2Dcm.convert(new File(frames[i]), dcmFile,isClip);
}
long fin = System.currentTimeMillis();
} catch (IOException e) {
e.printStackTrace();
}
}
def setMetaData(File dcmFile,boolean isClip) throws IOException{
DicomInputStream dcmInputStream = null;
try {
dcmInputStream = new DicomInputStream(dcmFile);
this.attrs = isClip?dcmInputStream.readDataset(-1,-1):dcmInputStream.readDataset(-1, Tag.PixelData);
attrs.setString(Tag.SOPClassUID, VR.UI, attrs.getString(Tag.SOPClassUID));
//attrs.setString(524310, VR.UI, "1.2.840.10008.5.1.4.1.1.7");
ensureUS(attrs, Tag.BitsAllocated, 8);
ensureUS(attrs, Tag.BitsStored, attrs.getInt(Tag.BitsAllocated, ((this.buffer[this.jpgHeaderLen] & 0xFF) > 8) ? 16 : 8));
ensureUS(attrs, Tag.HighBit, this.attrs.getInt(Tag.BitsStored, this.buffer[this.jpgHeaderLen] & 0xFF) - 1);
ensureUS(attrs, Tag.PixelRepresentation, 0);
attrs.setString(Tag.StudyInstanceUID, VR.UI, attrs.getString(Tag.StudyInstanceUID));
attrs.setString(Tag.SeriesInstanceUID, VR.UI, attrs.getString(Tag.SeriesInstanceUID));
attrs.setString(Tag.SOPInstanceUID, VR.UI, attrs.getString(Tag.SOPInstanceUID));
/*ensureUID(attrs, Tag.StudyInstanceUID);
ensureUID(attrs, Tag.SeriesInstanceUID);
ensureUID(attrs, Tag.SOPInstanceUID);*/
Date now = new Date();
attrs.setDate(524306, VR.DA, [now] as Date[]);
attrs.setDate(524307, VR.TM, [now] as Date[]);
}finally{
dcmInputStream.close();
}
}
def convert(File jpgFile, File dcmFile,boolean isClip) throws IOException {
this.jpgHeaderLen = 0;
this.jpgLen = (int) jpgFile.length();
DataInputStream jpgInput = new DataInputStream(new BufferedInputStream(new FileInputStream(jpgFile)));
try {
if ((this.noAPPn) || (missingRowsColumnsSamplesPMI(this.attrs))) {
readHeader(this.attrs, jpgInput);
}
def tranferSyntaxUid = isClip?UID.RLELossless:UID.JPEGBaseline1
Attributes fmi = attrs.createFileMetaInformation(tranferSyntaxUid);
DicomOutputStream dos = new DicomOutputStream(dcmFile);
try {
dos.writeDataset(fmi, attrs);
dos.writeHeader(Tag.PixelData, VR.OB, -1);
dos.writeHeader(Tag.Item, null, 0);
Long tempHeaderLength = this.jpgLen + 1 & 0xFFFFFFFE
int headerLength = tempHeaderLength.intValue()
dos.writeHeader(Tag.Item, null, headerLength);
dos.write(this.buffer, 0, this.jpgHeaderLen);
int r;
while ((r = jpgInput.read(this.buffer)) > 0) {
dos.write(this.buffer, 0, r);
}
if (((this.jpgLen & 0x1) != 0)) {
dos.write(0);
}
dos.writeHeader(Tag.SequenceDelimitationItem, null, 0);
} finally {
dos.close();
}
} finally {
jpgInput.close();
}
System.out.println("Done!!!");
}
private boolean missingRowsColumnsSamplesPMI(Attributes attrs) {
boolean isMissing = ((!(attrs.containsValue(2621456))) || (!(attrs.containsValue(2621457)))
|| (!(attrs.containsValue(2621442))) || (!(attrs.containsValue(2621444))));
return isMissing;
}
def readHeader(Attributes attrs, DataInputStream jpgInput) throws IOException {
if ((jpgInput.read() != FF) || (jpgInput.read() != SOI) || (jpgInput.read() != FF)) {
throw new IOException("JPEG stream does not start with FF D8 FF");
}
int marker = jpgInput.read();
boolean seenSOF = false;
this.buffer[0] = (byte) FF;
this.buffer[1] = (byte) SOI;
this.buffer[2] = (byte) FF;
this.buffer[3] = (byte) marker;
this.jpgHeaderLen = 4;
while (marker != SOS) {
int segmLen = jpgInput.readUnsignedShort();
if (this.buffer.length < this.jpgHeaderLen + segmLen + 2) {
growBuffer(this.jpgHeaderLen + segmLen + 2);
}
this.buffer[(this.jpgHeaderLen++)] = (byte) (segmLen >>> 8);
this.buffer[(this.jpgHeaderLen++)] = (byte) segmLen;
jpgInput.readFully(this.buffer, this.jpgHeaderLen, segmLen - 2);
if (((marker & 0xF0) == SOF) && (marker != DHT) && (marker != DAC)) {
seenSOF = true;
int p = this.buffer[this.jpgHeaderLen] & 0xFF;
int y = (this.buffer[(this.jpgHeaderLen + 1)] & 0xFF) << 8 | this.buffer[(this.jpgHeaderLen + 2)] & 0xFF;
int x = (this.buffer[(this.jpgHeaderLen + 3)] & 0xFF) << 8 | this.buffer[(this.jpgHeaderLen + 4)] & 0xFF;
int nf = this.buffer[(this.jpgHeaderLen + 5)] & 0xFF;
attrs.setInt(Tag.SamplesPerPixel, VR.US, [nf] as int[]);
if (nf == 3) {
attrs.setString(Tag.PhotometricInterpretation, VR.CS, "YBR_FULL_422");
attrs.setInt(Tag.PlanarConfiguration, VR.US, [0] as int[]);
} else {
attrs.setString(Tag.PhotometricInterpretation, VR.CS, "MONOCHROME2");
}
attrs.setInt(Tag.Rows, VR.US, [y] as int[]);
attrs.setInt(Tag.Columns, VR.US, [x] as int[]);
attrs.setInt(Tag.BitsAllocated, VR.US, [(p > 8) ? 16 : 8] as int[]);
attrs.setInt(Tag.BitsStored, VR.US, [p] as int[]);
attrs.setInt(Tag.HighBit, VR.US, [p - 1] as int[]);
attrs.setInt(Tag.PixelRepresentation, VR.US, [0] as int[]);
}
if ((this.noAPPn & (marker & 0xF0) == APP)) {
this.jpgLen -= segmLen + 2;
this.jpgHeaderLen -= 4;
} else {
this.jpgHeaderLen += segmLen - 2;
}
if (jpgInput.read() != FF) {
throw new IOException("Missing SOS segment in JPEG stream");
}
marker = jpgInput.read();
this.buffer[(this.jpgHeaderLen++)] = (byte) FF;
this.buffer[(this.jpgHeaderLen++)] = (byte) marker;
}
if (!(seenSOF))
throw new IOException("Missing SOF segment in JPEG stream");
}
private void growBuffer(int minSize) {
int newSize = this.buffer.length << 1;
while (newSize < minSize) {
newSize <<= 1;
}
byte[] tmp = new byte[newSize];
System.arraycopy(this.buffer, 0, tmp, 0, this.jpgHeaderLen);
this.buffer = tmp;
}
private void ensureUID(Attributes attrs, int tag) {
if (!(attrs.containsValue(tag)))
attrs.setString(tag, VR.UI, UIDUtils.createUID());
}
private void ensureUS(Attributes attrs, int tag, int val) {
if (!(attrs.containsValue(tag)))
attrs.setInt(tag, VR.US, [val] as int[]);
}
}