;+ ; NAME: ; cw_pixed ; PURPOSE: (one line) ; Pixel editor. ; DESCRIPTION: ; This compound widget may be used to edit a grid of pixels in an array. ; Unless near the edge of the image, the grid is centered on (xpos, ypos). ; The left column and the bottom row display the y and x coordinates, ; respectively, for the grid. Xpos and ypos are enclosed in brackets, ; for identification. ; CATEGORY: ; Compound Widgets ; CALLING SEQUENCE: ; result = cw_pixed( parent, image, xpos, ypos ) ; INPUTS: ; parent : The id of the parent widget. ; image : The array to be edited. ; xpos, ypos : The pixel at this location in the array, along with a ; collection of its neighbors, will be displayed as a grid of ; editable text widgets. ; ; OPTIONAL INPUT PARAMETERS: ; ; INPUT KEYWORD PARAMETERS: ; GRIDsize = The size of the grid of surrounding pixels. Default ; is 7 pixels (7X7 grid). Note: In order to maintain symmetry ; about the center pixel, the grid size needs to be odd. ; Therefore, even values will be increased by 1 pixel. ; ; OUTPUTS: ; result : The id of the compound widget. ; COMMON BLOCKS: ; ; SIDE EFFECTS: ; This compound widget generates events with the following structure: ; { id:0L, top:0L, handler:0L, type:0, count:0, x:0, y:0, value:v } ; where, ; type The event type (0=Done, 1=single pixel changed). ; count Specifies the number of elements in the remaining three tags ; x and y Coordinates of changed pixel(s). ; value Value(s) for changed pixel(s). ; ; The zero values in the above structure indicate the data types for the ; those tags, not the actual values. The 'value' tag will be the same type ; as the data in the array being edited. ; ; RESTRICTIONS: ; ; PROCEDURE: ; ; MODIFICATION HISTORY: ; Written by Doug Loucks, Lowell Observatory, April 28, 1994. ; 95/10/31, MWB, Fixed widget layout problem caused by IDL v4.0 changes. ; 2000/05/08, MWB, Control UPDATE to speed up 2-n invocations of this tool. ;- ; ------------------------------------------------------------------------------ ; Procedure cw_pixed_eve ; Event handler. function cw_pixed_eve, event widget_control, event.id, GET_VALUE=value, GET_UVALUE=uvalue, /HOURGLASS stash = widget_info( event.handler, /CHILD ) widget_control, stash, GET_UVALUE=state, /NO_COPY out_event = 0 case event.id of state.doneid : begin child = WIDGET_INFO( event.top, /CHILD ) widget_control, stash, SET_UVALUE=state, /NO_COPY widget_control, event.top, MAP=0 widget_control, child, /DESTROY return, 0 end state.restoreid : begin w = WHERE( state.chgdids GT 0, count ) IF count GT 0 THEN BEGIN x = INTARR( count ) y = INTARR( count ) v = REPLICATE( state.tval, count ) widget_control, event.top, UPDATE=0 FOR j=0, count-1 DO BEGIN widget_control, state.chgdids[w[j]], GET_UVALUE=uv x[j] = uv.x y[j] = uv.y v[j] = state.savgrid[ uv.x, uv.y ] text = STRING( v[j], FORMAT=state.fmt ) widget_control, state.chgdids[w[j]], SET_VALUE=text state.chgdids[ w[j] ] = 0 ENDFOR widget_control, event.top, UPDATE=1 out_event = { id:event.handler, top:event.top, handler:0L, type:1, $ count:count, x:state.xset+x, y:state.yset+y, value:v } ENDIF END ELSE : BEGIN widget_control, event.id, GET_VALUE=value, GET_UVALUE=uvalue x = uvalue.x y = uvalue.y state.grid[ x, y ] = value[0] out_event = { id:event.handler, top:event.top, handler:0L, type:1, $ count:1, x:[state.xset+x], y:[state.yset+y], value:[state.tval] } state.chgdids[ x, y ] = event.id out_event.value = value[0] END ENDCASE widget_control, stash, SET_UVALUE=state, /NO_COPY return, out_event END ; ------------------------------------------------------------------------------ ; Procedure cw_pixed ; Compound Widget Pixel Editor. function cw_pixed, parent, image, xpos, ypos, GRIDsize=in_gridsize, $ UVALUE=in_uvalue stat = size( image ) xsize = stat[1] ysize = stat[2] typecode = stat[3] CASE typecode OF 1 : BEGIN width = 4 fmt = '(I4)' tval = 0B END 2 : BEGIN width = 6 fmt = '(I6)' tval = 0 END 3 : BEGIN width = 12 fmt = '(I12)' tval = 0L END 4 : BEGIN width = 12 fmt = '(G0.0)' tval = 0.0 END 5 : BEGIN width = 14 fmt = '(G0.0)' tval = 0.0 END ELSE : BEGIN MESSAGE, 'Error. Typecode ' + STRING(typecode,FORMAT='(G0.0)') + $ ' not supported', /INFO width = 12 fmt = '(G0.0)' tval = 0.0 END ENDCASE IF KEYWORD_SET( in_gridsize ) THEN gridsize=in_gridsize ELSE gridsize=7 IF (gridsize MOD 2) EQ 0 THEN gridsize=gridsize+1 hw = gridsize / 2 xset = xpos - hw yset = ypos - hw IF xset LT 0 THEN xset = 0 IF yset LT 0 THEN yset = 0 IF xset+gridsize GE xsize THEN xset=xsize-gridsize IF yset+gridsize GE ysize THEN yset=ysize-gridsize IF !order EQ 0 THEN BEGIN y1 = gridsize - 1 y2 = 0 dy = -1 ENDIF ELSE BEGIN y1 = 0 y2 = gridsize - 1 dy = 1 ENDELSE ; Extract grid to be edited, and make a copy that won't be touched. grid = image[xset:xset+gridsize-1, yset:yset+gridsize-1 ] savgrid = grid if keyword_set(in_uvalue) then begin mainbase = widget_base(parent,COLUMN=1,EVENT_FUNC='cw_pixed_eve', $ UVALUE=in_uvalue) endif else begin mainbase = widget_base(parent,COLUMN=1,EVENT_FUNC='cw_pixed_eve') endelse widget_control,mainbase,UPDATE=0 wb = widget_base(mainbase,ROW=1) doneid = widget_button(wb,VALUE='Done') restoreid = widget_button(wb,VALUE='Restore Initial Values') cba = widget_base(mainbase,COLUMN=gridsize+1,/frame) xids = lonarr(gridsize,/nozero) yids = lonarr(gridsize,/nozero) gridids = lonarr(gridsize, gridsize,/nozero) f = '(G0.0)' ; Create the y label ids for j=y1,y2,dy do begin text = string(yset+j,format=f) mark = (yset+j) eq ypos if mark then text = '[' + text + ']' yids[j] = widget_label(cba,value=text) endfor w0 = widget_label( cba, value=' ' ) ; create the x label and grid ids for i=0,gridsize-1 do begin for j=y1,y2,dy do begin text = string(image[xset+i,yset+j],FORMAT=f) w0 = widget_text(cba,VALUE=text,UVALUE={x:i,y:j},Xsize=width,/EDIT) gridids[i,j] = w0 endfor text = string(xset+i,FORMAT=f) mark = (xset+i) eq xpos if mark then text = '[' + text + ']' xids[i] = widget_label(cba,VALUE=text) endfor ; scan through all the items in this base and find the max x and y sizes. max_xs=0 max_ys=0 t_b = widget_info(cba,/child) ; gets first child while (t_b ne 0L) do begin geo = widget_info(t_b,/geometry) max_xs=max([max_xs,geo.scr_xsize]) max_ys=max([max_ys,geo.scr_ysize]) t_b = widget_info(t_b,/sibling) ; gets next child (0=no more) endwhile ; Now, go back through all widget items and set them to the same size. t_b = widget_info(cba,/child) while (t_b ne 0L) do begin widget_control,t_b,SCR_Xsize=max_xs,SCR_YSIZE=max_ys t_b = widget_info(t_b,/sibling) endwhile m = median(grid) xp = xpos - xset yp = ypos - yset x = indgen(gridsize) ya = grid[ xp, * ] yb = grid[ *, yp ] w = where( x ne xp, count ) coeff1 = goodpoly( x[w]+xpos, ya[w], 1, 3.0, yfit ) coeff2 = goodpoly( x[w]+ypos, yb[w], 1, 3.0, yfit ) ny1 = poly( xpos, coeff1 ) ny2 = poly( ypos, coeff2 ) text = string('Grid Median: ',m,' Linear Interpolation, Row: ',ny2, $ ' Column: ',ny1,format='(A,G0.0,A,G0.0,A,G0.0)') w0 = widget_label(mainbase,VALUE=text) stash = widget_info( mainbase, /CHILD ) widget_control, mainbase, UPDATE=1 state = { chgdids: lonarr(gridsize,gridsize), $ ; flags, set if cell modified fmt: fmt, $ grid: grid, $ gridsize: gridsize, $ savgrid: savgrid, $ tval: tval, $ xpos: xpos, $ xset: xset, $ ypos: ypos, $ yset: yset, $ doneid: doneid, $ gridids: gridids, $ restoreid: restoreid, $ xids: xids, $ yids: yids, $ mainbase: mainbase} widget_control,stash,SET_UVALUE=state,/no_copy return,mainbase end