; $Id$ ;+ ; NAME: XCTV2 ; ; PURPOSE: ; This set of procedures implements a display widget for ; roaming, zooming, scaling, and examining pixel values in two ; images simultaneously. ; ; CALLING SEQUENCE: ; XCTV2, Array1, Array2 [, H1, H2] ; XCTV2, Array1, Array2, H1 ; first header only ; XCTV2, Array1, Array2, 0, H2 ; second header only ; ; POSITIONAL PARAMETERS: ; Input: ; Array1: First image to be displayed. ; Array2: Second image to be displyed. Generally, the two ; images should be the same size, since direct ; comparison is the point. ; H1: Header of first image (optional) ; H2: Header of second image (optional) ; ; KEYWORD PARAMETERS: ; Input: ; GROUP_LEADER: Widget group leader, if this widget is ; called from another widget program. ; Of the following size keywords, the most useful are ; XLIM and YLIM; the least useful are XSIZE and YSIZE. ; XLIM, YLIM: Biggest size of image permitted without ; resorting to scrollbars. ; X_SCROLL_SIZE, Y_SCROLL_SIZE: Size of visible portion ; of main image displays. ; XSIZE, YSIZE: Size of main image displays, if not same ; as input array sizes. ; ZOOM_SIZE: Size of zoom window (always square), pixels. ; PSFILE: Initial file name for hardcopy. ; PSTITLE: Initial title for hardcopy. ; PAN_SIZE: Size of pan window (always square), pixels. ; NO_COPY: Flag to cause input arrays to be deallocated ; and kept only in the display widget internal storage. ; Output: ; DSP1: Object reference for the first display. ; DSP2: Object reference for the second display. These ; will in general only be useful if you are trying ; to do something fancy or to use help,/obj to ; see how the objects are laid out. ; GWIN: Two-element array containing the graphics window ; identifiers for the left and right main windows, ; respectively. ; ; METHOD: ; Uses the GANGEXAM object class, which inherits from both ; IMGDISPLAY and REPEATER. Although the coding is object-oriented, ; these classes use IDL direct graphics, not object graphics. ; IMGDISPLAY provides the capabilities for display, roaming, ; hardcopy, etc., while REPEATER enables one display to broadcast ; its cursor events to the other, so you can operate both displays ; simultaneously. ; ; USAGE NOTES: ; Layout is two side-by-side panels. Each panel contains a ; main window, a pan window, and a zoom window: ; pan window - a boxaveraged version of the whole image ; main window - the full resolution image, with scroll ; bars if necessary ; zoom window - a subimage at the cursor position, ; enlarged ; To pan, you put the mouse cursor in the pan window, hold down ; the left mouse button, and move around. To stop, let go of ; the mouse button. ; To move the zoom window, you do the same maneuver, except with ; the mouse cursor in the main window. ; The left and right images will do the same thing if you are ; panning/zooming in the left panel; if you pan/zoom in the ; right panel, then the left panel will not follow along. You ; can change this and choose the right panel to be the ; controller: just double click any of the three windows in the ; right panel. ; ; The following widget buttons are provided: ; Top left: ; QUIT WIDGET ; Display Controls -- creates a popup to do image scaling, ; hardcopy for left panel only ; Zoom x.x -- droplist to choose a zoom factor for left ; panel only: click it, hold mouse button down, and ; drag highlight to desired value ; Top right: ; Display Controls -- creates a popup to do image scaling, ; hardcopy for right panel only ; Zoom x.x -- dropllist to choose a zoom factor for right ; panel only ; Same Scale -- push to make the image scaling in absolute ; units the same for both panels (the pan/zoom controlling ; panel is also the controlling panel for this). ; ; EXAMPLE: ; stis_read, 10001, h1, d1, readout=1 ; stis_read, 10001, h2, d2, readout=2 ; xctv2, d1, d2 ; ; NOTES: ; The latest version and supporting procedures are ; available in http://idlastro.gsfc.nasa.gov/ftp/contrib/bhill/ ; ; MODIFICATION HISTORY: ; Written by R. S. Hill, Raytheon ITSS, 26 May 1999 ; Same-scale button. RSH, RITSS, 11 May 1999 ; Made H1 and H2 positional. Eliminated some unused code. ; RSH, 12 Oct. 1999 ; Square brackets on subscripts. MESSAGE error handling. ; RSH, 28 June 2000 ; Only one quit button. RSH, 17 Nov 2000 ; Pan window keeps aspect ratio as close as possible to image. ; Scale byte images 0 - 255 on initial display. RSH, SSAI, 26 Sep 2001 ; Set retain=2 by default. RSH, 26 Sep. 2001 ; ;- PRO xctv2_cleanup, tlb widget_control, tlb, get_uvalue=info IF obj_valid((*info).dsp1) THEN obj_destroy, (*info).dsp1 IF obj_valid((*info).dsp2) THEN obj_destroy, (*info).dsp2 IF ptr_valid(info) THEN ptr_free, info RETURN END PRO XCTV2, Array1, Array2, H1, H2, $ DSP1=dsp1, DSP2=dsp2, GWIN=gwin, $ GROUP_LEADER=group_leader,XSIZE=xsize,YSIZE=ysize, $ PSFILE=psfile,PSTITLE=pstitle,X_SCROLL_SIZE=x_scroll_size, $ Y_SCROLL_SIZE=y_scroll_size,XLIM=xlim,YLIM=ylim, $ ZOOM_SIZE=zoom_size, PAN_SIZE=pan_size, NO_COPY=no_copy, $ PAN_LIMITS=pan_limits, RETAIN=retain on_error, 2 IF n_params(0) LT 2 THEN BEGIN print,'CALLING SEQUENCE: XCTV2, Array1, Array2, H1, H2' print,' OR XCTV2, Array1, Array2, H1' print,' OR XCTV2, Array1, Array2, 0, H2' print,' OR XCTV2, Array1, Array2' print,'KEYWORD PARAMETERS: ' print,' DSP1, DSP2, GWIN, GROUP_LEADER, XSIZE, YSIZE, ' print,' PSFILE, PSTITLE, X_SCROLL_SIZE, Y_SCROLL_SIZE, ' print,' XLIM, YLIM, ZOOM_SIZE, PAN_YSIZE, PAN_LIMITS, ' print,' RETAIN, NO_COPY' RETURN ENDIF ; ; Check arguments. sz = size(array1) ndim = sz[0] nel = sz[ndim+2] type1 = sz[n_elements(sz)-2] IF nel GT 0 AND ndim EQ 2 THEN BEGIN xdim = sz[1] & ydim = sz[2] ENDIF ELSE BEGIN message, 'Bad ARRAY1.' ENDELSE sz = size(array2) ndim = sz[0] nel = sz[ndim+2] type2 = sz[n_elements(sz)-2] IF nel GT 0 AND ndim EQ 2 THEN BEGIN xdim2 = sz[1] & ydim2 = sz[2] ENDIF ELSE BEGIN message, 'Bad ARRAY2.' ENDELSE IF keyword_set(h1) THEN BEGIN nelh1 = n_elements(h1) szh1 = size(h1) ndimh1 = szh1[0] typeh1 = szh1[n_elements(szh1)-2] IF (nelh1 GT 0) AND (ndimh1 NE 1 OR typeh1 NE 7) THEN BEGIN message, 'Bad HEADER1.' ENDIF IF nelh1 GT 0 THEN hu1 = h1 ENDIF nelh2 = n_elements(h2) szh2 = size(h2) ndimh2 = szh2[0] typeh2 = szh2[n_elements(szh2)-2] IF (nelh2 GT 0) AND (ndimh2 NE 1 OR typeh2 NE 7) THEN BEGIN message, 'Bad HEADER2.' ENDIF IF nelh2 GT 0 THEN hu2 = h2 ; ; Boil down the window size parameters, using defaults as necessary. IF n_elements(xsize) LE 0 THEN xsize=xdim IF n_elements(ysize) LE 0 THEN ysize=ydim IF n_elements(xlim) LE 1 THEN xlim=500 IF n_elements(ylim) LE 1 THEN ylim=500 IF n_elements(zoom_size) LE 1 THEN zoom_size=200 IF n_elements(pan_limits) LE 1 THEN pan_limits=[500,200] IF n_elements(pan_size) EQ 1 OR n_elements(pan_size) GT 2 THEN $ message, 'Explicit pan_size must have two elements.' IF n_elements(pan_size) LE 1 THEN $ pan_size=[round(200.0d0*double(xdim)/double(ydim)), 200] pan_fill_fac = max(double(pan_size)/double(pan_limits)) pan_size = round(pan_size/pan_fill_fac) IF n_elements(x_scroll_size) LT 1 THEN BEGIN IF xsize GT xlim THEN x_scroll_size=xlim $ ELSE x_scroll_size=xsize ENDIF IF n_elements(y_scroll_size) LT 1 THEN BEGIN IF ysize GT ylim THEN y_scroll_size=ylim $ ELSE y_scroll_size=ysize ENDIF IF n_elements(retain) LT 1 THEN retain=2 device, retain=retain ; ; Create top level base widget (overall frame). tlb = widget_base(title='XCTV2',row=1,group_leader=group_leader) ;dfltfont='6x13' ;widget_control, default_font=dfltfont ; ; Create image displays. dsp1 = obj_new('GANGEXAMINE', tlb, xsize=xsize, ysize=ysize, $ /kill_button, log_tag='xctv2a', $ x_scroll_size=x_scroll_size, $ y_scroll_size=y_scroll_size, $ /ps_dialog,zoomwin=zoom_size, $ panwin=pan_size,/readout,/vertical, $ header=hu1) dsp2 = obj_new('GANGEXAMINE', tlb, dsp1, dsp1, $ xsize=xsize, ysize=ysize, $ kill_button=0, log_tag='xctv2b', $ x_scroll_size=x_scroll_size, $ y_scroll_size=y_scroll_size, $ /ps_dialog,zoomwin=zoom_size, $ panwin=pan_size,/readout,/vertical, $ /sync, header=hu2, /blink) ; ; Generate on screen. widget_control, tlb, /realize ; ; Set up Postscript file name defaults. IF n_elements(pstitle) LE 0 THEN pstitle='' IF n_elements(psfile) LE 0 THEN psfile='idl.ps' dsp1->psfile, psfile, pstitle dsp2->psfile, psfile, pstitle ; ; Display images. IF type1 EQ 1 THEN dsp1->setdisplay, minval=0, maxval=255 IF type2 EQ 1 THEN dsp2->setdisplay, minval=0, maxval=255 IF keyword_set(no_copy) THEN BEGIN IF n_params(0) GT 0 THEN dsp1->draw, temporary(array1) IF n_params(0) GT 1 THEN dsp2->draw, temporary(array2) ENDIF ELSE BEGIN IF n_params(0) GT 0 THEN dsp1->draw, array1 IF n_params(0) GT 1 THEN dsp2->draw, array2 ENDELSE ; ; Get graphics window IDs. dsp1->id, draw_wid1 dsp2->id, draw_wid2 widget_control, draw_wid1, get_value=gwin1 widget_control, draw_wid2, get_value=gwin2 widget_control, tlb, tlb_set_title='Windows '+strn(gwin1) + $ ' and '+strn(gwin2) wset, gwin1 gwin = [gwin1,gwin2] ; ; Set up shared information. info = ptr_new({tlb:tlb, dsp1:dsp1, dsp2:dsp2}) widget_control, tlb, set_uvalue=info ; ; Hand over to widget manager. xmanager, 'xctv2', tlb, /no_block, cleanup='xctv2_cleanup' RETURN END