source: trunk/ToBeReviewed/IMAGE/image_viewer.pro @ 23

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

upgrade of IMAGE according to cerbere.lodyc.jussieu.fr: /usr/home/smasson/SAXO_RD/ : files

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