⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dicom_viewer.pro

📁 DICOM viewer - this software is used to view a set of DICOM images.
💻 PRO
📖 第 1 页 / 共 3 页
字号:
;
;  Name - DICOM_VIEWER
;
;  Calling Syntax - DICOM_VIEWER
;
;  Purpose - Display dicom tags and images.  Allow quick navigation
;            between dicom files in a directory.using the familiar
;            patient, study, series, image hierarchy.
;
;  Modification History - 17 May 2004, Written, Atle Borsholm
;                         Sept 2004, tree widget, iVolume, RTK
;                         April 2005, Rewrote DICOM_VIEWER_POPULATE_TREE. DSA
;                                     Added Expand/Contract menu buttons. DSA
;                                     Added file directory label. DSA
;                         May 2005,   Modified rubberband zoom DSA
;
;
;----------------------------------------------------------------------

;
;  Private:
;
;----------------------------------------------------------------------
;  dicom_viewer_table_event
;+
;  Handles table events
;
;  @param event {in}{type=structure}  Event structure.
;-
pro dicom_viewer_table_event, event
    compile_opt hidden

    widget_control, event.top, get_uvalue = s

    if strlowcase(tag_names(event, /struct)) eq 'widget_context' then begin

        widget_displaycontextmenu, event.id, event.x, event.y, (*s).table_cbase

    endif else begin

        if strlowcase(tag_names(event, /struct)) eq 'widget_table_cell_sel' then $
            (*s).table_row_select = event.sel_bottom

    endelse

end



;
;  Private:
;
;----------------------------------------------------------------------
;  dicom_viewer_table_event
;+
;  Handle table's context menu events
;
;  @param event {in}{type=structure}  Event structure.
;-
pro dicom_viewer_table_context_event, event

    widget_control, event.top, get_uvalue = s

    if ((*s).table_row_select ge 0) && ((*s).anonymizer -> query_wizard()) then begin

        widget_control, (*s).wtable, get_value = new_tag, $
            use_table_select = [0,(*s).table_row_select,0,(*s).table_row_select]

        if strlen(new_tag) gt 0 then $
            (*s).anonymizer -> define_tags, new_tag

    endif

end




;
;  Private:
;

;----------------------------------------------------------------------
;  dicom_viewer_event
;+
;  Handle top level base resize events.
;
;  @param ev {in}{type=structure}  Event structure.
;-
pro dicom_viewer_event, ev
    compile_opt idl2, HIDDEN

    ;  Top level base didn't generate the event, ignore it.
    if ev.top ne ev.id then return

    WIDGET_CONTROL, ev.top, TLB_GET_SIZE=tlbSize, GET_UVALUE=s

    tlbSize = (tlbSize - (*s).padding) > [500,40]
    colWidths = WIDGET_INFO((*s).wtable, /COLUMN_WIDTHS)
    colWidths = ROUND(colWidths*(tlbSize[0]/TOTAL(colWidths)))

    WIDGET_CONTROL, (*s).tbase, SCR_XSIZE=tlbSize[0] - (*s).xpad
    WIDGET_CONTROL, (*s).wTree, SCR_XSIZE=tlbSize[0] - (*s).xpad
    WIDGET_CONTROL, (*s).wtable, SCR_XSIZE=tlbSize[0], $
                    SCR_YSIZE=tlbSize[1], COLUMN_WIDTHS=colWidths
end


;----------------------------------------------------------------------
;  dicom_viewer_tree_event
;+
;  Handle a tree event.
;-
pro dicom_viewer_tree_event, event
  compile_opt idl2

  ;  Get the event type and app state
  WIDGET_CONTROL, event.id, GET_UVALUE=str
  WIDGET_CONTROL, event.top, GET_UVALUE=s

  ;  Disable the series in iVolume menu
  WIDGET_CONTROL, (*s).wVol, SENSITIVE=0

  ;  What to do depends upon what was clicked
  case str of
    'PATIENT': ;  ignore for now
    'STUDY'  : ;  ignore for now
    'SERIES' : WIDGET_CONTROL, (*s).wVol, SENSITIVE=1 ;  allow for series in iVolume
    ELSE     : begin

        widget_control, (*s).outlabel, set_value = ' '
        void = dicom_viewer_open_file(str, s)  ;  open an image, we know it exists

    end
  endcase
end


