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

Last change on this file since 138 was 136, checked in by pinsard, 18 years ago

some improvements and corrections in some .pro file according to
aspell and idldoc log file

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