2014-03-02 40 views
1

我遇到了以下問題。我必須編寫連接到pacs並獲取圖像的小應用程序。我決定使用dcm4che工具包。我已經寫了下面的代碼: 公共類Dcm4 {Dcm4Che - 從pacs獲取圖像

/** 
* @param args the command line arguments 
*/ 
public static void main(String[] args) { 
    // TODO code application logic here 
    DcmQR dcmqr = new MyDcmQR("server"); 

    dcmqr.setCalledAET("server", true); 
    dcmqr.setRemoteHost("213.165.94.158"); 
    dcmqr.setRemotePort(104); 
    dcmqr.getKeys(); 

    dcmqr.setDateTimeMatching(true); 
    dcmqr.setCFind(true); 
    dcmqr.setCGet(true); 

    dcmqr.setQueryLevel(MyDcmQR.QueryRetrieveLevel.IMAGE); 

    dcmqr.addMatchingKey(Tag.toTagPath("PatientID"),"2011"); 
    dcmqr.addMatchingKey(Tag.toTagPath("StudyInstanceUID"),"1.2.276.0.7230010.3.1.2.669896852.2528.1325171276.917"); 
    dcmqr.addMatchingKey(Tag.toTagPath("SeriesInstanceUID"),"1.2.276.0.7230010.3.1.3.669896852.2528.1325171276.916"); 


    dcmqr.configureTransferCapability(true); 
    List<DicomObject> result=null; 
    byte[] imgTab=null; 
    BufferedImage bImage=null; 
    try { 
     dcmqr.start(); 
     System.out.println("started"); 
     dcmqr.open(); 
     System.out.println("opened"); 
     result = dcmqr.query(); 
     System.out.println("queried"); 
     dcmqr.get(result); 
     System.out.println("List Size = " + result.size()); 

     for(DicomObject dco:result){ 
      System.out.println(dco); 
      dcmTools.toByteArray(dco); 
      System.out.println("end parsing"); 
     } 

    } catch (Exception e) { 
     System.out.println("error "+e); 
    } 

    try{ 
     dcmqr.stop(); 
     dcmqr.close(); 
    }catch (Exception e) { 

    } 

    System.out.println("done"); 
} 
} 

一切似乎是罰款,直到我打電話dcmTools.toByteArray(DCO)。 輸出至calliing toByteArray()看起來是這樣的:ToByteArray的

List Size = 1 
(0008,0052) CS #6 [IMAGE] Query/Retrieve Level 
(0008,0054) AE #6 [server] Retrieve AE Title 
(0020,000E) UI #54 [1.2.276.0.7230010.3.1.3.669896852.2528.1325171276.916] Series Instance UID 

來源:

error java.lang.IllegalArgumentException: Missing (0002,0010) Transfer Syntax UID 

我,已經發現了一些信息:

public static byte[] toByteArray(DicomObject obj) throws IOException { 
    ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
    BufferedOutputStream bos = new BufferedOutputStream(baos); 
    DicomOutputStream dos = new DicomOutputStream(bos); 
    dos.writeDicomFile(obj); 
    dos.close(); 
    byte[] data = baos.toByteArray(); 
    return data; 
} 

調用toByteArray我被輸出後其他論壇,似乎DcmQR.get()方法不會發送任何數據。是否有可能迫使DcmQR做到這一點。我寫過這個問題在DcmQR.createStorageService()方法中,但我還沒有找到解決方案。請幫幫我!!!

你好cneller!

我做了一些改變,你建議:我已經添加setMoveDest和setStoreDestination和DicomObject存儲在目標我已經添加 - 它看起來不錯。然後我試着寫基於FutureDimseRSP響應處理它在Association.cget方法應用於:

