【转】用fo-dicom实现print scu的注意事项!!!!!!!!!
轉自:https://blog.csdn.net/tvsofa2008/article/details/50245357
用fo-dicom實現print scu的注意事項
fo-dicom是一個開源的協議庫,開發語言是c#。網上針對fo-dicom的分析也有不少,但是專門針對dicom print的文章還是太少了。
近幾天需要用fo-dicom實現一個print scu,把其中的一些注意事項總結一下。
工欲善其事,必先利其器。在編程調試過程中各種各樣的輔助工具必不可少。經過網上搜索、自己驗證測試后,推薦使用方便的scp,scu測試工具:
這兩個工具使用方便,scu只需要設置一下called AET、calling AET、remote host、remote port等參數即可。
scp稍微麻煩一些,必須先在Rules選項卡中建立一個新項,填入called AET、打印機名稱等。然后在General選項卡中設置scp參數即可。
工具齊備了,下面開始代碼吧。fo-dicom本身例子已經包含了printscu和printscp,先直接使用例子中的代碼試一下,發現:
所以貌似fo-dicom自己給的print代碼是有問題的,無法直接使用。
先用fo-dicom printscu + charruasoft print scp測試打印,把scp和scu的輸出信息抓好保存。
再用charruasoft print scu + charruasoft print scp測試打印,把scp和scu的輸出信息抓好保存。
對比分析發現fo-dicom printscu一開始的associate都沒有成功!它并沒有協商BasicGrayscalePrintManagementMetaSOPClass,分析dicom代碼后,PrintJob.cs的Print函數增加如下代碼:
當然,我們打印的是黑白片子,如果要打印彩色片子,BasicGrayscalePrintManagementMetaSOPClass要相應改變。
在DicomClient.cs中修改public IAsyncResult BeginSend(Stream stream, string callingAe, string calledAe, AsyncCallback callback, object state)函數:
//foreach (var request in _requests) // assoc.PresentationContexts.AddFromRequest(request); foreach (var context in _contexts)assoc.PresentationContexts.Add(context.AbstractSyntax, context.GetTransferSyntaxes().ToArray());foreach (var pc in assoc.PresentationContexts) {foreach (var request in _requests){request.PresentationContext = new DicomPresentationContext(pc.ID,request.PresentationContext.AbstractSyntax,pc.AcceptedTransferSyntax,DicomPresentationContextResult.Proposed);} }這樣associate過程終于通過了。但是在fo-dicom print scu發送第2次N-CREATE數據包時scp返回”處理失敗”錯誤。
繼續分析,發現是fo-dicom第2次N-CREATE數據包的Sequence字段中只有ReferencedImageBoxSequence,并不存在ReferencedFilmSessionSequence,這個明顯與正確的抓包有差別,因此懷疑是這里的問題,即:fo-dicom在FilmBox的Initialize()函數中沒有加入ReferencedFilmSessionSequence字段。找到問題就好解決了,在FilmBox.cs的Initialize()函數中加入代碼:
Add(new DicomSequence(DicomTag.ReferencedFilmSessionSequence));var item = new DicomDataset(); item.Add(DicomTag.ReferencedSOPClassUID,_filmSession.SOPClassUID); item.Add(DicomTag.ReferencedSOPInstanceUID,_filmSession.SOPInstanceUID);var seq = Get<DicomSequence>(DicomTag.ReferencedFilmSessionSequence); seq.Items.Add(item); ... //if (!this.Contains(DicomTag.RequestedResolutionID)) //{ // RequestedResolutionID = "STANDARD"; //}這回再編譯運行,已經能正確的與scp通訊了,片子打印無誤。
總結
在我們的應用中,fo-dicom庫的print scu代碼確實存在問題,無法與膠片打印機正確通訊。
fo-dicom庫需要做稍微的修改:
當然,這可能和我們使用的膠片打印機有關,在其它應用中可能還需要適當修改。
問題
1.fo-dicom里找不到print的例子呀,能告訴我在哪里嗎?
? ?fo-dicom-development\Examples\Print SCU目錄下
2.代碼更正
Add(new DicomSequence(DicomTag.ReferencedFilmSessionSequence));
var item = new DicomDataset();
item.Add(DicomTag.ReferencedSOPClassUID,_filmSession.SOPClassUID);
item.Add(DicomTag.ReferencedSOPInstanceUID,_filmSession.SOPInstanceUID);
var seq = Get<DicomSequence>(DicomTag.ReferencedFilmSessionSequence);//樓主這里少了一個括號
seq.Items.Add(item);
3.新版本按照這個改了,還是沒有通過...
fo-dicom request包中InstanceUID字段都是scu產生并填充的,正常來說,scp只是把收到的InstanceUID字段原樣返回。因此,你可以控制InstanceUID的值。 并且,用scp response的UID返回值填充下一個request的UID應該是可行的,fo-dicom本身就是這樣實現的吧
對的,這個參數導致第二次N-Create的response讀取PDU時出錯,無法繼續進行(用其他SCP程序該步可以通過,因為charruasoft print scp會返回你N-Create設置的參數和它帶的其他一些參數),可是當我屏蔽了這個參數,進行到N-Action時,還是有問題,其中的SOPInstanceUID給的不對,應該是動態的,用第二次N-Create返回回來的SOPInstanceUID,然而想在N-Create的Response中設置卻是無法實現的,因為在收到Response時,N-Action的request好像已經發出去了,所以邏輯好像是有問題的。(我已用多種虛擬打印設備測試過)
我是改完后根據回憶寫的,可能有遺漏的地方。你是用文中提到的那個scp程序測試的嗎?如果是應該是能通過的。要是用真實膠片機測試,可能不一定行。你把FilmBox中 //if (!this.Contains(DicomTag.RequestedResolutionID)) //{ // RequestedResolutionID = "STANDARD"; //} 這樣改一下試試,祝好運。
總結
以上是生活随笔為你收集整理的【转】用fo-dicom实现print scu的注意事项!!!!!!!!!的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2020年个人所得税专项附加扣除怎么算?
- 下一篇: 大学生怎么网上申请信用卡