;+ ; NAME: ; RemoteView_Display3D ; PURPOSE: ; Collapses the 3D volume data in FOVCube to a 2D view ready for display using ; some form of rgbo rendering ; CATEGORY: ; RemoteView project ; CALLING SEQUENCE: PRO RemoteView_Display3D, D3D, FOVInfo, FOVCube, FOVLoc, iView, $ FOVCubeB = FOVCubeB , $ voxel = Voxel , $ base_dir = base_dir , $ base_name = base_name , $ images = images , $ title = title , $ format = format , $ logo = logo , $ rim = rim , $ silent = silent , $ view_nr = view_nr , $ _extra = _extra ; INPUTS: ; D3D array[1]; type: structure ; info about volume data (see href=RemoteView_Init=) ; FOVCube array[nX,nY,nZ]; type: float ; function values covering fov of nX,nY lines of sight ; at nZ positions along line of sight ; FOVLoc array[3,nX,nY,nZ]; type: float ; heliographic locations at all line of sight segments. ; Always returned in spherical coordinates (even for ; rectangular matrix) i.e. heliographic longitude, ; latitude in radians; and heliocentric distance in AU. ; iView scalar; type: integer ; image number (used only in file name construction) ; OPTIONAL INPUT PARAMETERS: ; FOVCubeB=FOVCubeB ; array[nX,nY,nZ]; type: float ; magnetic field values covering fov of nX,nY lines of ; sight at nZ positions along line of sight ; voxel=Voxel scalar; type: integer; default: 0 ; 0: skip rgbo calculation (bodies and orbits only) ; 1: use IDL Voxel_Proj function ; (doesn't work in IDL 5.4 unless the patch ; Voxel_Proj2 is available) ; 2: home-brew rgbo rendering (needs work) ; base_dir=base_dir ; scalar; type: string; default: getenv('TUB') ; destination directory for all image files ; base_name-base_name ; scalar; type: string; default: f3dfnc ; base name for output image files ; view_nr=view_nr scalar; type: integer; default: none ; overrides argument 'iView' ; iView is the loop parameter used in the calling ; procedure href=remoteview= to loop over multiple ; view. Often remoteview itself is called in a loop ; processing a single view per call. iView will ; always be 1 in this case, and image files would ; be overwritten. Keyword view_nr can be added to ; the remoteview call to replace iView and avoid ; overwriting of images. ; logo=logo scalar; type: string; default: none ; name of tiny image file to be put in lowerleft corner of ; display. Must be a truecolor image. ; rim=rim array[4]; type: float; default: [0.0,0.15,0.1,0.1] ; OUTPUTS: ; (images to display or file) ; images=images scalar or array; type: string ; fully-qualified names of image files ; (if no images were created, 'images' will be undefined) ; INCLUDE: @compile_opt.pro ; On error, return to caller ; CALLS: ; InitVar, CheckDir, RemoteView_Voxel, RemoteView_ZPix, reset_colors ; TimeGet, TimeUnit, twin, destroyvar, boost, img_read ; RemoteView_Matte, RGBO_DepthCue, SuperArray, checkdir ; COMMON BLOCKS: common SkyDisplaySave, PreviousImage ; PROCEDURE: ; The common block is used to store the left image when an interleaved ; image is requested. (after the right image is calculated the left and ; right images are merged). ; MODIFICATION HISTORY: ; AUG-2000, Paul Hick (UCSD/CASS) ; AUG-2002, Paul Hick (UCSD/CASS) ; Our home-made rgbo rendering engine (voxel=2) seems to work now. ; Added option to include depth cueing, and an option to do 'radial ; cueing' (multiply opacity with a radial distance-dependent function). ; Added color legend to display, together with minimal annotation. ; JUN-2004, Paul Hick (UCSD/CASS; pphick@ucsd.edu) ; A negative Voxel value now suppresses the labeling and color bar. ;- InitVar, view_nr, iView stereo = FOVInfo.view_stereo left = stereo AND (view_nr mod 2) InitVar, silent, 0 InitVar, Voxel , 0 nDim = size(FOVCube, /dim) ; The edges of the fov are at normal coordinates 0 and 1. This corresponds ; to the centers of voxels 0 and nDim-1 Sx = [0,nDim[0]-1] Sy = [0,nDim[1]-1] Sz = [0,nDim[2]-1] Sx += 0.5 Sy += 0.5 Sz += 0.5 !x.s = [-Sx[0],1.0]/(Sx[1]-Sx[0]) !y.s = [-Sy[0],1.0]/(Sy[1]-Sy[0]) !z.s = [-Sz[0],1.0]/(Sz[1]-Sz[0]) CASE Voxel EQ 0 OF 0: BEGIN ; Set up keywords for special treatment of bad, high and low values in ; the volume data array before converting to byte ;FOVBad = where(1-finite(FOVCube), n) ;CASE n OF ;0 : destroyvar, FOVBad ;ELSE: OpaBad = 0.0 ;ENDCASE ;FOVLow = where( finite(FOVCube) and FOVCube lt D3D.full_range_v[0], n) ;CASE n OF ;0 : destroyvar, FOVLow ;ELSE: OpaLow = 0.0 ;ENDCASE ;FOVHigh = where( finite(FOVCube) and FOVCube gt D3D.full_range_v[1], n) ;CASE n OF ;0 : destroyvar, FOVHigh ;ELSE: OpaHigh = 0.0 ;ENDCASE zpix = tvrd() ; 2D byte array zbuf = tvrd(/words,/chan) ; 2D int array: Read depth values from the Z-buffer ; Convert volume data to byte values in range D3D.rgb_range ; NaN's are set to rgb_range_v[0] FOVCube = D3D.rgb_range_v[0]+bytscl(FOVCube,top=D3D.rgb_range_v[1]-D3D.rgb_range_v[0], $ min=D3D.full_range_v[0],max=D3D.full_range_v[1],/nan) ;FOVCubeB = exp(-FOVCubeB*FOVCubeB) ;FOVCubeB = D3D.rgb_range_b[0]+bytscl(FOVCubeB,top=D3D.rgb_range_b[1]-D3D.rgb_range_b[0], $ ; min=D3D.full_range_b[0],max=D3D.full_range_b[1],/nan) ; Sets NaN's to zero ; Multiply colors in rgbo vector with opacity rgbo = D3D.rgbo rgbo[*,0:2] *= SuperArray(rgbo[*,3]/255.0,3,/trail) ; 3D byte array: true-color image CASE abs(voxel) OF 1: BEGIN CASE !version.release OF '5.4': message, 'voxel_proj does not work in v5.4 for a t3d matrix of unity' ELSE : zpix = voxel_proj (FOVCube, round(rgbo), zpix=zpix, zbuf=zbuf) ENDCASE END 2: BEGIN ; Pick up the mattes to be applied to opacity (and color?) ; RGBO_DepthCue does a standard depth cue operation (using ; keyword cue_depth) RGBO_DepthCue, _extra=_extra, dimension=nDim, matte=matte ; Apply a "radial cue": decreasing opacity with increasing ; radial distance. RemoteView_Matte, FOVLoc, _extra=_extra, matte=Matte zpix = RGBO_Project(FOVCube, rgbo, zpix=zpix, zbuf=zbuf, $ bad_data =FOVBad , bad_opacity =OpaBad , $ low_data =FOVlow , low_opacity =OpaLow , $ high_data=FOVhigh, high_opacity=OpaHigh, matte=Matte) END ENDCASE InitVar, rim, [0.0,0.12,0.1,0.1] IF Voxel GT 0 AND total(rim) NE 0 THEN BEGIN rim = round([ rim[0:1]*D3D.xysize[0],rim[2:3]*D3D.xysize[1]]) xysize = D3D.xysize+[rim[0]+rim[1],rim[2]+rim[3]] bar = [round(0.5*rim[1]),D3D.xysize[1]] set_plot,'Z' device, z_buffering=0, set_resolution=xysize reset_colors erase, !p.background xyouts, 0.02, 0.95, /normal, TimeGet(FOVInfo.view_time, /ymd, upto=TimeUnit(/min)), _extra=_extra IF IsType(title, /defined) THEN xyouts, 0.85, 0.02, /normal, title, align=1, _extra=_extra InitVar, format, '' CASE format OF '': BEGIN xyouts, 0.98, 0.02, /normal, strcompress(round(D3D.full_range_v[0])), align=1, _extra=_extra xyouts, 0.98, 0.95, /normal, strcompress(round(D3D.full_range_v[1])), align=1, _extra=_extra END ELSE: BEGIN xyouts, 0.98, 0.02, /normal, string(D3D.full_range_v[0],format=format), align=1, _extra=_extra xyouts, 0.98, 0.95, /normal, string(D3D.full_range_v[1],format=format), align=1, _extra=_extra END ENDCASE tmp = zpix zpix = SuperArray(tvrd(),3,/trail) ; Insert remote view zpix[rim[0]:rim[0]+D3D.xysize[0]-1,rim[2]:rim[2]+D3D.xysize[1]-1,*] = tmp ; Insert logo IF IsType(logo, /string) THEN BEGIN IF img_read(logo, logo_img, truedim=3, /silent) THEN BEGIN tmp = size(logo_img, /dim) zpix[0:tmp[0]-1,0:tmp[1]-1,*] = logo_img ENDIF ENDIF ; Insert color bar tmp = D3D.rgbo[D3D.rgb_range_v[0]:D3D.rgb_range_v[1],0:2] tmp = congrid (tmp,bar[1],3) tmp = byte(round(tmp)) tmp = SuperArray(tmp,bar[0],/lead) zpix[xysize[0]-bar[0]:*,rim[2]:rim[2]+bar[1]-1,*] = tmp ENDIF END 1: zpix = tvrd() ; 2D byte array ENDCASE IF D3D.Interleave THEN BEGIN CASE left OF 0: BEGIN PreviousImage = zpix RETURN END 1: BEGIN OddRows = 1+2*indgen(D3D.xysize[1]/2) zpix[*,OddRows,*] = PreviousImage[*,OddRows,*] END ENDCASE ENDIF ; The 24-bit Tiff file contains the full 24-bit true color image ; The reduction to an 8-bit pseudo-image is done by COLOR_QUAN. The resulting ; image often has 'dirty' pixels with the wrong colors. to_base = IsType(base_dir,/defined) IF to_base THEN to_base = checkdir(base_dir) IF NOT to_base THEN base_dir = getenv('TUB') InitVar, base_name, 'earth_remoteview' file = filepath(root=base_dir,base_name+string(format='(I3.3)',view_nr)) IF (1B-D3D.Interleave)*stereo THEN file += (['r','l'])[left] set_plot, !TheTerminal reset_colors destroyvar, images IF D3D.Bmp8 THEN BEGIN tmp_file = file+'.bmp' boost, images, tmp_file write_bmp, tmp_file, color_quan(zpix,3,r,g,b), r,g,b IF silent LE 0 THEN message, /info, 'created '+tmp_file ENDIF IF D3D.Bmp24 THEN BEGIN tmp_file = file+'.bmp' boost, images, tmp_file write_bmp, tmp_file, reverse( transpose(zpix, [2,0,1]) ,1) IF silent LE 0 THEN message, /info, 'created '+tmp_file ENDIF IF D3D.Tiff24 THEN BEGIN ; Writing true-color (24-bit) Tiff-file tmp_file = file+'.tif' boost, images, tmp_file ;write_tiff, tmp_file, red=reverse(zpix[*,*,0],2), gr=reverse(zpix[*,*,1],2), bl=reverse(zpix[*,*,2],2), planarconfig=2 write_tiff, tmp_file, red=zpix[*,*,0], gr=zpix[*,*,1], bl=zpix[*,*,2], planarconfig=2 IF silent LE 0 THEN message, /info, 'created '+tmp_file ENDIF IF D3D.Tiff8 THEN BEGIN ; Writing pseudo-color (8-bit) Tiff-file tmp_file = file+'.tif' boost, images, tmp_file write_tiff, tmp_file, reverse( color_quan(zpix,3,r,g,b) ,2), red=r, gr=g, bl=b IF silent LE 0 THEN message, /info, 'created '+tmp_file ENDIF IF D3D.PNG THEN BEGIN tmp_file = file+'.png' boost, images, tmp_file write_png, tmp_file, transpose(zpix, [2,0,1]) IF silent LE 0 THEN message, /info, 'created '+tmp_file ENDIF IF D3D.Gif THEN BEGIN tmp_file = file+'.gif' boost, images, tmp_file write_gif, tmp_file, color_quan(zpix,3,r,g,b), r, g, b IF silent LE 0 THEN message, /info, 'created '+tmp_file ENDIF IF D3D.PPM THEN BEGIN tmp_file = file+'.ppm' boost, images, tmp_file write_ppm, tmp_file, zpix IF silent LE 0 THEN message, /info, 'created '+tmp_file ENDIF IF D3D.JPG THEN BEGIN tmp_file = file+'.jpg' boost, images, tmp_file write_jpeg, tmp_file, zpix, true=3 IF silent LE 0 THEN message, /info, 'created '+tmp_file ENDIF IF D3D.Display THEN BEGIN npix = size(zpix, /dim) twin, /show, xsize=npix[0], ysize=npix[1], /nocoordinates, $ ;twin, /show, xsize=D3D.xysize[0], ysize=D3D.xysize[1], /nocoordinates, $ tl =(1B-stereo) or D3D.Interleave, $ br =(1B-D3D.Interleave)*stereo*(1B-left), $ bl =(1B-D3D.Interleave)*stereo*left ;IF size(zpix, /n_dim) EQ 3 AND Voxel NE 0 AND !d.n_colors EQ 2L^24 THEN BEGIN ; True-color display IF size(zpix, /n_dim) EQ 3 AND Voxel NE 0 AND !d.n_colors GT 256 THEN BEGIN ; True-color display loadct, 0 ; Why am I doing this??? tv, zpix, true=(where(npix EQ 3))[0]+1 ENDIF ELSE BEGIN ; Convert to 8-bit image for pseudo-display true = size(zpix, /n_dim) EQ 3 IF true THEN zpix = color_quan(zpix,3,r,g,b) tv, zpix IF true THEN tvlct, r,g,b ENDELSE ENDIF ;CASE n_elements(images) OF ;0 : ;1 : destroyvar, images ;ELSE: images = images[1:*] ;ENDCASE RETURN & END