public class MyDimseRSP extends DimseRSPHandler implements DimseRSP{ 

private MyEntry entry = new MyEntry(null, null); 

private boolean finished; 
private int autoCancel; 
private IOException ex; 

@Override 
public synchronized void onDimseRSP(Association as, DicomObject cmd, 
            DicomObject data) { 
    super.onDimseRSP(as, cmd, data); 
    MyEntry last = entry; 
    while (last.next != null) 
     last = last.next; 

    last.next = new MyEntry(cmd, data); 
    if (CommandUtils.isPending(cmd)) { 
     if (autoCancel > 0 && --autoCancel == 0) 
      try { 
       super.cancel(as); 
      } catch (IOException e) { 
       ex = e; 
      } 
    } else { 
     finished = true; 
    } 
    notifyAll(); 
} 

@Override 
public synchronized void onClosed(Association as) { 
    if (!finished) { 
//   ex = as.getException(); 
     ex = null; 
     if (ex == null) { 
      ex = new IOException("Association to " + as.getRemoteAET() 
        + " closed before receive of outstanding DIMSE RSP"); 
     } 
     notifyAll(); 
    } 
} 

public final void setAutoCancel(int autoCancel) { 
    this.autoCancel = autoCancel; 
} 

@Override 
public void cancel(Association a) throws IOException { 
    if (ex != null) 
     throw ex; 
    if (!finished) 
     super.cancel(a); 
} 

public DicomObject getDataset() { 
    return entry.command; 
} 

public DicomObject getCommand() { 
    return entry.dataset; 
} 

public MyEntry getEntry() { 
    return entry; 
} 

public synchronized boolean next() throws IOException, InterruptedException { 
    if (entry.next == null) { 
     if (finished) 
      return false; 

     while (entry.next == null && ex == null) 
      wait(); 

     if (ex != null) 
      throw ex; 
    } 
    entry = entry.next; 
    return true; 
} 
} 

這裏是MyEntry代碼:從Dmcqr爲

public class MyEntry { 

final DicomObject command; 
final DicomObject dataset; 
MyEntry next; 

public MyEntry(DicomObject command, DicomObject dataset) { 
    this.command = command; 
    this.dataset = dataset; 
} 

public DicomObject getCommand() { 
    return command; 
} 

public DicomObject getDataset() { 
    return dataset; 
} 

public MyEntry getNext() { 
    return next; 
} 

public void setNext(MyEntry next) { 
    this.next = next; 
} 
} 

然後我重新輸入get方法如下:

public void getObject(DicomObject obj, DimseRSPHandler rspHandler)throws IOException, InterruptedException{ 
    TransferCapability tc = selectTransferCapability(qrlevel.getGetClassUids()); 
    MyDimseRSP myRsp=new MyDimseRSP(); 
    if (tc == null) 
     throw new NoPresentationContextException(UIDDictionary 
       .getDictionary().prompt(qrlevel.getGetClassUids()[0]) 
       + " not supported by " + remoteAE.getAETitle()); 
    String cuid = tc.getSopClass(); 
    String tsuid = selectTransferSyntax(tc); 
    DicomObject key = obj.subSet(MOVE_KEYS); 
    assoc.cget(cuid, priority, key, tsuid, rspHandler); 
    assoc.waitForDimseRSP(); 
} 

在這種方法的第二個參數,我用我的響應處理程序(MyDimseRSP)的一個實例。我運行我的代碼,得到了我的響應處理程序的命令和數據集的空值。在「下一個」變量中,只有「命令」不爲空,並且當然它不是我需要的DicomObject。我做錯了什麼!

+0

請參閱下面答案中的編輯。你的MyDimseRSP類也有getDataset和getCommand混淆。 – cneller

回答

0

您將不得不逐步完成代碼(包括DCM4CHE工具包代碼)。我懷疑你正在使用默認的響應處理程序,它只計算已完成操作的數量,並不實際存儲來自get命令的圖像數據。

顯然,下面的for循環正在循環查找操作的結果,而不是get(需要在響應處理程序中處理)。

for(DicomObject dco:result) 

我希望你將不得不重寫響應處理適當地寫你的DICOM文件。另請參閱DcmRcv類,用於從您將收到的DicomObject中編寫DICOM文件。

從上面您的修改,我認爲你只是試圖讓原始DICOM實例數據(不存儲它的命令)。大致如下的響應處理程序如何:

List<DicomObject> dataList = new ArrayList<DicomObject>(); 

@Override 
public void onDimseRSP(Association as, DicomObject cmd, DicomObject data) { 
    if(shouldAdd(as, cmd)) { 
     dataList.add(data) 
    } 
} 

小心大列表,但它應該讓你的內存中的數據。

+0

謝謝你的回答 - 我真的很新dcm4che和文檔相當差 - 這就是爲什麼我想問你的示例代碼。你能否介紹合適的溶劑......謝謝! – user3359688

+0

在configureConnsferCapability之前,請確保爲您期望的對象添加了StoreTransferCapability和setStoreDestination。默認操作應至少將圖像存儲在文件系統上。 – cneller

+0

此外,在抱怨太多關於文檔之前,請仔細閱讀代碼。 DCM4CHE2工具包的功能數量非常可觀,並且其架構非常堅固。這比任何人都付出的代價更值得! – cneller