;----------------------------------------------------------------------
;  dicom_viewer_draw_event
;+
;  Handle draw widget events.
;
;  @param ev {in}{type=structure}  Event structure.
;-
pro dicom_viewer_draw_event, ev
    compile_opt HIDDEN

    ;  Get the app structure
    widget_control, ev.top, get_uvalue=s


    ;  Right-click (context menu)
    if (ev.release eq 4) then begin
        WIDGET_DISPLAYCONTEXTMENU, ev.id, ev.x, ev.y, (*s).cbase
    endif

    ;  Left-click (zoom)
    if (ev.type eq 0) && (ev.press eq 1) then begin
        ;  Begin zoom box
        res = (*s).win->PickData((*s).view, (*s).image, [ev.x, ev.y], xyz)
        poly = xyz[0:1,[0,0,0,0]] ; replicate 4 corners of box
        oPoly = OBJ_NEW('IDLgrPolygon', poly, STYLE=1, COLOR=[0,255,0])
        (*s).model->Add, oPoly
        (*s).win->Draw
    endif else if (ev.type eq 2) && ((*s).model->Count() ge 2) then begin
        ;  Drag zoom box (grow)
        res = (*s).win->PickData((*s).view, (*s).image, [ev.x, ev.y], xyz)
        oPoly = (*s).model->Get(POSITION=1)
        oPoly->GetProperty, DATA=data
        data[0,[1,2]] = xyz[0]
        data[1,[2,3]] = xyz[1]
        oPoly->SetProperty, DATA=data
        (*s).win->Draw
    endif else if (ev.type eq 1) && (ev.release eq 1) && ((*s).model->Count() gt 1) then begin
        ;  Done with zoom box
        oPoly = (*s).model->Get(POSITION=1)
        (*s).model->Remove, oPoly
        oPoly->GetProperty, DATA=data
        OBJ_DESTROY, oPoly
        minx = MIN(data[0,*], MAX=maxx)
        miny = MIN(data[1,*], MAX=maxy)

        if (maxx-minx gt 1) && (maxy-miny gt 1) then begin

          (*s).view -> getproperty, viewplane_rect = vpr
          range = [maxx-minx, maxy-miny]
          k = min(vpr[2:3]/range)
          new_range = vpr[2:3]/k
          (*s).view -> setproperty, viewplane_rect = [[minx,miny]-float(new_range-range)/2, new_range]

        endif

        (*s).win->Draw
    endif

    dicom_viewer_update_sensitivity, s
end


;----------------------------------------------------------------------
;  dicom_viewer_context_event
;+
;    Right-click in the draw widget.
;
;  @param ev {in}{type=structure}  Event structure.
;-
pro dicom_viewer_context_event, ev
    compile_opt HIDDEN, idl2

    ;  Get the application state
    WIDGET_CONTROL, ev.top, GET_UVALUE=s

    ;  And context menu value
    WIDGET_CONTROL, ev.id, GET_UVALUE=arg

    if (arg eq 'anonymize') then begin

        if (*s).anonymizer -> query_wizard() then return

        child = widget_info((*s).table_cbase, /child)
        widget_control, child, sensitive = 1

        (*s).anonymizer -> setproperty, file = (*s).file

        wcheck = widget_info((*s).bwiz, /button_set)

        outfile = (*s).anonymizer -> anonymize( $
            wizard = wcheck)

        if widget_info(child, /active) then $
            widget_control, child, sensitive = 0

        if outfile eq '' then $
            return

        if wcheck then begin

            void = dialog_message(/quest, $
                ['Anonymized file ' + outfile +  ' created', $
                 'Open this file?'])

            if strlowcase(void) eq 'yes' then begin

                if file_test(outfile, /directory) then $
                    dir = outfile $
                else $
                    dir = file_dirname(outfile,/mark_dir)

                files=file_search(dir+'*',/test_regular)

                if dicom_viewer_open_file(outfile, s) then begin

                    widget_control, (*s).wtree, set_uvalue=files
                    void = dicom_viewer_populate_tree(s, outfile)

                endif

            endif

        endif

        widget_control, (*s).outlabel, set_value = 'Anonymized file : ' + outfile

    endif else begin

        ;  Perform the selected event and update the image
        (*s).image->ContextEvent, arg
        (*s).win->Draw
        dicom_viewer_update_sensitivity, s

        ;  Set the cine timer
        if (arg eq 'cine') then begin
            if tag_names(ev, /STRUCTURE_NAME) ne 'WIDGET_TIMER' then (*s).cine = ~(*s).cine
            if (*s).cine then WIDGET_CONTROL, ev.id, TIMER=0.5 $
            else WIDGET_CONTROL, ev.id, /CLEAR_EVENTS
        endif

    endelse

