Viewing contents of file '../idllib/contrib/windt/dgtz_image.pro'
;+
; NAME:
;
; DGTZ_IMAGE
;
; PURPOSE:
;
; A widget application to interactively measure distances in an
; image, either between two points, two horizontal lines, or two
; vertical lines.
;
; CATEGORY:
;
; Image analysis
;
; CALLING SEQUENCE:
;
; DGTZ_IMAGE,IMAGE
;
; INPUTS:
;
; IMAGE = 2-D array containing image.
;
; OUTPUTS:
;
; The measured distances are listed on the widget, and
; can also be saved to a text file (using MORE.)
;
; KEYWORD PARAMETERS:
;
; UNITS - String specifying units. Default is 'units'.
;
; COMMON BLOCKS:
;
; dgtz_image, internal to this program.
;
; MODIFICATION HISTORY:
;
; David L. Windt, Bell Laboratories, May 1997
; windt@bell-labs.com
;
; Jul 1997: Corrected problem with widget labels
;-
;---procedure to save results-----------------------------------------------
pro dgtz_image_wt
common dgtz_image,dgtz_image,im,ref,mode, $
n_dist,dist,unit,xprof,yprof,cursor,sz
file=pickfile(/write)
if file eq '' then return
more,file=file, $
dist(0:n_dist-1,0), $
dist(0:n_dist-1,1), $
dist(0:n_dist-1,2), $
dist(0:n_dist-1,3), $
dist(0:n_dist-1,4), $
dist(0:n_dist-1,5)
;; call dgtz_image_plot, because pickfile erases the windows!
dgtz_image_plot,/init
return
end
;-procedure to draw the image and plots--------------------------------------
;
pro dgtz_image_plot,initialize=initialize
common dgtz_image
sx=float(sz(0))
sxmax=sz(1)
sy=float(sz(2))
symax=sz(3)
;; display image:
if keyword_set(initialize) then begin
widget_control,dgtz_image.iwindow,get_value=value & wset,value
tvscl,im
tvcrs,sx/2,sy/2,/device ; position cursor at center.
endif
; draw cross-hairs...
device,set_graphics=6 ; Use XOR.
widget_control,dgtz_image.iwindow,get_value=value & wset,value
plots,[cursor(0),cursor(0)],[0,sy],/device,color=6
plots,[0,sx],[cursor(1),cursor(1)],/device,color=6
device,set_graphics=3
;; plot profiles...
if keyword_set(initialize) then begin
widget_control,dgtz_image.xwindow,get_value=value & wset,value
plot,xprof(0,*),xprof(1,*),xmargin=[0,0],/xstyle,ymargin=[0,0],/ystyle
device,set_graphics=6
plots,[cursor(0)/sx,cursor(0)/sx],[0,1.],/normal,color=6
device,set_graphics=3
widget_control,dgtz_image.ywindow,get_value=value & wset,value
plot,yprof(1,*),xprof(0,*),xmargin=[0,0],/xstyle,ymargin=[0,0],/ystyle
device,set_graphics=6
plots,[0,1.],[cursor(1)/sy,cursor(1)/sy],/normal,color=6
device,set_graphics=3
endif
return
end
;---procedure to compute distances--------------------------------------------
pro dgtz_image_dist,event
common dgtz_image
if n_dist gt 0 then begin
;; initialize periods.
dist(*,0)=0
if ref(1) eq 0 then ref(1)=ref(0)
;; compute period in UNITS..
for i=0,n_dist-1 do dist(i,0)=(ref(0)/ref(1))*dist(i,1)
;; create string array.
a=strarr(n_dist)
for i=0,n_dist-1 do a(i)=strtrim(abs(fix(dist(i,1))),2)+ $
' pixels = '+strtrim(dist(i,0),2)+' '+unit
endif else a=''
;; label widget:
widget_control,dgtz_image.dist,set_value=a
;; set Save sensitivity:
widget_control,dgtz_image.save,sensitive=n_dist gt 0
return
end
;---procedure to cursor events----------------------------------------
pro dgtz_image_curs,event
common dgtz_image
; update cursor.
widget_control,dgtz_image.cursor,set_value= $
'X = '+strtrim(event.x,2)+', Y = '+ $
strtrim(event.y,2)+', Intensity = '+ $
strtrim(fix(im(event.x,event.y)),2)
sx=float(sz(0))
sxmax=sz(1)
sy=float(sz(2))
symax=sz(3)
device,set_graphics=6 ; Use XOR.
; draw cross-hairs...
widget_control,dgtz_image.iwindow,get_value=value & wset,value
plots,[cursor(0),cursor(0)],[0,sy],/device,color=6
plots,[event.x,event.x],[0,sy],/device,color=6
plots,[0,sx],[cursor(1),cursor(1)],/device,color=6
plots,[0,sx],[event.y,event.y],/device,color=6
; indicate current cursor position on profiles...
widget_control,dgtz_image.xwindow,get_value=value & wset,value
plots,[cursor(0)/sx,cursor(0)/sx],[0,1.],/normal,color=6
plots,[event.x/sx,event.x/sx],[0,1.],/normal,color=6
widget_control,dgtz_image.ywindow,get_value=value & wset,value
plots,[0,1.],[cursor(1)/sy,cursor(1)/sy],/normal,color=6
plots,[0,1.],[event.y/sy,event.y/sy],/normal,color=6
device,set_graphics=3 ; back to default.
cursor=[event.x,event.y,cursor(2)]
return
end
;---procedure to handle widget events----------------------------------------
pro dgtz_image_ev,event
common dgtz_image
on_ioerror,finish
widget_control,event.id,get_uvalue=uvalue
if tag_names(event,/structure) eq 'WIDGET_DRAW' then begin
;; draw events:
;; call cursor event handler
dgtz_image_curs,event
;; determine what mouse button was pressed:
if event.press gt 0 then begin
case event.press of
;; Left click: measure distance:
1: begin
;; has 1st point been digitized?
if cursor(2) eq 1 then begin
dist(n_dist,4)=event.x
dist(n_dist,5)=event.y
x1=dist(n_dist,2)
y1=dist(n_dist,3)
x2=dist(n_dist,4)
y2=dist(n_dist,5)
case mode of
0: begin ; pts.
if (x2 eq x1) and (y2 eq y1) then goto,finish
dist(n_dist,1)=sqrt((x2-x1)^2+(y2-y1)^2)
end
1: begin ; h-lines
if (y2 eq y1) then return
dist(n_dist,1)=y2-y1
end
2: begin ; v-lines
if (x2 eq x1) then return
dist(n_dist,1)=x2-x1
end
endcase
;; increment counter and compute new distances:
n_dist=n_dist+1
dgtz_image_dist
;; reset flag:
cursor(2)=0
widget_control,dgtz_image.status, $
set_value='Click Left for Distances, Right for Conversion Reference Pixels.'
endif else begin
;; need second point:
dist(n_dist,2)=event.x
dist(n_dist,3)=event.y
widget_control,dgtz_image.status, $
set_value='Digitize Second Point...'
;; set flag:
cursor(2)=1
endelse
end
4: begin $
;; Right click: measure reference distance:
;; has 1st point been digitized?
if cursor(2) eq 1 then begin
ref(4)=event.x
ref(5)=event.y
x1=ref(2)
y1=ref(3)
x2=ref(4)
y2=ref(5)
case mode of
0: begin ; pts.
if (x2 eq x1) and (y2 eq y1) then goto,finish
ref(1)=sqrt((x2-x1)^2+(y2-y1)^2)
end
1: begin ; h-lines
if (y2 eq y1) then return
ref(1)=abs(y2-y1)
end
2: begin ; v-lines
if (x2 eq x1) then return
ref(1)=abs(x2-x1)
end
endcase
;; update widgets...
widget_control,dgtz_image.ref_pix, $
set_value=strtrim(fix(ref(1)),2)+' pixels='
widget_control,dgtz_image.ref_con, $
set_value=strtrim(ref(0)/ref(1),2)+' '+strtrim(unit,2)+'/pixel'
;; compute new distances:
dgtz_image_dist
;; reset flag:
cursor(2)=0
widget_control,dgtz_image.status, $
set_value='Click Left for Distances, Right for Conversion Reference Pixels.'
endif else begin
;; wait for second point:
ref(2)=event.x
ref(3)=event.y
widget_control,dgtz_image.status, $
set_value='Digitize Second Reference Point...'
;; set flag:
cursor(2)=1
endelse
end
else:;;
endcase
endif
return
endif else begin
;; buttons:
case uvalue of
'save': dgtz_image_wt
'xloadct': xloadct,group=dgtz_image.base
'done': begin
widget_control,event.top,/destroy
return
end
'points': mode=0
'hlines': mode=1
'vlines': mode=2
'clear': begin
if event.value eq 0 then begin
;; clear last:
n_dist=(n_dist-1) > 0
dgtz_image_dist
endif else begin
;; clear all:
n_dist=0
dgtz_image_dist
endelse
end
'ref_val': begin
;; get new value:
widget_control,dgtz_image.ref_val,get_value=value
if value(0) ne 0 then ref(0)=float(value(0))
;; update widgets:
widget_control,dgtz_image.ref_val,set_value= $
strtrim(ref(0),2)
widget_control,dgtz_image.ref_con, $
set_value=strtrim(ref(0)/ref(1),2)+ $
' '+strtrim(unit,2)+'/pixel'
;; compute new distances...
dgtz_image_dist
end
else:;;
endcase
endelse
finish:;;
return
end
;---procedure to create main widgets---------------------------------------
pro dgtz_image,image,units=units
common dgtz_image
if n_params() lt 1 then message,'usage: dgtz_image, image'
im=image ; image
sz=size(im) ; size of image
sx=float(sz(1)) ; x size
sy=float(sz(2)) ; y size
sxmax=640 ; maximum image window size, beyond which
symax=512 ; scroll bars are implemented.
sz=[sx,sxmax,sy,symax]
; reference: [distance, delta(pixels), pixelx0, pixely0, pixelx1, pixely1]
ref=[1.,1.,0,1./sqrt(2),0.,1./sqrt(2)]
if keyword_set(units) then unit=units else unit='units'
mode=0 ; initialize measurement mode.
n_dist=0 ; initialize number of periods defined
dist=fltarr(100,6) ; array of distances.
; compute average profiles...
xprof=fltarr(2,sx)
yprof=fltarr(2,sy)
xprof(0,*)=findgen(sx)
yprof(0,*)=findgen(sy)
xprof(1,*)=im#replicate(1,sy)/sy
yprof(1,*)=replicate(1,sx)#im/sx
; define cursor position.
cursor=[sx/2,sy/2,0]
; create widget...
dgtz_image={base:0L, $
save:0L, $ ; save button.
status:0L, $ ; status label.
cursor:0L, $ ; cursor position.
iwindow:0L, $ ; image window.
xwindow:0L, $ ; x profile.
ywindow:0L, $ ; y profile.
mode:0L, $ ; mode buttons.
ref_val:0L, $ ; reference distance value.
ref_pix:0L, $ ; reference distance pixels.
ref_con:0L, $ ; reference conversion factor.
clear:0L, $ ; clear buttons.
dist:0L} ; distances list
dgtz_image.base=widget_base(title='Image Distance Measurement',/col,mbar=mbar)
file_menu=widget_button(mbar,/menu,value='File')
dgtz_image.save=widget_button(file_menu,value='Save...',uvalue='save')
button=widget_button(file_menu,value='Adjust Color Table...',uvalue='xloadct')
button=widget_button(file_menu,value='Done',uvalue='done',/separator)
mode_menu=widget_button(mbar,/menu,value='Mode')
button=widget_button(mode_menu,value='Measure distance between two points',uvalue='points')
button=widget_button(mode_menu,value='Measure distance between two horizontal lines',uvalue='hlines')
button=widget_button(mode_menu,value='Measure distance between two vertical lines',uvalue='vlines')
dgtz_image.status=widget_label(dgtz_image.base,/align_left, $
value='Click Left for Distances, ' + $
'Right for Conversion Reference Pixels.')
dgtz_image.cursor=widget_label(dgtz_image.base,value=string(replicate(50B,50)),/align_left)
row=widget_base(dgtz_image.base,/row)
col=widget_base(row,/column)
dgtz_image.ywindow=widget_draw(col,xsize=100,ysize=(sy<symax))
col=widget_base(row,/column)
if (sx gt sxmax) or (sy gt symax) then $
dgtz_image.iwindow=widget_draw(col,xsize=sx, $
ysize=sy,/scroll, $
x_scroll_size=(sx<sxmax), $
y_scroll_size=(sy<symax), $
/button,/motion) $
else dgtz_image.iwindow=widget_draw(col,xsize=sx, $
ysize=sy,/button,/motion)
dgtz_image.xwindow=widget_draw(col,xsize=(sx < sxmax),ysize=100)
base=widget_base(row,/column)
base=widget_base(base,/column,/frame)
label=widget_label(base,value='Distances:',/align_left)
dgtz_image.dist=widget_text(base,xsize=30,ysize=15,/scroll)
buttons=cw_bgroup(base,['Clear Last','Clear All'],uvalue='clear',/row)
row=widget_base(dgtz_image.base,/row)
dgtz_image.ref_val=cw_field(row,/string,xsize=10,ysize=1,/return_events, $
value=strtrim(ref(0),2),uvalue='ref_val', $
title='Conversion:')
label=widget_label(row,value=strtrim(unit,2)+' per')
dgtz_image.ref_pix=widget_label(row,value=strtrim(fix(sx>sy),2)+' pixels=')
dgtz_image.ref_con=widget_label(row,value=strtrim(ref(0)/ref(1),2)+' '+$
strtrim(unit,2)+'/pixel ')
;; unmap widget
widget_control,dgtz_image.base,map=0
;; realize widget
widget_control,dgtz_image.base,/realize
;; clear curser area:
widget_control,dgtz_image.cursor,set_value=''
;; reset conversion pixels:
widget_control,dgtz_image.ref_pix,set_value=strtrim(fix(ref(1)),2)+' pixels='
;; call dgtz_image_plot to paint the draw widgets:
dgtz_image_plot,/init
;; set Save sensitivity:
widget_control,dgtz_image.save,sensitive=0
;; map widget
widget_control,dgtz_image.base,map=1
xmanager,"dgtz_image",dgtz_image.base,event_handler="dgtz_image_ev"
end