source: trunk/SRC/Picture/image_viewer.pro @ 325

Last change on this file since 325 was 325, checked in by pinsard, 16 years ago

modification of some headers (+some corrections) to prepare usage of the new idldoc

  • Property svn:keywords set to Id
File size: 46.4 KB
Line 
1;+
2;
3; @file_comments
4; The purpose of this program is to provide an interactive tool that can be used
5; to view JPEG, BMP, GIF, PNG, and TIFF picture files.  Images are loaded into
6; memory, so the initial file access may take a while, but once each picture has
7; been opened they can all be viewed in a very rapid fashion.
8;
9; @categories
10; Visualization, Widget
11;
12; @param EVENT {in}{required}
13;
14; @restrictions
15; While this program is running in an IDL session it will change the current
16; working directory, enables/disables color decomposition, and sets !QUIET=1,
17; !ORDER=0, & !P.BACKGROUND=0.  These settings are returned to their initial
18; settings before the program was initiated once it is terminated.
19;
20; @restrictions
21; This program is supported in IDL version 5.5 and newer.  In order to open
22; GIF files or TIFF files with LZW compression the copy of IDL being used must
23; be licensed with these features.  IDL only supports BMP files in the standard
24; Windows format and does not support OS2 bitmaps.
25;
26; @history
27; Written by: AEB, 1/02.
28;
29; @version
30; $Id$
31;_
32;
33PRO image_viewer_open_files,event
34;THIS PROCEDURE IS CALLED WHEN A USER SELECTS "File > Open Picture Files" FROM THE MAIN MENU
35;
36  compile_opt idl2, strictarrsubs
37;
38;error handling:
39!ERROR_STATE.CODE=0
40CATCH,error
41if error NE 0 then begin
42  HELP,/LAST_MESSAGE,OUTPUT=traceback
43  messageStr=['Error Caught :','',traceback]
44  dummy=DIALOG_MESSAGE(messageStr,/ERROR)
45  ;if status report dialog is still active, destroy it:
46  if SIZE(tlb,/TYPE) NE 0 then WIDGET_CONTROL,tlb,/DESTROY
47  RETURN
48endif
49;obtain state structure for top-level-base from its UVALUE:
50WIDGET_CONTROL,event.top,GET_UVALUE=pState
51;prompt user to select files with native file selection dialog:
52if (*pState).gifFlag EQ 1 then filter=['*.JPG','*.jpg','*.JPEG','*.jpeg','*.JPE','*.jpe',$
53  '*.JFIF','*.jfif','*.GIF','*.gif','*.BMP','*.bmp','*.TIF','*.tif','*.TIFF','*.tiff',$
54  '*.PNG','*.png'] else $
55  filter=['*.JPG','*.jpg','*.JPEG','*.jpeg','*.JPE','*.jpe','*.JFIF','*.jfif','*.BMP','*.bmp',$
56  '*.TIF','*.tif','*.TIFF','*.tiff','*.PNG','*.png']
57files=DIALOG_PICKFILE(TITLE='Select picture files to open',/MULTIPLE_FILES,$
58                      FILTER=filter,GET_PATH=path)
59;if user hit "Cancel" then return to previous program level:
60if (files[0] EQ '') then RETURN
61;change current working directory to location of selected files:
62CD,path
63nFiles=N_ELEMENTS(files)
64(*pState).nFiles=nFiles
65(*pState).increment=100./nFiles
66files=files[SORT(files)]
67;create status report dialog:
68xCenter=(*pState).screenSize[0]/2
69yCenter=(*pState).screenSize[1]/2
70tlb2=WIDGET_BASE(TITLE='Status Report',/COLUMN,/ALIGN_CENTER,TLB_FRAME_ATTR=19,/MODAL,$
71                 GROUP_LEADER=(*pState).tlb)
72  spacer=WIDGET_LABEL(tlb2,VALUE=' ')
73  label1=WIDGET_LABEL(tlb2,VALUE='LOADING SELECTED IMAGE FILES INTO MEMORY')
74  spacer=WIDGET_LABEL(tlb2,VALUE=' ')
75  label2=WIDGET_LABEL(tlb2,VALUE='*** PLEASE WAIT ***')
76  spacer=WIDGET_LABEL(tlb2,VALUE=' ')
77  statusBase=WIDGET_BASE(tlb2,/ROW,/FRAME,/BASE_ALIGN_CENTER,/ALIGN_CENTER,EVENT_PRO='image_viewer_timer')
78    cancelBut=WIDGET_BUTTON(statusBase,VALUE='Cancel',EVENT_PRO='image_viewer_cancel')
79    progressLabel=WIDGET_LABEL(statusBase,Value=' Progress :  0 ')
80    statusSlider=WIDGET_SLIDER(statusBase,SENSITIVE=0,TITLE=' ',XSIZE=200)
81    percentLabel=WIDGET_LABEL(statusBase,VALUE=' 100 %')
82geom=WIDGET_INFO(tlb2,/GEOMETRY)
83xHalfSize=geom.Scr_XSize/2
84yHalfSize=geom.Scr_YSize/2
85WIDGET_CONTROL,tlb2,XOFFSET=xCenter-xHalfSize,YOFFSET=yCenter-yHalfSize
86WIDGET_CONTROL,tlb2,/REALIZE
87(*pState).statusBase=statusBase
88(*pState).statusSlider=statusSlider
89WIDGET_CONTROL,tlb2,SET_UVALUE=pState
90;reset settings of GUI:
91WIDGET_CONTROL,(*pState).fileText,SET_VALUE=''
92WIDGET_CONTROL,(*pState).imageDraw,GET_VALUE=drawID
93WSET,drawID
94TVLCT,0,0,0,0
95ERASE
96;re-create thumbnails base with appropriate size for number of images selected:
97nRows = CEIL (nFiles / 3.0)
98WIDGET_CONTROL,(*pState).thumbBase,/DESTROY
99(*pState).thumbBase=WIDGET_BASE((*pState).controlsBase,/COLUMN,/ALIGN_TOP,/FRAME,XSIZE=260,$
100                                YSIZE=(nRows*89),/SCROLL,X_SCROLL_SIZE=260,Y_SCROLL_SIZE=650)
101;initialize pointer array to reference image data:
102numImages=N_ELEMENTS(*(*pState).images)
103if numImages NE 0 then PTR_FREE,*(*pState).images
104*(*pState).images=PTRARR(nFiles,/ALLOCATE_HEAP)
105*(*pState).files=files
106;loop through each file:
107(*pState).timer=1B
108WIDGET_CONTROL,statusBase,TIMER=0.01
109END
110;
111;+
112;
113; @param event {in}{required}
114;
115;-
116PRO image_viewer_open_folder,event
117;THIS PROCEDURE IS CALLED WHEN A USER SELECTS "File > Open All In Folder" FROM THE MAIN MENU
118;
119  compile_opt idl2, strictarrsubs
120;
121; error handling:
122!ERROR_STATE.CODE=0
123CATCH,error
124if error NE 0 then begin
125  HELP,/LAST_MESSAGE,OUTPUT=traceback
126  messageStr=['Error Caught :','',traceback]
127  dummy=DIALOG_MESSAGE(messageStr,/ERROR)
128  ;if status report dialog is still active, destroy it:
129  if SIZE(tlb,/TYPE) NE 0 then WIDGET_CONTROL,tlb,/DESTROY
130  RETURN
131endif
132;obtain state structure for top-level-base from its UVALUE:
133WIDGET_CONTROL,event.top,GET_UVALUE=pState
134;prompt user to select files with native file selection dialog:
135folder=DIALOG_PICKFILE(TITLE='Select folder that contains picture files',/DIRECTORY)
136;if user hit "Cancel" then return to previous program level:
137if folder EQ '' then RETURN
138;change current working directory to location of selected files:
139CD,folder
140if (*pState).gifFlag EQ 1 then filter=['*.JPG','*.JPEG','*.JPE','*.JFIF','*.GIF','*.BMP',$
141  '*.TIF','*.TIFF','*.PNG'] else $
142  filter=['*.JPG','*.JPEG','*.JPE','*.JFIF','*.BMP','*.TIF','*.TIFF','*.PNG']
143files=FILE_SEARCH(filter,COUNT=nFiles,/FOLD_CASE,/FULLY_QUALIFY_PATH,/NOSORT)
144if nFiles EQ 0 then begin
145  dummy=DIALOG_MESSAGE('No valid picture files were found in the selected folder !',/INFO)
146  RETURN
147endif
148(*pState).nFiles=nFiles
149(*pState).increment=100./nFiles
150files=files[SORT(files)]
151;create status report dialog:
152xCenter=(*pState).screenSize[0]/2
153yCenter=(*pState).screenSize[1]/2
154tlb2=WIDGET_BASE(TITLE='Status Report',/COLUMN,/ALIGN_CENTER,TLB_FRAME_ATTR=19,/MODAL,$
155                 GROUP_LEADER=(*pState).tlb)
156  spacer=WIDGET_LABEL(tlb2,VALUE=' ')
157  label1=WIDGET_LABEL(tlb2,VALUE='LOADING SELECTED IMAGE FILES INTO MEMORY')
158  spacer=WIDGET_LABEL(tlb2,VALUE=' ')
159  label2=WIDGET_LABEL(tlb2,VALUE='*** PLEASE WAIT ***')
160  spacer=WIDGET_LABEL(tlb2,VALUE=' ')
161  statusBase=WIDGET_BASE(tlb2,/ROW,/FRAME,/BASE_ALIGN_CENTER,/ALIGN_CENTER,EVENT_PRO='image_viewer_timer')
162    cancelBut=WIDGET_BUTTON(statusBase,VALUE='Cancel',EVENT_PRO='image_viewer_cancel')
163    progressLabel=WIDGET_LABEL(statusBase,Value=' Progress :  0 ')
164    statusSlider=WIDGET_SLIDER(statusBase,SENSITIVE=0,TITLE=' ',XSIZE=200)
165    percentLabel=WIDGET_LABEL(statusBase,VALUE=' 100 %')
166geom=WIDGET_INFO(tlb2,/GEOMETRY)
167xHalfSize=geom.Scr_XSize/2
168yHalfSize=geom.Scr_YSize/2
169WIDGET_CONTROL,tlb2,XOFFSET=xCenter-xHalfSize,YOFFSET=yCenter-yHalfSize
170WIDGET_CONTROL,tlb2,/REALIZE
171(*pState).statusBase=statusBase
172(*pState).statusSlider=statusSlider
173WIDGET_CONTROL,tlb2,SET_UVALUE=pState
174;reset settings of GUI:
175WIDGET_CONTROL,(*pState).fileText,SET_VALUE=''
176WIDGET_CONTROL,(*pState).imageDraw,GET_VALUE=drawID
177WSET,drawID
178TVLCT,0,0,0,0
179ERASE
180;re-create thumbnails base with appropriate size for number of images selected:
181nRows = CEIL (nFiles / 3.0)
182WIDGET_CONTROL,(*pState).thumbBase,/DESTROY
183(*pState).thumbBase=WIDGET_BASE((*pState).controlsBase,/COLUMN,/ALIGN_TOP,/FRAME,XSIZE=260,$
184                                YSIZE=(nRows*89),/SCROLL,X_SCROLL_SIZE=260,Y_SCROLL_SIZE=650)
185;initialize pointer array to reference image data:
186numImages=N_ELEMENTS(*(*pState).images)
187if numImages NE 0 then PTR_FREE,*(*pState).images
188*(*pState).images=PTRARR(nFiles,/ALLOCATE_HEAP)
189*(*pState).files=files
190;loop through each file:
191(*pState).timer=1B
192WIDGET_CONTROL,statusBase,TIMER=0.01
193END
194;
195;+
196;
197; @param event {in}{required}
198;
199;-
200PRO image_viewer_cancel,event
201;
202  compile_opt idl2, strictarrsubs
203;
204;obtain state structure for top-level-base from its UVALUE:
205WIDGET_CONTROL,event.top,GET_UVALUE=pState
206;shut-off timer:
207(*pState).timer=0B
208END
209;
210;+
211;
212; @param event {in}{required}
213;
214;-
215PRO image_viewer_timer,event
216;
217  compile_opt idl2, strictarrsubs
218;
219;obtain state structure for top-level-base from its UVALUE:
220WIDGET_CONTROL,event.top,GET_UVALUE=pState
221if (*pState).timer EQ 1 then begin ;continue processing files:
222  if (*pState).currFile LE (*pState).nFiles-1 then begin
223    i=(*pState).currFile
224    extension=STRUPCASE(STRMID((*(*pState).files)[i],STRPOS((*(*pState).files)[i],'.',/REVERSE_SEARCH)+1))
225    if extension EQ 'JPG' or extension EQ 'JPEG' or extension EQ 'JPE' or extension EQ 'JFIF' then begin
226      result=QUERY_JPEG((*(*pState).files)[i],info)
227      if result NE 1 then begin
228        dummy=DIALOG_MESSAGE(['Selected file:','',(*(*pState).files)[i],'',$
229                              'does not appear to be a valid JPEG file !'],/ERROR)
230        if (i MOD 3) EQ 0 then (*pState).rowBase=WIDGET_BASE((*pState).thumbBase,/ROW,/ALIGN_LEFT)
231        if (*pState).currFile EQ (*pState).nFiles-1 then begin
232          ;last file ... terminate timer:
233          (*pState).timer=0B
234          (*pState).currFile=0L
235          WIDGET_CONTROL,event.top,/DESTROY
236        endif else begin
237          ;increment file number and update progress slider:
238          (*pState).currFile=(*pState).currFile+1
239          progressValue = ROUND((i+1)*(*pState).increment) < 100
240          WIDGET_CONTROL,(*pState).statusSlider,SET_VALUE=progressValue
241          ;fire off timer again:
242          WIDGET_CONTROL,(*pState).statusBase,TIMER=0.01
243        endelse
244        RETURN
245      endif
246      if (i MOD 3) EQ 0 then (*pState).rowBase=WIDGET_BASE((*pState).thumbBase,/ROW,/ALIGN_LEFT)
247      TVLCT,0,0,0,0
248      thumbDraw=WIDGET_DRAW((*pState).rowBase,/BUTTON_EVENTS,RETAIN=2,XSIZE=80,YSIZE=80,$
249                            EVENT_PRO='image_viewer_thumbs',UVALUE=(i+1),UNAME=STRTRIM(i+1,2))
250      WAIT,0.01
251      WIDGET_CONTROL,thumbDraw,GET_VALUE=drawID
252      WSET,drawID
253      if info.channels EQ 3 then begin
254        READ_JPEG,(*(*pState).files)[i],image,TRUE=1
255        if (*pState).colorMode EQ 'PSEUDO' then begin
256          image=COLOR_QUAN(TEMPORARY(image),1,red,green,blue,COLORS=!D.TABLE_SIZE-1)
257          red=[[0],TEMPORARY(red)]
258          green=[[0],TEMPORARY(green)]
259          blue=[[0],TEMPORARY(blue)]
260          image=TEMPORARY(image)+1B
261          imageColorMode='PSEUDO'
262          TVLCT,red,green,blue
263        endif else begin
264          imageColorMode='TRUE'
265          red=0B
266          green=0B
267          blue=0B
268          DEVICE,DECOMPOSED=1
269        endelse
270      endif
271      if info.channels EQ 1 then begin
272        READ_JPEG,(*(*pState).files)[i],image
273        if (*pState).colorMode EQ 'PSEUDO' then image=BYTSCL(TEMPORARY(image),TOP=!D.TABLE_SIZE-1)
274        red=BINDGEN(!D.TABLE_SIZE)
275        green=BINDGEN(!D.TABLE_SIZE)
276        blue=BINDGEN(!D.TABLE_SIZE)
277        imageColorMode='PSEUDO'
278        if (*pState).colorMode EQ 'TRUE' then DEVICE,DECOMPOSED=0
279        TVLCT,red,green,blue
280      endif
281      ratio=FLOAT(info.dimensions[0])/info.dimensions[1]
282      ;resize image if necessary:
283      if info.dimensions[0] GT 710 or info.dimensions[1] GT 650 then begin
284        if ratio GE 1.09231 then begin
285          factor=(710./info.dimensions[0])
286          xSize=710
287          ySize=ROUND(info.dimensions[1]*factor)
288          if imageColorMode EQ 'PSEUDO' then image=CONGRID(image,710,ySize)
289          if imageColorMode EQ 'TRUE' then image=CONGRID(image,3,710,ySize)
290        endif else begin
291          factor=(650./info.dimensions[1])
292          xSize=ROUND(info.dimensions[0]*factor)
293          ySize=650
294          if imageColorMode EQ 'PSEUDO' then image=CONGRID(image,xSize,650)
295          if imageColorMode EQ 'TRUE' then image=CONGRID(image,3,xSize,650)
296        endelse
297      endif else begin
298        xSize=info.dimensions[0]
299        ySize=info.dimensions[1]
300      endelse
301      ;create thumbnail:
302      if xSize GT 80 or ySize GT 80 then begin
303        if ratio GE 1.09231 then begin
304          factor=(80./info.dimensions[0])
305          thumbxSize=80
306          thumbySize=ROUND(info.dimensions[1]*factor)
307          if imageColorMode EQ 'PSEUDO' then thumb=CONGRID(image,80,thumbySize)
308          if imageColorMode EQ 'TRUE' then thumb=CONGRID(image,3,80,thumbySize)
309        endif else begin
310          factor=(80./info.dimensions[1])
311          thumbxSize=ROUND(info.dimensions[0]*factor)
312          thumbySize=80
313          if imageColorMode EQ 'PSEUDO' then thumb=CONGRID(image,thumbxSize,80)
314          if imageColorMode EQ 'TRUE' then thumb=CONGRID(image,3,thumbxSize,80)
315        endelse
316        xOffset=ROUND((80-thumbxSize)/2.)
317        yOffset=ROUND((80-thumbySize)/2.)
318      endif else begin
319        bottom=FLOOR((80-ySize)/2.)
320        top=bottom+ySize-1
321        left=FLOOR((80-xSize)/2.)
322        right=left+xSize-1
323        if imageColorMode EQ 'PSEUDO' then begin
324          thumb=BYTARR(80,80)
325          thumb[left:right,bottom:top]=image
326        endif else begin ;imageColorMode EQ 'TRUE':
327          thumb=BYTARR(3,80,80)
328          thumb[*,left:right,bottom:top]=image
329        endelse
330        xOffset=0
331        yOffset=0
332      endelse
333      if imageColorMode EQ 'PSEUDO' then TV,TEMPORARY(thumb),xOffset,yOffset
334      if imageColorMode EQ 'TRUE' then TV,TEMPORARY(thumb),xOffset,yOffset,TRUE=1
335      imageStruct={image:TEMPORARY(image),xSize:xSize,ySize:ySize,imageColorMode:imageColorMode,$
336                   red:TEMPORARY(red),green:TEMPORARY(green),blue:TEMPORARY(blue)}
337      *(*(*pState).images)[i]=TEMPORARY(imageStruct)
338    endif
339    ;
340    if extension EQ 'GIF' and (*pState).gifFlag EQ 1 then begin
341      result=QUERY_GIF((*(*pState).files)[i],info)
342      if result NE 1 then begin
343        dummy=DIALOG_MESSAGE(['An error has occurred.  This is due to one of the following reasons :','',$
344                              '1) This installation of IDL is not licensed for GIF technology patented',$
345                              'by the Unisys Corporation.','',$
346                              '2) Selected file:','',(*(*pState).files)[i],'',$
347                              'is not a valid GIF file.'],/ERROR)
348        if (i MOD 3) EQ 0 then (*pState).rowBase=WIDGET_BASE((*pState).thumbBase,/ROW,/ALIGN_LEFT)
349        if (*pState).currFile EQ (*pState).nFiles-1 then begin
350          ;last file ... terminate timer:
351          (*pState).timer=0B
352          (*pState).currFile=0L
353          WIDGET_CONTROL,event.top,/DESTROY
354        endif else begin
355          ;increment file number and update progress slider:
356          (*pState).currFile=(*pState).currFile+1
357          progressValue = ROUND((i+1)*(*pState).increment) < 100
358          WIDGET_CONTROL,(*pState).statusSlider,SET_VALUE=progressValue
359          ;fire off timer again:
360          WIDGET_CONTROL,(*pState).statusBase,TIMER=0.01
361        endelse
362        RETURN
363      endif
364      if (i MOD 3) EQ 0 then (*pState).rowBase=WIDGET_BASE((*pState).thumbBase,/ROW,/ALIGN_LEFT)
365      TVLCT,0,0,0,0
366      thumbDraw=WIDGET_DRAW((*pState).rowBase,/BUTTON_EVENTS,RETAIN=2,XSIZE=80,YSIZE=80,$
367                            EVENT_PRO='image_viewer_thumbs',UVALUE=(i+1),UNAME=STRTRIM(i+1,2))
368      WAIT,0.01
369      WIDGET_CONTROL,thumbDraw,GET_VALUE=drawID
370      WSET,drawID
371      if info.has_palette EQ 1 then begin
372        READ_GIF,(*(*pState).files)[i],image,red,green,blue
373        trueColorImage=BYTARR(3,info.dimensions[0],info.dimensions[1])
374        trueColorImage[0,*,*]=red[image]
375        trueColorImage[1,*,*]=green[image]
376        trueColorImage[2,*,*]=blue[image]
377        image=COLOR_QUAN(TEMPORARY(trueColorImage),1,red,green,blue,COLORS=!D.TABLE_SIZE-1)
378        red=[[0],TEMPORARY(red)]
379        green=[[0],TEMPORARY(green)]
380        blue=[[0],TEMPORARY(blue)]
381        image=TEMPORARY(image)+1B
382      endif
383      if info.has_palette EQ 0 then begin
384        READ_GIF,(*(*pState).files)[i],image
385        if (*pState).colorMode EQ 'PSEUDO' then image=BYTSCL(TEMPORARY(image),TOP=!D.TABLE_SIZE-1)
386        red=BINDGEN(!D.TABLE_SIZE)
387        green=BINDGEN(!D.TABLE_SIZE)
388        blue=BINDGEN(!D.TABLE_SIZE)
389      endif
390      if (*pState).colorMode EQ 'TRUE' then DEVICE,DECOMPOSED=0
391      TVLCT,red,green,blue
392      imageColorMode='PSEUDO'
393      ratio=FLOAT(info.dimensions[0])/info.dimensions[1]
394      ;resize image if necessary:
395      if info.dimensions[0] GT 710 or info.dimensions[1] GT 650 then begin
396        if ratio GE 1.09231 then begin
397          factor=(710./info.dimensions[0])
398          xSize=710
399          ySize=ROUND(info.dimensions[1]*factor)
400          image=CONGRID(image,710,ySize)
401        endif else begin
402          factor=(650./info.dimensions[1])
403          xSize=ROUND(info.dimensions[0]*factor)
404          ySize=650
405          image=CONGRID(image,xSize,650)
406        endelse
407      endif else begin
408        xSize=info.dimensions[0]
409        ySize=info.dimensions[1]
410      endelse
411      ;create thumbnail:
412      if xSize GT 80 or ySize GT 80 then begin
413        if ratio GE 1.09231 then begin
414          factor=(80./info.dimensions[0])
415          thumbxSize=80
416          thumbySize=ROUND(info.dimensions[1]*factor)
417          thumb=CONGRID(image,80,thumbySize)
418        endif else begin
419          factor=(80./info.dimensions[1])
420          thumbxSize=ROUND(info.dimensions[0]*factor)
421          thumbySize=80
422          thumb=CONGRID(image,thumbxSize,80)
423        endelse
424        xOffset=ROUND((80-thumbxSize)/2.)
425        yOffset=ROUND((80-thumbySize)/2.)
426      endif else begin
427        bottom=FLOOR((80-ySize)/2.)
428        top=bottom+ySize-1
429        left=FLOOR((80-xSize)/2.)
430        right=left+xSize-1
431        thumb=BYTARR(80,80)
432        thumb[left:right,bottom:top]=image
433        xOffset=0
434        yOffset=0
435      endelse
436      TV,TEMPORARY(thumb),xOffset,yOffset
437      imageStruct={image:TEMPORARY(image),xSize:xSize,ySize:ySize,imageColorMode:imageColorMode,$
438                   red:TEMPORARY(red),green:TEMPORARY(green),blue:TEMPORARY(blue)}
439      *(*(*pState).images)[i]=TEMPORARY(imageStruct)
440    endif
441    ;
442    if extension EQ 'BMP' then begin
443      result=QUERY_BMP((*(*pState).files)[i],info)
444      if result NE 1 then begin
445        dummy=DIALOG_MESSAGE(['An error has occurred.  This is due to one of the following reasons :','',$
446                              '1) The selected BMP file is an "OS2" format file, which is not supported',$
447                              'by IMAGE_VIEWER.','',$
448                              '2) Selected file:','',(*(*pState).files)[i],'',$
449                              'is not a valid BMP file.'],/ERROR)
450        if (i MOD 3) EQ 0 then (*pState).rowBase=WIDGET_BASE((*pState).thumbBase,/ROW,/ALIGN_LEFT)
451        if (*pState).currFile EQ (*pState).nFiles-1 then begin
452          ;last file ... terminate timer:
453          (*pState).timer=0B
454          (*pState).currFile=0L
455          WIDGET_CONTROL,event.top,/DESTROY
456        endif else begin
457          ;increment file number and update progress slider:
458          (*pState).currFile=(*pState).currFile+1
459          progressValue = ROUND((i+1)*(*pState).increment) < 100
460          WIDGET_CONTROL,(*pState).statusSlider,SET_VALUE=progressValue
461          ;fire off timer again:
462          WIDGET_CONTROL,(*pState).statusBase,TIMER=0.01
463        endelse
464        RETURN
465      endif
466      if (i MOD 3) EQ 0 then (*pState).rowBase=WIDGET_BASE((*pState).thumbBase,/ROW,/ALIGN_LEFT)
467      TVLCT,0,0,0,0
468      thumbDraw=WIDGET_DRAW((*pState).rowBase,/BUTTON_EVENTS,RETAIN=2,XSIZE=80,YSIZE=80,$
469                            EVENT_PRO='image_viewer_thumbs',UVALUE=(i+1),UNAME=STRTRIM(i+1,2))
470      WAIT,0.01
471      WIDGET_CONTROL,thumbDraw,GET_VALUE=drawID
472      WSET,drawID
473      if info.channels EQ 3 then begin
474        image=READ_BMP((*(*pState).files)[i],/RGB)
475        if (*pState).colorMode EQ 'PSEUDO' then begin
476          image=COLOR_QUAN(image,1,red,green,blue,COLORS=!D.TABLE_SIZE-1)
477          red=[[0],TEMPORARY(red)]
478          green=[[0],TEMPORARY(green)]
479          blue=[[0],TEMPORARY(blue)]
480          image=TEMPORARY(image)+1B
481          imageColorMode='PSEUDO'
482          TVLCT,red,green,blue
483        endif else begin
484          imageColorMode='TRUE'
485          red=0B
486          green=0B
487          blue=0B
488          DEVICE,DECOMPOSED=1
489        endelse
490      endif
491      if info.channels EQ 1 then begin
492        image=READ_BMP((*(*pState).files)[i],red,green,blue)
493        if info.has_palette EQ 0 then begin
494          if (*pState).colorMode EQ 'PSEUDO' then image=BYTSCL(TEMPORARY(image),TOP=!D.TABLE_SIZE-1)
495          red=BINDGEN(!D.TABLE_SIZE)
496          green=BINDGEN(!D.TABLE_SIZE)
497          blue=BINDGEN(!D.TABLE_SIZE)
498        endif else begin
499          trueColorImage=BYTARR(3,info.dimensions[0],info.dimensions[1])
500          trueColorImage[0,*,*]=red[image]
501          trueColorImage[1,*,*]=green[image]
502          trueColorImage[2,*,*]=blue[image]
503          image=COLOR_QUAN(TEMPORARY(trueColorImage),1,red,green,blue,COLORS=!D.TABLE_SIZE-1)
504          red=[[0],TEMPORARY(red)]
505          green=[[0],TEMPORARY(green)]
506          blue=[[0],TEMPORARY(blue)]
507          image=TEMPORARY(image)+1B
508        endelse
509        imageColorMode='PSEUDO'
510        if (*pState).colorMode EQ 'TRUE' then DEVICE,DECOMPOSED=0
511        TVLCT,red,green,blue
512      endif
513      ratio=FLOAT(info.dimensions[0])/info.dimensions[1]
514      ;resize image if necessary:
515      if info.dimensions[0] GT 710 or info.dimensions[1] GT 650 then begin
516        if ratio GE 1.09231 then begin
517          factor=(710./info.dimensions[0])
518          xSize=710
519          ySize=ROUND(info.dimensions[1]*factor)
520          if imageColorMode EQ 'PSEUDO' then image=CONGRID(image,710,ySize)
521          if imageColorMode EQ 'TRUE' then image=CONGRID(image,3,710,ySize)
522        endif else begin
523          factor=(650./info.dimensions[1])
524          xSize=ROUND(info.dimensions[0]*factor)
525          ySize=650
526          if imageColorMode EQ 'PSEUDO' then image=CONGRID(image,xSize,650)
527          if imageColorMode EQ 'TRUE' then image=CONGRID(image,3,xSize,650)
528        endelse
529      endif else begin
530        xSize=info.dimensions[0]
531        ySize=info.dimensions[1]
532      endelse
533      ;create thumbnail:
534      if xSize GT 80 or ySize GT 80 then begin
535        if ratio GE 1.09231 then begin
536          factor=(80./info.dimensions[0])
537          thumbxSize=80
538          thumbySize=ROUND(info.dimensions[1]*factor)
539          if imageColorMode EQ 'PSEUDO' then thumb=CONGRID(image,80,thumbySize)
540          if imageColorMode EQ 'TRUE' then thumb=CONGRID(image,3,80,thumbySize)
541        endif else begin
542          factor=(80./info.dimensions[1])
543          thumbxSize=ROUND(info.dimensions[0]*factor)
544          thumbySize=80
545          if imageColorMode EQ 'PSEUDO' then thumb=CONGRID(image,thumbxSize,80)
546          if imageColorMode EQ 'TRUE' then thumb=CONGRID(image,3,thumbxSize,80)
547        endelse
548        xOffset=ROUND((80-thumbxSize)/2.)
549        yOffset=ROUND((80-thumbySize)/2.)
550      endif else begin
551        bottom=FLOOR((80-ySize)/2.)
552        top=bottom+ySize-1
553        left=FLOOR((80-xSize)/2.)
554        right=left+xSize-1
555        if imageColorMode EQ 'PSEUDO' then begin
556          thumb=BYTARR(80,80)
557          thumb[left:right,bottom:top]=image
558        endif else begin ;imageColorMode EQ 'TRUE':
559          thumb=BYTARR(3,80,80)
560          thumb[*,left:right,bottom:top]=image
561        endelse
562        xOffset=0
563        yOffset=0
564      endelse
565      if imageColorMode EQ 'PSEUDO' then TV,TEMPORARY(thumb),xOffset,yOffset
566      if imageColorMode EQ 'TRUE' then TV,TEMPORARY(thumb),xOffset,yOffset,TRUE=1
567      imageStruct={image:TEMPORARY(image),xSize:xSize,ySize:ySize,imageColorMode:imageColorMode,$
568                   red:TEMPORARY(red),green:TEMPORARY(green),blue:TEMPORARY(blue)}
569      *(*(*pState).images)[i]=TEMPORARY(imageStruct)
570    endif
571    ;
572    if extension EQ 'TIF' or extension EQ 'TIFF' then begin
573      result=QUERY_TIFF((*(*pState).files)[i],info)
574      if result NE 1 then begin
575        dummy=DIALOG_MESSAGE(['An error has occurred.  This is due to one of the following reasons :','',$
576              '1) The selected TIFF file has LZW (Lempel-Zif-Welch) compression and this installation',$
577              'of IDL is not licensed for TIFF LZW technology patented by the Unisys Corporation.','',$
578              '2) Selected file:','',(*(*pState).files)[i],'',$
579              'is not a valid TIFF file.'],/ERROR)
580        if (i MOD 3) EQ 0 then (*pState).rowBase=WIDGET_BASE((*pState).thumbBase,/ROW,/ALIGN_LEFT)
581        if (*pState).currFile EQ (*pState).nFiles-1 then begin
582          ;last file ... terminate timer:
583          (*pState).timer=0B
584          (*pState).currFile=0L
585          WIDGET_CONTROL,event.top,/DESTROY
586        endif else begin
587          ;increment file number and update progress slider:
588          (*pState).currFile=(*pState).currFile+1
589          progressValue = ROUND((i+1)*(*pState).increment) < 100
590          WIDGET_CONTROL,(*pState).statusSlider,SET_VALUE=progressValue
591          ;fire off timer again:
592          WIDGET_CONTROL,(*pState).statusBase,TIMER=0.01
593        endelse
594        RETURN
595      endif
596      if info.orientation NE 0 and info.orientation NE 1 and info.orientation NE 4 then begin
597        dummy=DIALOG_MESSAGE('IMAGE_VIEWER only works with standard orientation TIFF files !',/ERROR)
598        if (i MOD 3) EQ 0 then (*pState).rowBase=WIDGET_BASE((*pState).thumbBase,/ROW,/ALIGN_LEFT)
599        if (*pState).currFile EQ (*pState).nFiles-1 then begin
600          ;last file ... terminate timer:
601          (*pState).timer=0B
602          (*pState).currFile=0L
603          WIDGET_CONTROL,event.top,/DESTROY
604        endif else begin
605          ;increment file number and update progress slider:
606          (*pState).currFile=(*pState).currFile+1
607          progressValue = ROUND((i+1)*(*pState).increment) < 100
608          WIDGET_CONTROL,(*pState).statusSlider,SET_VALUE=progressValue
609          ;fire off timer again:
610          WIDGET_CONTROL,(*pState).statusBase,TIMER=0.01
611        endelse
612        RETURN
613      endif
614      if (i MOD 3) EQ 0 then (*pState).rowBase=WIDGET_BASE((*pState).thumbBase,/ROW,/ALIGN_LEFT)
615      TVLCT,0,0,0,0
616      thumbDraw=WIDGET_DRAW((*pState).rowBase,/BUTTON_EVENTS,RETAIN=2,XSIZE=80,YSIZE=80,$
617                            EVENT_PRO='image_viewer_thumbs',UVALUE=(i+1),UNAME=STRTRIM(i+1,2))
618      WAIT,0.01
619      WIDGET_CONTROL,thumbDraw,GET_VALUE=drawID
620      WSET,drawID
621      if info.channels EQ 3 then begin
622        image=READ_TIFF((*(*pState).files)[i],INTERLEAVE=0,ORDER=order,IMAGE_INDEX=0)
623        if info.pixel_type NE 1 then image=BYTSCL(TEMPORARY(image))
624        if order EQ 1 then begin
625          ;flip image:
626          rImage=REFORM(image[0,*,*])
627          rImage=ROTATE(rImage,7)
628          gImage=REFORM(image[1,*,*])
629          gImage=ROTATE(gImage,7)
630          bImage=REFORM(image[2,*,*])
631          bImage=ROTATE(bImage,7)
632          image=BYTARR(3,info.dimensions[0],info.dimensions[1])
633          image[0,*,*]=TEMPORARY(rImage)
634          image[1,*,*]=TEMPORARY(gImage)
635          image[2,*,*]=TEMPORARY(bImage)
636        endif
637        if (*pState).colorMode EQ 'PSEUDO' then begin
638          image=COLOR_QUAN(image,1,red,green,blue,COLORS=!D.TABLE_SIZE-1)
639          red=[[0],TEMPORARY(red)]
640          green=[[0],TEMPORARY(green)]
641          blue=[[0],TEMPORARY(blue)]
642          image=TEMPORARY(image)+1B
643          imageColorMode='PSEUDO'
644          TVLCT,red,green,blue
645        endif else begin
646          imageColorMode='TRUE'
647          red=0B
648          green=0B
649          blue=0B
650          DEVICE,DECOMPOSED=1
651        endelse
652      endif
653      if info.channels EQ 1 then begin
654        image=READ_TIFF((*(*pState).files)[i],red,green,blue,ORDER=order,IMAGE_INDEX=0)
655        if info.pixel_type NE 1 then image=BYTSCL(TEMPORARY(image))
656        if order EQ 1 then begin
657          ;flip image:
658          image=ROTATE(TEMPORARY(image),7)
659        endif
660        if info.has_palette EQ 0 then begin
661          if (*pState).colorMode EQ 'PSEUDO' then image=BYTSCL(TEMPORARY(image),TOP=!D.TABLE_SIZE-1)
662          red=BINDGEN(!D.TABLE_SIZE)
663          green=BINDGEN(!D.TABLE_SIZE)
664          blue=BINDGEN(!D.TABLE_SIZE)
665        endif else begin
666          trueColorImage=BYTARR(3,info.dimensions[0],info.dimensions[1])
667          trueColorImage[0,*,*]=red[image]
668          trueColorImage[1,*,*]=green[image]
669          trueColorImage[2,*,*]=blue[image]
670          image=COLOR_QUAN(TEMPORARY(trueColorImage),1,red,green,blue,COLORS=!D.TABLE_SIZE-1)
671          red=[[0],TEMPORARY(red)]
672          green=[[0],TEMPORARY(green)]
673          blue=[[0],TEMPORARY(blue)]
674          image=TEMPORARY(image)+1B
675        endelse
676        imageColorMode='PSEUDO'
677        if (*pState).colorMode EQ 'TRUE' then DEVICE,DECOMPOSED=0
678        TVLCT,red,green,blue
679      endif
680      ratio=FLOAT(info.dimensions[0])/info.dimensions[1]
681      ;resize image if necessary:
682      if info.dimensions[0] GT 710 or info.dimensions[1] GT 650 then begin
683        if ratio GE 1.09231 then begin
684          factor=(710./info.dimensions[0])
685          xSize=710
686          ySize=ROUND(info.dimensions[1]*factor)
687          if imageColorMode EQ 'PSEUDO' then image=CONGRID(image,710,ySize)
688          if imageColorMode EQ 'TRUE' then image=CONGRID(image,3,710,ySize)
689        endif else begin
690          factor=(650./info.dimensions[1])
691          xSize=ROUND(info.dimensions[0]*factor)
692          ySize=650
693          if imageColorMode EQ 'PSEUDO' then image=CONGRID(image,xSize,650)
694          if imageColorMode EQ 'TRUE' then image=CONGRID(image,3,xSize,650)
695        endelse
696      endif else begin
697        xSize=info.dimensions[0]
698        ySize=info.dimensions[1]
699      endelse
700      ;create thumbnail:
701      if xSize GT 80 or ySize GT 80 then begin
702        if ratio GE 1.09231 then begin
703          factor=(80./info.dimensions[0])
704          thumbxSize=80
705          thumbySize=ROUND(info.dimensions[1]*factor)
706          if imageColorMode EQ 'PSEUDO' then thumb=CONGRID(image,80,thumbySize)
707          if imageColorMode EQ 'TRUE' then thumb=CONGRID(image,3,80,thumbySize)
708        endif else begin
709          factor=(80./info.dimensions[1])
710          thumbxSize=ROUND(info.dimensions[0]*factor)
711          thumbySize=80
712          if imageColorMode EQ 'PSEUDO' then thumb=CONGRID(image,thumbxSize,80)
713          if imageColorMode EQ 'TRUE' then thumb=CONGRID(image,3,thumbxSize,80)
714        endelse
715        xOffset=ROUND((80-thumbxSize)/2.)
716        yOffset=ROUND((80-thumbySize)/2.)
717      endif else begin
718        bottom=FLOOR((80-ySize)/2.)
719        top=bottom+ySize-1
720        left=FLOOR((80-xSize)/2.)
721        right=left+xSize-1
722        if imageColorMode EQ 'PSEUDO' then begin
723          thumb=BYTARR(80,80)
724          thumb[left:right,bottom:top]=image
725        endif else begin ;imageColorMode EQ 'TRUE':
726          thumb=BYTARR(3,80,80)
727          thumb[*,left:right,bottom:top]=image
728        endelse
729        xOffset=0
730        yOffset=0
731      endelse
732      if imageColorMode EQ 'PSEUDO' then TV,TEMPORARY(thumb),xOffset,yOffset
733      if imageColorMode EQ 'TRUE' then TV,TEMPORARY(thumb),xOffset,yOffset,TRUE=1
734      imageStruct={image:TEMPORARY(image),xSize:xSize,ySize:ySize,imageColorMode:imageColorMode,$
735                   red:TEMPORARY(red),green:TEMPORARY(green),blue:TEMPORARY(blue)}
736      *(*(*pState).images)[i]=TEMPORARY(imageStruct)
737    endif
738    ;
739    if extension EQ 'PNG' then begin
740      result=QUERY_PNG((*(*pState).files)[i],info)
741      if result NE 1 then begin
742        dummy=DIALOG_MESSAGE(['Selected file:','',(*(*pState).files)[i],'',$
743                              'does not appear to be a valid PNG file !'],/ERROR)
744        if (i MOD 3) EQ 0 then (*pState).rowBase=WIDGET_BASE((*pState).thumbBase,/ROW,/ALIGN_LEFT)
745        if (*pState).currFile EQ (*pState).nFiles-1 then begin
746          ;last file ... terminate timer:
747          (*pState).timer=0B
748          (*pState).currFile=0L
749          WIDGET_CONTROL,event.top,/DESTROY
750        endif else begin
751          ;increment file number and update progress slider:
752          (*pState).currFile=(*pState).currFile+1
753          progressValue = ROUND((i+1)*(*pState).increment) < 100
754          WIDGET_CONTROL,(*pState).statusSlider,SET_VALUE=progressValue
755          ;fire off timer again:
756          WIDGET_CONTROL,(*pState).statusBase,TIMER=0.01
757        endelse
758        RETURN
759      endif
760      if (i MOD 3) EQ 0 then (*pState).rowBase=WIDGET_BASE((*pState).thumbBase,/ROW,/ALIGN_LEFT)
761      TVLCT,0,0,0,0
762      thumbDraw=WIDGET_DRAW((*pState).rowBase,/BUTTON_EVENTS,RETAIN=2,XSIZE=80,YSIZE=80,$
763                            EVENT_PRO='image_viewer_thumbs',UVALUE=(i+1),UNAME=STRTRIM(i+1,2))
764      WAIT,0.01
765      WIDGET_CONTROL,thumbDraw,GET_VALUE=drawID
766      WSET,drawID
767      if info.channels EQ 3 then begin
768        image=READ_PNG((*(*pState).files)[i])
769        if info.pixel_type NE 1 then image=BYTSCL(TEMPORARY(image))
770        if (*pState).colorMode EQ 'PSEUDO' then begin
771          image=COLOR_QUAN(image,1,red,green,blue,COLORS=!D.TABLE_SIZE-1)
772          red=[[0],TEMPORARY(red)]
773          green=[[0],TEMPORARY(green)]
774          blue=[[0],TEMPORARY(blue)]
775          image=TEMPORARY(image)+1B
776          imageColorMode='PSEUDO'
777          TVLCT,red,green,blue
778        endif else begin
779          imageColorMode='TRUE'
780          red=0B
781          green=0B
782          blue=0B
783          DEVICE,DECOMPOSED=1
784        endelse
785      endif
786      if info.channels EQ 1 then begin
787        image=READ_PNG((*(*pState).files)[i],red,green,blue)
788        if info.pixel_type NE 1 then image=BYTSCL(TEMPORARY(image))
789        if info.has_palette EQ 0 then begin
790          if (*pState).colorMode EQ 'PSEUDO' then image=BYTSCL(TEMPORARY(image),TOP=!D.TABLE_SIZE-1)
791          red=BINDGEN(!D.TABLE_SIZE)
792          green=BINDGEN(!D.TABLE_SIZE)
793          blue=BINDGEN(!D.TABLE_SIZE)
794        endif else begin
795          trueColorImage=BYTARR(3,info.dimensions[0],info.dimensions[1])
796          trueColorImage[0,*,*]=red[image]
797          trueColorImage[1,*,*]=green[image]
798          trueColorImage[2,*,*]=blue[image]
799          image=COLOR_QUAN(TEMPORARY(trueColorImage),1,red,green,blue,COLORS=!D.TABLE_SIZE-1)
800          red=[[0],TEMPORARY(red)]
801          green=[[0],TEMPORARY(green)]
802          blue=[[0],TEMPORARY(blue)]
803          image=TEMPORARY(image)+1B
804        endelse
805        imageColorMode='PSEUDO'
806        if (*pState).colorMode EQ 'TRUE' then DEVICE,DECOMPOSED=0
807        TVLCT,red,green,blue
808      endif
809      ratio=FLOAT(info.dimensions[0])/info.dimensions[1]
810      ;resize image if necessary:
811      if info.dimensions[0] GT 710 or info.dimensions[1] GT 650 then begin
812        if ratio GE 1.09231 then begin
813          factor=(710./info.dimensions[0])
814          xSize=710
815          ySize=ROUND(info.dimensions[1]*factor)
816          if imageColorMode EQ 'PSEUDO' then image=CONGRID(image,710,ySize)
817          if imageColorMode EQ 'TRUE' then image=CONGRID(image,3,710,ySize)
818        endif else begin
819          factor=(650./info.dimensions[1])
820          xSize=ROUND(info.dimensions[0]*factor)
821          ySize=650
822          if imageColorMode EQ 'PSEUDO' then image=CONGRID(image,xSize,650)
823          if imageColorMode EQ 'TRUE' then image=CONGRID(image,3,xSize,650)
824        endelse
825      endif else begin
826        xSize=info.dimensions[0]
827        ySize=info.dimensions[1]
828      endelse
829      ;create thumbnail:
830      if xSize GT 80 or ySize GT 80 then begin
831        if ratio GE 1.09231 then begin
832          factor=(80./info.dimensions[0])
833          thumbxSize=80
834          thumbySize=ROUND(info.dimensions[1]*factor)
835          if imageColorMode EQ 'PSEUDO' then thumb=CONGRID(image,80,thumbySize)
836          if imageColorMode EQ 'TRUE' then thumb=CONGRID(image,3,80,thumbySize)
837        endif else begin
838          factor=(80./info.dimensions[1])
839          thumbxSize=ROUND(info.dimensions[0]*factor)
840          thumbySize=80
841          if imageColorMode EQ 'PSEUDO' then thumb=CONGRID(image,thumbxSize,80)
842          if imageColorMode EQ 'TRUE' then thumb=CONGRID(image,3,thumbxSize,80)
843        endelse
844        xOffset=ROUND((80-thumbxSize)/2.)
845        yOffset=ROUND((80-thumbySize)/2.)
846      endif else begin
847        bottom=FLOOR((80-ySize)/2.)
848        top=bottom+ySize-1
849        left=FLOOR((80-xSize)/2.)
850        right=left+xSize-1
851        if imageColorMode EQ 'PSEUDO' then begin
852          thumb=BYTARR(80,80)
853          thumb[left:right,bottom:top]=image
854        endif else begin ;imageColorMode EQ 'TRUE':
855          thumb=BYTARR(3,80,80)
856          thumb[*,left:right,bottom:top]=image
857        endelse
858        xOffset=0
859        yOffset=0
860      endelse
861      if imageColorMode EQ 'PSEUDO' then TV,TEMPORARY(thumb),xOffset,yOffset
862      if imageColorMode EQ 'TRUE' then TV,TEMPORARY(thumb),xOffset,yOffset,TRUE=1
863      imageStruct={image:TEMPORARY(image),xSize:xSize,ySize:ySize,imageColorMode:imageColorMode,$
864                   red:TEMPORARY(red),green:TEMPORARY(green),blue:TEMPORARY(blue)}
865      *(*(*pState).images)[i]=TEMPORARY(imageStruct)
866    endif
867    ;increment file number and update progress slider:
868    (*pState).currFile=(*pState).currFile+1
869    progressValue = ROUND((i+1)*(*pState).increment) < 100
870    WIDGET_CONTROL,(*pState).statusSlider,SET_VALUE=progressValue
871    ;fire off timer again:
872    WIDGET_CONTROL,(*pState).statusBase,TIMER=0.01
873  endif else begin ;all files have already been read-in:
874    (*pState).timer=0B
875    (*pState).currFile=0L
876    WIDGET_CONTROL,event.top,/DESTROY
877  endelse
878endif else begin ;user hit "Cancel":
879  (*pState).currFile=0L
880  WIDGET_CONTROL,event.top,/DESTROY
881endelse
882END
883;
884;+
885;
886; @param event {in}{required}
887;
888;-
889PRO image_viewer_exit,event
890;
891  compile_opt idl2, strictarrsubs
892;
893;THIS PROCEDURE IS CALLED WHEN A USER SELECTS "File > Exit" FROM THE MAIN MENU
894;terminate the program by destroying the top-level-base (widgetID always stored in event.top):
895WIDGET_CONTROL,event.top,/DESTROY
896END
897;
898;+
899;
900; @param event {in}{required}
901;
902;-
903PRO image_viewer_help,event
904;THIS PROCEDURE IS CALLED WHEN A USER SELECTS "Help > Help on IMAGE_VIEWER"
905;FROM THE MAIN MENU
906;
907  compile_opt idl2, strictarrsubs
908;
909;display a simple message:
910messageStr=['IMAGE_VIEWER written by AEB, 2002.','',$
911            'The purpose of this program is to provide an interactive tool that can be used',$
912            'to view JPEG, BMP, GIF, PNG, and TIFF picture files.  In order to provide rapid',$
913            'viewing capabilities the images are loaded into memory, which can cause the',$
914            'initial file access to take a bit of time while the pictures are opened and',$
915            'thumbnails are created.']
916dummy=DIALOG_MESSAGE(messageStr,/info)
917END
918;
919;+
920;
921; @param event {in}{required}
922;
923;-
924PRO image_viewer_thumbs,event
925;THIS PROCEDURE IS CALLED WHEN A USER CLICKS ON ONE OF THE THUMBNAIL PICTURES
926;
927  compile_opt idl2, strictarrsubs
928;
929;error handling:
930!ERROR_STATE.CODE=0
931CATCH,error
932if error NE 0 then begin
933  HELP,/LAST_MESSAGE,OUTPUT=traceback
934  messageStr=['Error Caught :','',traceback]
935  dummy=DIALOG_MESSAGE(messageStr,/ERROR)
936  RETURN
937endif
938if event.press EQ 1 then begin
939  WIDGET_CONTROL,/HOURGLASS
940  ;obtain state structure for top-level-base from its UVALUE:
941  WIDGET_CONTROL,event.top,GET_UVALUE=pState
942  WIDGET_CONTROL,(*pState).imageDraw,GET_VALUE=drawID
943  WSET,drawID
944  TVLCT,0,0,0,0
945  ERASE
946  ;obtain current image data:
947  WIDGET_CONTROL,event.id,GET_UVALUE=fileID
948  imageStruct=*(*(*pState).images)[fileID-1]
949  xOffset=ROUND((710-imageStruct.xSize)/2.)
950  yOffset=ROUND((650-imageStruct.ySize)/2.)
951  if (*pState).colorMode EQ 'PSEUDO' then begin
952    TVLCT,imageStruct.red,imageStruct.green,imageStruct.blue
953    TV,TEMPORARY(imageStruct.image),xOffset,yOffset
954  endif else begin ;(*pState).colorMode EQ 'TRUE':
955    if imageStruct.imageColorMode EQ 'PSEUDO' then begin
956      DEVICE,DECOMPOSED=0
957      TVLCT,imageStruct.red,imageStruct.green,imageStruct.blue
958      TV,TEMPORARY(imageStruct.image),xOffset,yOffset
959    endif else begin ;imageStruct.imageColorMode EQ 'TRUE':
960      DEVICE,DECOMPOSED=1
961      TV,TEMPORARY(imageStruct.image),xOffset,yOffset,TRUE=1
962    endelse
963  endelse
964  WIDGET_CONTROL,(*pState).fileText,SET_VALUE=(*(*pState).files)[fileID-1]
965endif
966END
967;
968;+
969;
970; @param widgetID {in}{required}
971;
972;-
973PRO image_viewer_cleanup,widgetID
974;THIS PROCEDURE IS CALLED WHEN THE PROGRAM IS TERMINATED AND XMANAGER REGISTERS A CLEANUP:
975;
976  compile_opt idl2, strictarrsubs
977;
978;obtain state structure for top-level-base from its uvalue:
979WIDGET_CONTROL,widgetID,GET_UVALUE=pState
980;test for validity of state structure pointer:
981if PTR_VALID(pState) then begin
982  ;reset original settings:
983  !QUIET=(*pState).quietInit
984  !ORDER=(*pState).orderInit
985  !P.BACKGROUND=(*pState).backInit
986  CD,(*pState).currentDir
987  DEVICE,DECOMPOSED=(*pState).dc
988  TVLCT,(*pState).r,(*pState).g,(*pState).b
989  ;cleanup heap memory:
990  PTR_FREE,TEMPORARY((*pState).files)
991  numImages=N_ELEMENTS(*(*pState).images)
992  if numImages NE 0 then PTR_FREE,*(*pState).images
993  PTR_FREE,TEMPORARY((*pState).images)
994  PTR_FREE,TEMPORARY(pState)
995endif
996END
997;
998;+
999;
1000; @param event {in}{required}
1001;
1002;-
1003PRO image_viewer_event,event
1004;THIS PROCEDURE IS CALLED WHEN A USER RESIZES THE TOP-LEVEL BASE
1005;
1006  compile_opt idl2, strictarrsubs
1007;
1008;error handling:
1009!ERROR_STATE.CODE=0
1010CATCH,error
1011if error NE 0 then begin
1012  HELP,/LAST_MESSAGE,OUTPUT=traceback
1013  messageStr=['Error Caught :','',traceback]
1014  dummy=DIALOG_MESSAGE(messageStr,/ERROR)
1015  RETURN
1016endif
1017;obtain state structure for top-level-base from its UVALUE:
1018WIDGET_CONTROL,event.top,GET_UVALUE=pState
1019;reset widget size:
1020WIDGET_CONTROL,event.top,XSIZE=(*pState).tlbWidth,YSIZE=(*pState).tlbHeight,XOFFSET=0,YOFFSET=0
1021END
1022;
1023;+
1024;
1025;-
1026PRO image_viewer
1027;
1028  compile_opt idl2, strictarrsubs
1029;
1030;error handling:
1031!ERROR_STATE.CODE=0
1032CATCH,error
1033if error NE 0 then begin
1034  HELP,/LAST_MESSAGE,OUTPUT=traceback
1035  messageStr=['Error Caught :','',traceback]
1036  dummy=DIALOG_MESSAGE(messageStr,/ERROR)
1037  !QUIET=quietInit
1038  !ORDER=orderInit
1039  !P.BACKGROUND=backInit
1040  CD,currentDir
1041  RETURN
1042endif
1043;ignore beta and development build versions of IDL because string to float conversion will fail:
1044betaTest=STRPOS(STRLOWCASE(!VERSION.RELEASE),'beta')
1045buildTest=STRPOS(STRLOWCASE(!VERSION.RELEASE),'build')
1046;check to make sure the version of IDL running is 5.5 or newer:
1047if betaTest EQ -1 and buildTest EQ -1 then begin
1048  if FLOAT(!VERSION.RELEASE) LT 5.5 then begin
1049    dummy=dialog_message('IMAGE_VIEWER is only supported in IDL version 5.5 or newer.',/ERROR)
1050    RETURN
1051  endif
1052endif
1053;check to make sure there is adequate real estate:
1054DEVICE,GET_SCREEN_SIZE=screenSize
1055if (LONG(screenSize[0])*screenSize[1]) LT 786432 then begin
1056  messageStr=['IMAGE_VIEWER requires the computer monitor (Display) to be',$
1057              'configured in (1024 x 768) mode or better.']
1058  dummy=DIALOG_MESSAGE(messageStr)
1059  RETURN
1060endif
1061;check in auxiliary license:
1062result=LMGR("idl_tifflzw",VERSION='1.0')
1063result=LMGR("idl_gif",VERSION='1.0')
1064gifFlag=1B
1065if result NE 1 then begin
1066  messageStr=['The ability to read GIF (and TIFF LZW compressed) images requires',$
1067              'an auxiliary license in order to conform with the patent rights of the',$
1068              'Unisys Corporation.  IMAGE_VIEWER was unable to find the required',$
1069              'license in this installation.  Consequently, the ability to read GIF files',$
1070              'will be disabled.']
1071  dummy=DIALOG_MESSAGE(messageStr)
1072  gifFlag=0B
1073endif
1074;warn users of color flashing if monitor in PseudoColor mode:
1075if !D.N_COLORS LE 256 then begin
1076  messageStr=['The computer monitor (Display) is currently configured in 8-bit (256 Colors)',$
1077              'PseudoColor mode.  Due to the dynamic (read+write) nature of the colormap',$
1078              'system for this visual, when a colortable is loaded for an image it affects',$
1079              'all visible graphics windows, including the thumbnails of other images.  This',$
1080              'can lead to a phenomenon known as "color flashing".','',$
1081              'If possible, it is recommended that you exit this program, reconfigure your',$
1082              'monitor in 24-bit (TrueColor) mode or better, and restart IMAGE_VIEWER.']
1083  dummy=DIALOG_MESSAGE(messageStr)
1084endif
1085;obtain the current working directory:
1086CD,CURRENT=currentDir
1087if STRUPCASE(!VERSION.OS_FAMILY) EQ 'WINDOWS' then begin
1088  executeStr='cd "%USERPROFILE%\My Documents\My Pictures" & cd'
1089  SPAWN,executeStr,pathInit,/HIDE
1090  pathInit=pathInit[0]
1091  result=FILE_TEST(pathInit,/READ)
1092  if result EQ 1 then begin
1093    CD,pathInit
1094  endif else begin
1095    result=FILE_TEST('C:\My Documents\My Pictures',/READ)
1096    if result EQ 1 then begin
1097      CD,'C:\My Documents\My Pictures'
1098    endif else begin
1099      result=FILE_TEST('C:\',/READ)
1100      if result EQ 1 then CD,'C:\'
1101    endelse
1102  endelse
1103endif
1104;suppress informational messaging:
1105quietInit=!QUIET
1106!QUIET=1
1107;make sure color decomposition is disabled:
1108DEVICE,GET_DECOMPOSED=dc
1109if !D.N_COLORS GT 256 then colorMode='TRUE' else colorMode='PSEUDO'
1110;obtain the current color table:
1111TVLCT,r,g,b,/GET
1112LOADCT,0,/SILENT
1113;force !ORDER=0:
1114orderInit=!ORDER
1115!ORDER=0
1116;force !P.BACKGROUND=0:
1117backInit=!P.BACKGROUND
1118!P.BACKGROUND=0
1119;create GUI:
1120tlb=WIDGET_BASE(TITLE='Image Viewer',/ROW,MBAR=menuBar,/TLB_SIZE_EVENTS,XOFFSET=0,YOFFSET=0)
1121  fileMenu=WIDGET_BUTTON(menuBar,VALUE='File',/MENU)
1122    fileBttn1=WIDGET_BUTTON(fileMenu,VALUE='Open Picture Files',EVENT_PRO='image_viewer_open_files')
1123    fileBttn2=WIDGET_BUTTON(fileMenu,VALUE='Open All In Folder',EVENT_PRO='image_viewer_open_folder')
1124    fileBttn3=WIDGET_BUTTON(fileMenu,VALUE='Exit',EVENT_PRO='image_viewer_exit')
1125  helpMenu=WIDGET_BUTTON(menuBar,VALUE='Help',/MENU)
1126    helpBttn1=WIDGET_BUTTON(helpMenu,VALUE='Help on IMAGE_VIEWER',EVENT_PRO='image_viewer_help')
1127  controlsBase=WIDGET_BASE(tlb,/COLUMN,/FRAME,/ALIGN_TOP)
1128    labelBase=WIDGET_BASE(controlsBase,/COLUMN,SCR_XSIZE=280)
1129      thumbLabel=WIDGET_LABEL(labelBase,/ALIGN_CENTER,VALUE='CLICK ON THUMBNAIL TO VIEW IMAGE')
1130    thumbBase=WIDGET_BASE(controlsBase,/COLUMN,/ALIGN_TOP,/FRAME,XSIZE=260,YSIZE=700,$
1131                          /SCROLL,X_SCROLL_SIZE=260,Y_SCROLL_SIZE=650)
1132  imageBase=WIDGET_BASE(tlb,/COLUMN,/FRAME,/ALIGN_TOP)
1133    fileBase=WIDGET_BASE(imageBase,/ROW,/ALIGN_CENTER)
1134      fileLabel=WIDGET_LABEL(fileBase,VALUE='Current Image File = ')
1135      fileText=WIDGET_TEXT(fileBase,XSIZE=75,YSIZE=1)
1136    imageDraw=WIDGET_DRAW(imageBase,XSIZE=710,YSIZE=650,RETAIN=2)
1137;display the GUI on the computer monitor:
1138WIDGET_CONTROL,tlb,/REALIZE
1139;obtain the top-level base geometry:
1140tlbGeom=WIDGET_INFO(tlb,/GEOMETRY)
1141tlbWidth=tlbGeom.xsize
1142tlbHeight=tlbGeom.ysize
1143if tlbWidth EQ 0 or tlbHeight EQ 0 then begin
1144  WIDGET_CONTROL,tlb,TLB_GET_SIZE=tlbSize
1145  tlbWidth=tlbSize[0]
1146  tlbHeight=tlbSize[1]
1147endif
1148;create state structure to store information needed by the other event handling procedures:
1149pState=PTR_NEW({files:PTR_NEW(/ALLOCATE_HEAP),$
1150                images:PTR_NEW(/ALLOCATE_HEAP),$
1151                screenSize:screenSize,quietInit:quietInit,orderInit:orderInit,tlb:tlb,statusBase:0L,$
1152                controlsBase:controlsBase,thumbBase:thumbBase,fileText:fileText,timer:0B,nFiles:0L,$
1153                currentDir:currentDir,imageDraw:imageDraw,dc:dc,r:r,g:g,b:b,gifFlag:gifFlag,statusSlider:0L,$
1154                backInit:backInit,colorMode:colorMode,tlbWidth:tlbWidth,tlbHeight:tlbHeight,currFile:0L,$
1155                rowBase:0L,increment:0.0})
1156;store this state structure in the uvalue of the top-level-base
1157;so it can be obtained by other program units:
1158WIDGET_CONTROL,tlb,SET_UVALUE=pState
1159;register the GUI with the XMANAGER event handler routine:
1160XMANAGER,'image_viewer',tlb,CLEANUP='image_viewer_cleanup'
1161END
Note: See TracBrowser for help on using the repository browser.