end


;----------------------------------------------------------------------
;  dicom_viewer_maketable
;+
;  @returns A string array with the tag numbers and description(*s).
;
;  @param oDicom {in}{type=IDLffDICOMEx object reference}  A DICOM file.
;-
function dicom_viewer_maketable, oDicom
    compile_opt HIDDEN

    tags=oDicom->EnumerateTags(/QUIET)
    n=n_elements(tags)
    table=strarr(6,n)
    indent = strmid(replicate(62b,max(tags.level)>1),0,tags.level)
    table[0,*]=indent+tags.tag
    table[1,*]=strtrim(tags.length,2)
    table[2,*]=tags.vr
    table[3,*]=strtrim(tags.valuecount,2)
    table[4,*]=tags.value
    table[5,*]=tags.description
    return, table
end


;----------------------------------------------------------------------
;  dicom_viewer_open_file
;+
;  Open and display a DICOM file.
;
;  @returns  True (1) if file successfully opened, false (0) otherwise.
;
;  @param file {in}{type=string}  Pathname of the file to open.
;  @param s {in}{type=pointer}  Pointer to application state.
;-
function dicom_viewer_open_file, file, s
  compile_opt idl2

    err = 0
    catch, err

    if (err eq 0) then begin

        o = obj_new('IDLffDicomEx',file,/NON)
        (*s).file = file
        (*s).image->Import,o
        table=dicom_viewer_maketable(o)
        ysize=(size(table))[2]
        WIDGET_CONTROL, (*s).wtable, SET_VALUE=temporary(table), $
          TABLE_YSIZE=ysize, SET_UVALUE=file
        WIDGET_CONTROL, (*s).wTable, SET_TABLE_VIEW=[0,0]
        WIDGET_CONTROL, (*s).wexport, SENSITIVE=1
        (*s).image->GetContext, SENSITIVE=sens, COUNT=n
        for i=0,n-1 do WIDGET_CONTROL, (*s).cbut2[i], SENSITIVE=sens[i]
        (*s).anonymizer -> setproperty, file = file
        catch, /CANCEL

    endif else begin
        ;
        ;  Not a DICOM file.
        ;
        catch, /CANCEL
        WIDGET_CONTROL, (*s).wtable, SET_VALUE=strarr(6,6)
        (*s).image->IDLgrImage::SetProperty, DATA=bytarr(2,2)
        (*s).image -> setproperty, nframes = 0
        (*s).view->SetProperty, VIEWPLANE_RECT=[0,0,2,2]
        (*s).win->Draw
        WIDGET_CONTROL, (*s).wexport, SENSITIVE=0
        dicom_viewer_update_sensitivity, s
        help, /LAST, OUTPUT=errmsg
        (*s).file = ''
        void=dialog_message(['Error opening dicom file',errmsg], DIALOG_PARENT=(*s).tlb)

    ; Unselect any selected tree nodes.
        wid = widget_info((*s).wtree, /tree_select)
        if wid[0] gt -1 then $
            for i = 0, n_elements(wid)-1 do $
                widget_control, wid[i], set_tree_select = 0

    ; Change TLB title.
        widget_control, (*s).tlb, tlb_set_title = 'IDL Dicom Viewer'

        return, 0

    endelse
    if obj_valid(o) then obj_destroy, o
    (*s).view->SetProperty, VIEWPLANE_RECT=(*s).image->DefaultZoom()
    (*s).win->Draw
    dicom_viewer_update_sensitivity, s

; Change TLB title to reflect selected file.
    widget_control, (*s).tlb, tlb_set_title = 'IDL Dicom Viewer (' + $
        file + ')'

    return, 1

end



;----------------------------------------------------------------------
;  dicom_viewer_populate_tree
;+
;  Examine all files in the current directory and load the tree with
;  those DICOM files found sorted by patient, study, series and image.
;
;  @param s {in}{type=pointer}  Pointer to application state structure.
;  @param file {in}{type=string} Full path to file being opened.
;-
function dicom_viewer_populate_tree, s, file

    compile_opt idl2, logical_predicate

    widget_control, hourglass = 1

    file = (n_elements(file) gt 0) ? file[0] : ''

    widget_control, (*s).dirlabel, set_value = 'Scanning Files...'

    widget_control, (*s).wtree, get_uvalue = files

    geom = widget_info((*s).wtree, /geometry)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -