📄 dicom_viewer.pro
字号:
(*s).view->SetProperty, VIEWPLANE_RECT=[0,0,2,2]
(*s).win->Draw
help, /LAST, OUTPUT=errmsg
void=dialog_message(['Error while opening dicom file',errmsg], DIALOG_PARENT=ev.top)
dicom_viewer_update_sensitivity, s
return
endelse
if obj_valid(o) then obj_destroy, o
dicom_viewer_update_sensitivity, s
end
'contract': begin
wpatient = widget_info((*s).wtree, /child)
repeat begin
widget_control, wpatient, set_tree_expanded = 0
wpatient = widget_info(wpatient, /sibling)
endrep until (wpatient eq 0)
end
'expand': begin
wpatient = widget_info((*s).wtree, /child)
repeat begin
widget_control, wpatient, set_tree_expanded = 1
wstudy = widget_info(wpatient, /child)
repeat begin
widget_control, wstudy, set_tree_expanded = 1
wseries = widget_info(wstudy, /child)
repeat begin
widget_control, wseries, set_tree_expanded = 1
wseries = widget_info(wseries, /sibling)
endrep until (wseries eq 0)
wstudy = widget_info(wstudy, /sibling)
endrep until (wstudy eq 0)
wpatient = widget_info(wpatient, /sibling)
endrep until (wpatient eq 0)
end
'exit': begin
WIDGET_CONTROL, ev.top, /DESTROY
end
'netservice': begin
if lmgr('idl_dicomex_net') then $
dicomex_net_startup $
else $
void = dialog_message(/info, $
['You currently are not licensed to use IDL''s Dicom Network Services', $
'For more information go to http://www.rsinc.com/idl/addons_dicomns.asp'])
end
'vol': begin
if ((err=dicom_viewer_display_series(s)) ne '') then begin
void = dialog_message('Error: '+err, DIALOG_PARENT=ev.top)
endif
end
else: ; ignore
endcase
end
;----------------------------------------------------------------------
; dicom_viewer_update_sensitivity
;+
; Update the menu, toolbar, and popup sensitivity according to the
; current application state.
;
; @param s {in}{type=pointer} Pointer to application state structure.
;-
pro dicom_viewer_update_sensitivity, s
compile_opt HIDDEN
(*s).image->GetContext, SENSITIVE=sens, COUNT=count
for i=0, count-1 do if (*s).sens[i] ne sens[i] then begin
WIDGET_CONTROL, (*s).cbut[i], SENSITIVE=sens[i]
WIDGET_CONTROL, (*s).cbut2[i], SENSITIVE=sens[i]
WIDGET_CONTROL, (*s).cbut3[i], SENSITIVE=sens[i]
endif
(*s).sens=sens
(*s).image->GetProperty, CURRENTFRAME=frameNum, NFRAMES=nframes
nframes = nframes>1
(*s).image->GetProperty, DIMENSIONS=dims
if product(dims,/INTEGER) le 4 then frameNum=(nframes=0)-1
WIDGET_CONTROL, (*s).wText, SET_VALUE=STRING(FORMAT='(%"Frame number %d of %d")', frameNum+1, nframes)
end
;----------------------------------------------------------------------
; dicom_viewer_table_cleanup
;+
; Clean up the table widget on exit.
;
; @param wtable {in}{type=widget reference} The DICOM tags table widget.
;-
pro dicom_viewer_table_cleanup, wtable
compile_opt HIDDEN
; Find the true top level base.
tlb = wtable
while WIDGET_INFO(tlb, /PARENT) ne 0 do $
tlb = WIDGET_INFO(tlb, /PARENT)
; Get the application state and current file.
widget_control, tlb, GET_UVALUE=s
widget_control, wtable, GET_UVALUE=file
; If there is a current file store the name in the preferences
; so that the same directory can be restored the next time the
; application is run.
if keyword_set(file) then save, file, FILENAME=(*s).prefsFile
end
;----------------------------------------------------------------------
; dicom_viewer_cleanup
;+
; Free any memory used by the application.
;
; @param tlb {in}{type=widget reference} The top level base.
;-
pro dicom_viewer_cleanup, tlb
compile_opt HIDDEN
WIDGET_CONTROL, tlb, GET_UVALUE=s
heap_free, s
end
;
; Public:
;
;----------------------------------------------------------------------
; dicom_viewer
;+
; Create the DICOM viewer widgets, load preferences, and start
; event handling.
;
; @file_comments
;
; This program implements a basic DICOM viewer and demonstrates
; some of the functionality available in the <code>IDLffDICOMEx</code> object.
;
; @author Atle Borsholm
; @copyright Research Systems, Inc., 2004.
;-
pro dicom_viewer
compile_opt idl2, logical_predicate
demo_mode = lmgr(/DEMO) OR lmgr(/VM)
dicom_rw_lic = lmgr("idl_dicomex_rw")
;idl_dicomex_rw idl_lmgrd 6.200 31-dec-2005 uncounted \
;idl_dicomex_scp idl_lmgrd 6.200 31-dec-2005 uncounted \
dicom_net_lic=lmgr("idl_dicomex_net") ; idl_lmgrd 6.200 31-dec-2005 uncounted \
;IF (dicom_rw_lic EQ 0) THEN BEGIN
; result = dialog_message (' This program requires a license for the DICOM Services Module. Please contact your RSI Sales Rep to obtain a license', /INFORMATION)
; exit
;ENDIF
;
; Restore application preferences
;
AuthorDirname = 'rsi'
AuthorDesc = 'Research Systems, Inc.'
AppDirname = 'dicom_viewer'
AppDesc = 'Display DICOM images and tag infomration'
AppReadmeText = ['Author: rsi', 'DICOM viewer application preferences are stored in this directory']
AppReadmeVersion = 1
dir = APP_USER_DIR(AuthorDirname, AuthorDesc, AppDirname, AppDesc, AppReadmeText, AppReadmeVersion)
prefsFile = filepath(ROOT_DIR=dir,'dicom_viewer_prefs.sav')
if file_test(prefsFile, /REGULAR) then restore, prefsFile
;
; Create the DICOM image object used to display the images
; and add it to a model and view. See dicomviewerimage__define.pro.
;
image=obj_new('DicomViewerImage',/ORDER)
model=obj_new('IDLgrModel')
model->Add, image
image->GetProperty, DIMENSIONS=dim
oView=obj_new('IDLgrView', VIEWPLANE_RECT=[0,0,dim], color = [0,0,0])
oView->Add, model
;
; If there was a previous file, use its pathname to get a list
; of all the files in that same directory. These will be searched
; and all DICOM files will be loaded into the tree widget for display.
;
if keyword_set(file) then begin
dir = file_dirname(file,/mark_dir)
files = file_search(dir+'*',/test_regular)
;; update the list with all the files in the directory
basenames = file_basename(files)
endif
;
; Create the widgets starting with the top level base.
;
tlb = WIDGET_BASE(/COLUMN, MBAR=mbar, /TLB_SIZE_EVENTS, $
title = 'IDL Dicom Viewer')
;
; File and Tools menus
;
amp = (!version.os_family eq 'Windows') ? '&' : ''
wfile = WIDGET_BUTTON(mbar, VALUE=amp+'File',/MENU, EVENT_PRO='dicom_viewer_menu')
wTools = WIDGET_BUTTON(mbar, VALUE=amp+'Tools', /MENU, EVENT_PRO='dicom_viewer_context_event')
; File menu options. Tools menu options added below when building the image context menu.
wopen = WIDGET_BUTTON(wfile, VALUE=amp+'Open File', UVALUE='open')
wopendir = widget_button(wfile, value = 'Open ' + amp + 'Directory', uvalue = 'opendir')
wexp = WIDGET_BUTTON(wfile, VALUE=amp+'Export tags to text file', UVALUE='export', SENSITIVE=0)
wexpand = widget_button(wfile, value = amp+'Expand all folders', uvalue = 'expand')
wcontract = widget_button(wfile, value = amp+'Contract patient folders', uvalue = 'contract')
wExit = WIDGET_BUTTON(wFile, VALUE=amp+'Exit', UVALUE='exit')
; Base used by tree widget, toolbar and image
base = WIDGET_BASE(tlb, /ROW)
;
; Tree widget
;
tbase = WIDGET_BASE(base, XSIZE=400, YSIZE=420, col = 1)
dirlabel = widget_text(tbase, value = '')
wTree = WIDGET_TREE(tbase, xsize = 400, YSIZE=400, $
EVENT_PRO='dicom_viewer_tree_event', $
UVALUE=files)
;
; Toolbar. Add the file open button now, others are added below
; when the context menu for the image is created.
;
wToolbase = WIDGET_BASE(base, /COLUMN, EVENT_PRO='dicom_viewer_menu')
fileOpen = filepath(SUBDIR=['resource','bitmaps'],'open.bmp')
wOpen = WIDGET_BUTTON(wToolbase, VALUE=fileOpen, /BITMAP, UVALUE='opendir', TOOLTIP='Open Directory')
netfile = filepath('propsheet.bmp', subdir = ['resource', 'bitmaps'])
netb = widget_button(wtoolbase, value = netfile, /bitmap, $
uvalue = 'netservice', tooltip = 'Launch Network Services Dialog')
;
; Image display area
;
wDrawBase = WIDGET_BASE(base, /COLUMN)
wText = WIDGET_TEXT(wDrawBase, SCR_XSIZE=400)
wdr = WIDGET_DRAW(wDrawBase, GRAPHICS_LEVEL=2, RETAIN=2, RENDERER=1, XSIZE=400, YSIZE=400, $
/BUTTON_EVENTS, /MOTION_EVENTS, EVENT_PRO='dicom_viewer_draw_event')
;
; DICOM tags table
;
wtb = WIDGET_TABLE(tlb, COLUMN_WIDTH=[100,50,25,25,425,200], Y_SCROLL_SIZE=10, $
COLUMN_LABELS=['Tag','Length','VR','MV','Value','Description'], $
/SCROLL, /RESIZEABLE_COLUMNS, /NO_ROW_HEADERS, YSIZE=100, $
KILL_NOTIFY='dicom_viewer_table_cleanup', UVALUE=file, /all, $
event_pro = 'dicom_viewer_table_event', /context_events)
table_cbase = widget_base(tlb, xs = 100, ys = 100, /context_menu)
b = widget_button(table_cbase, value = 'Copy to Anonymizer', sensitive = 0, $
event_pro = 'dicom_viewer_table_context_event')
;
; Realize the widgets and draw the initial image, if any.
;
WIDGET_CONTROL, tlb,/REALIZE
WIDGET_CONTROL, wdr, GET_VALUE=owin
owin->SetProperty, GRAPHICS_TREE=oview
owin->Draw
;
; Create the context menu for the image and apply the same to the Tools menu
; and the toolbar.
;
wVol = WIDGET_BUTTON(wTools, VALUE=amp+'Open selected Series in iVolume', $
event_pro='dicom_viewer_menu', UVALUE='vol', SENSITIVE=0)
bmps = [filepath(SUBDIR=['resource','bitmaps'],['itl.bmp','reset.bmp','data_range.bmp','hist.bmp', $
'volume.bmp','redo.bmp','undo.bmp', 'camera.bmp']), 'anonymize.bmp']
image->GetContext, MENU=cmenu, ARG=arg, SENSITIVE=sens, COUNT=count
cbase=WIDGET_BASE(tlb,/CONTEXT_MENU, event_pro='dicom_viewer_context_event')
cbut3=(cbut2=(cbut=lonarr(count)))
for i=0, count-1 do begin
; Image context menu
cbut[i]=WIDGET_BUTTON(cbase, VALUE=cmenu[i], UVALUE=arg[i], SENSITIVE=sens[i])
; Toobar
cbut2[i]=WIDGET_BUTTON(wToolbase, VALUE=bmps[i], UVALUE=arg[i], SENSITIVE=0, $
EVENT_PRO='dicom_viewer_context_event', /BITMAP, TOOLTIP=cmenu[i])
; Tools menu
cbut3[i]=WIDGET_BUTTON(wTools, VALUE=cmenu[i], UVALUE=arg[i], SENSITIVE=sens[i])
endfor
wiz_base = widget_base(wtoolbase, /nonexclusive)
wizard_bmp = filepath(subdir=['resource','bitmaps'],'prop.bmp')
bwiz = widget_button(wiz_base, value=wizard_bmp, /bitmap, $
uvalue='wizard', tooltip='Launch Wizard When Anonymizing')
widget_control, bwiz, /set_button
outlabel = widget_label(tlb, value = ' ', /dynamic)
;
; Define padding around the widgets for responding to resize events.
;
WIDGET_CONTROL, tlb, TLB_GET_SIZE=tlbSize
geom = WIDGET_INFO(wtb, /GEOMETRY)
treeGeom = WIDGET_INFO(wTree, /GEOMETRY)
padding = (tlbSize - [geom.scr_xsize, geom.scr_ysize]) > [0,treeGeom.scr_ysize]
xpad = tlbSize[0] - treeGeom.scr_xsize
;
; Application state is stored in an anonymous structure which is
; itself stored in the UVALUE of the top level base so that all
; widgets can access it.
;
s=ptr_new({win:owin, $
tlb:tlb, $
file:'', $
tbase:tbase, $
image:image, $
view:oview, $
model:model, $
wtable:wtb, $
wTree:wTree, $
wVol:wVol, $
table_cbase:table_cbase, $
table_row_select:-1, $
cbase:cbase, $
cbut:cbut, $
dirlabel:dirlabel, $
outlabel:outlabel, $
padding:padding, $
prefsFile:prefsFile, $
wexport:wexp, $
cbut2:cbut2, $
cbut3:cbut3, $
sens:sens, $
cine:0, $
xpad:xpad, $
wText:wText, $
seriesData:ptr_new(), $
anonymizer:obj_new('anonymizer', /from_application), $
anonymizer_flag:0, $
bwiz:bwiz $
})
;
; Use DICOM Services
;
; Before using DICOM Services, make sure we are licensed
IF (dicom_rw_lic EQ 0) THEN BEGIN
msg1 = 'This program requires a license for the DICOM Services Module.' + STRING([13B, 10B])
msg2 = 'Contact your Research Systems sales representative at 303-786-9900 ' + STRING([13B, 10B])
msg3 = 'or send an email inquiry to sales@RSInc.com.'
result = dialog_message (msg1+msg2+msg3, /INFORMATION)
exit
ENDIF
; Okay we're licensed
;
WIDGET_CONTROL, tlb, SET_UVALUE=s
; Populate the tree
if n_elements(files) gt 0 then $
void = dicom_viewer_populate_tree(s)
;
; Call XMANAGER to start processing events. Each widget uses
; its own event handler routine.
;
if widget_info(tlb, /valid) then $
XMANAGER,'dicom_viewer', tlb, /NO_BLOCK, $
CLEANUP='dicom_viewer_cleanup'
end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -