source: trunk/SRC/ToBeReviewed/IMAGE/image_viewer.pro @ 114

Last change on this file since 114 was 114, checked in by smasson, 18 years ago

new compilation options (compile_opt idl2, strictarrsubs) in each routine

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