1 | ;+ |
---|
2 | ; @hidden |
---|
3 | ;- |
---|
4 | FUNCTION imdisp_getpos, ASPECT, POSITION=POSITION, MARGIN=MARGIN |
---|
5 | ; |
---|
6 | compile_opt idl2, strictarrsubs |
---|
7 | ; |
---|
8 | |
---|
9 | ;- Compute a position vector given an aspect ratio (called by IMDISP_IMSIZE) |
---|
10 | |
---|
11 | ;- Check arguments |
---|
12 | if (n_params() ne 1) then message, 'Usage: RESULT = IMDISP_GETPOS(ASPECT)' |
---|
13 | if (n_elements(aspect) eq 0) then message, 'ASPECT is undefined' |
---|
14 | |
---|
15 | ;- Check keywords |
---|
16 | if (n_elements(position) eq 0) then position = [0.0, 0.0, 1.0, 1.0] |
---|
17 | if (n_elements(margin) eq 0) then margin = 0.1 |
---|
18 | |
---|
19 | ;- Get range limited aspect ratio and margin input values |
---|
20 | aspect_val = (float(aspect[0]) > 0.01) < 100.0 |
---|
21 | margin_val = (float(margin[0]) > 0.0) < 0.495 |
---|
22 | |
---|
23 | ;- Compute aspect ratio of position vector in this window |
---|
24 | xsize = (position[2] - position[0]) * !d.x_vsize |
---|
25 | ysize = (position[3] - position[1]) * !d.y_vsize |
---|
26 | cur_aspect = ysize / xsize |
---|
27 | |
---|
28 | ;- Compute aspect ratio of this window |
---|
29 | win_aspect = float(!d.y_vsize) / float(!d.x_vsize) |
---|
30 | |
---|
31 | ;- Compute height and width in normalized units |
---|
32 | if (aspect_val ge cur_aspect) then begin |
---|
33 | height = (position[3] - position[1]) - 2.0 * margin |
---|
34 | width = height * (win_aspect / aspect_val) |
---|
35 | endif else begin |
---|
36 | width = (position[2] - position[0]) - 2.0 * margin |
---|
37 | height = width * (aspect_val / win_aspect) |
---|
38 | endelse |
---|
39 | |
---|
40 | ;- Compute and return position vector |
---|
41 | xcenter = 0.5 * (position[0] + position[2]) |
---|
42 | ycenter = 0.5 * (position[1] + position[3]) |
---|
43 | x0 = xcenter - 0.5 * width |
---|
44 | y0 = ycenter - 0.5 * height |
---|
45 | x1 = xcenter + 0.5 * width |
---|
46 | y1 = ycenter + 0.5 * height |
---|
47 | return, [x0, y0, x1, y1] |
---|
48 | |
---|
49 | END |
---|
50 | ;+ |
---|
51 | ; @hidden |
---|
52 | ;- |
---|
53 | FUNCTION imdisp_imscale, IMAGE, RANGE=RANGE, BOTTOM=BOTTOM, NCOLORS=NCOLORS, $ |
---|
54 | NEGATIVE=NEGATIVE |
---|
55 | ; |
---|
56 | compile_opt idl2, strictarrsubs |
---|
57 | ; |
---|
58 | |
---|
59 | ;- Byte-scale an image (called by IMDISP) |
---|
60 | |
---|
61 | ;- Check arguments |
---|
62 | if (n_params() ne 1) then message, 'Usage: RESULT = IMDISP_IMSCALE(IMAGE)' |
---|
63 | if (n_elements(image) eq 0) then message, 'Argument IMAGE is undefined' |
---|
64 | |
---|
65 | ;- Check keywords |
---|
66 | if (n_elements(range) eq 0) then begin |
---|
67 | min_value = min(image, max=max_value) |
---|
68 | range = [min_value, max_value] |
---|
69 | endif |
---|
70 | if (n_elements(bottom) eq 0) then bottom = 0B |
---|
71 | if (n_elements(ncolors) eq 0) then ncolors = !d.table_size - bottom |
---|
72 | |
---|
73 | ;- Compute the scaled image |
---|
74 | scaled = bytscl(image, min=range[0], max=range[1], top=(ncolors - 1)) |
---|
75 | |
---|
76 | ;- Create a negative image if required |
---|
77 | if keyword_set(negative) then scaled = byte(ncolors - 1) - scaled |
---|
78 | |
---|
79 | ;- Return the scaled image in the correct color range |
---|
80 | return, scaled + byte(bottom) |
---|
81 | |
---|
82 | END |
---|
83 | ; |
---|
84 | ;+ |
---|
85 | ; @hidden |
---|
86 | ;- |
---|
87 | FUNCTION imdisp_imregrid, DATA, NX, NY, INTERP=INTERP |
---|
88 | ; |
---|
89 | compile_opt idl2, strictarrsubs |
---|
90 | ; |
---|
91 | |
---|
92 | ;- Regrid a 2D array (called by IMDISP) |
---|
93 | |
---|
94 | ;- Check arguments |
---|
95 | if (n_params() ne 3) then $ |
---|
96 | message, 'Usage: RESULT = IMDISP_IMREGRID(DATA, NX, NY)' |
---|
97 | if (n_elements(data) eq 0) then message, 'Argument DATA is undefined' |
---|
98 | result = size(data) |
---|
99 | ndims = result[0] |
---|
100 | dims = result[1:ndims] |
---|
101 | if (ndims ne 2) then message, 'Argument DATA must have 2 dimensions' |
---|
102 | if (n_elements(nx) eq 0) then message, 'Argument NX is undefined' |
---|
103 | if (n_elements(ny) eq 0) then message, 'Argument NY is undefined' |
---|
104 | if (nx lt 1) then message, 'NX must be 1 or greater' |
---|
105 | if (ny lt 1) then message, 'NY must be 1 or greater' |
---|
106 | |
---|
107 | ;- Copy the array if the requested size is the same as the current size |
---|
108 | if (nx eq dims[0]) and (ny eq dims[1]) then begin |
---|
109 | new = data |
---|
110 | return, new |
---|
111 | endif |
---|
112 | |
---|
113 | ;- Compute index arrays for bilinear interpolation |
---|
114 | xindex = (findgen(nx) + 0.5) * (dims[0] / float(nx)) - 0.5 |
---|
115 | yindex = (findgen(ny) + 0.5) * (dims[1] / float(ny)) - 0.5 |
---|
116 | |
---|
117 | ;- Round the index arrays if nearest neighbor sampling is required |
---|
118 | if (keyword_set(interp) eq 0) then begin |
---|
119 | xindex = round(xindex) |
---|
120 | yindex = round(yindex) |
---|
121 | endif |
---|
122 | |
---|
123 | ;- Return regridded array |
---|
124 | return, interpolate(data, xindex, yindex, /grid) |
---|
125 | |
---|
126 | END |
---|
127 | ; |
---|
128 | ;+ |
---|
129 | ; |
---|
130 | ; @hidden |
---|
131 | ; |
---|
132 | ;- |
---|
133 | PRO imdisp_imsize, IMAGE, X0, Y0, XSIZE, YSIZE, ASPECT=ASPECT, $ |
---|
134 | POSITION=POSITION, MARGIN=MARGIN |
---|
135 | ; |
---|
136 | compile_opt idl2, strictarrsubs |
---|
137 | ; |
---|
138 | |
---|
139 | ;- Compute the size and offset for an image (called by IMDISP) |
---|
140 | |
---|
141 | ;- Check arguments |
---|
142 | if (n_params() ne 5) then $ |
---|
143 | message, 'Usage: IMDISP_IMSIZE, IMAGE, X0, Y0, XSIZE, YSIZE' |
---|
144 | if (n_elements(image) eq 0) then $ |
---|
145 | message, 'Argument IMAGE is undefined' |
---|
146 | if (n_elements(position) eq 0) then position = [0.0, 0.0, 1.0, 1.0] |
---|
147 | if (n_elements(position) ne 4) then $ |
---|
148 | message, 'POSITION must be a 4 elements vector' |
---|
149 | if (n_elements(margin) eq 0) then margin = 0.1 |
---|
150 | if (n_elements(margin) ne 1) then $ |
---|
151 | message, 'MARGIN must be a scalar' |
---|
152 | |
---|
153 | ;- Get image dimensions |
---|
154 | result = size(image) |
---|
155 | ndims = result[0] |
---|
156 | if (ndims ne 2) then message, 'IMAGE must be a 2D array' |
---|
157 | dims = result[1 : ndims] |
---|
158 | |
---|
159 | ;- Get aspect ratio for image |
---|
160 | if (n_elements(aspect) eq 0) then $ |
---|
161 | aspect = float(dims[1]) / float(dims[0]) |
---|
162 | if (n_elements(aspect) ne 1) then $ |
---|
163 | message, 'ASPECT must be a scalar' |
---|
164 | |
---|
165 | ;- Check output parameters |
---|
166 | if (arg_present(x0) ne 1) then message, 'Argument XO cannot be set' |
---|
167 | if (arg_present(y0) ne 1) then message, 'Argument YO cannot be set' |
---|
168 | if (arg_present(xsize) ne 1) then message, 'Argument XSIZE cannot be set' |
---|
169 | if (arg_present(ysize) ne 1) then message, 'Argument YSIZE cannot be set' |
---|
170 | |
---|
171 | ;- Get approximate image position |
---|
172 | position = imdisp_getpos(aspect, position=position, margin=margin) |
---|
173 | |
---|
174 | ;- Compute lower left position of image (device units) |
---|
175 | x0 = round(position[0] * !d.x_vsize) > 0L |
---|
176 | y0 = round(position[1] * !d.y_vsize) > 0L |
---|
177 | |
---|
178 | ;- Compute size of image (device units) |
---|
179 | xsize = round((position[2] - position[0]) * !d.x_vsize) > 2L |
---|
180 | ysize = round((position[3] - position[1]) * !d.y_vsize) > 2L |
---|
181 | |
---|
182 | ;- Recompute the image position based on actual image size |
---|
183 | position = fltarr(4) |
---|
184 | position[0] = x0 / float(!d.x_vsize) |
---|
185 | position[1] = y0 / float(!d.y_vsize) |
---|
186 | position[2] = (x0 + xsize) / float(!d.x_vsize) |
---|
187 | position[3] = (y0 + ysize) / float(!d.y_vsize) |
---|
188 | |
---|
189 | END |
---|
190 | ; |
---|
191 | ;+ |
---|
192 | ; |
---|
193 | ; @file_comments |
---|
194 | ; Display an image on the current graphics device. |
---|
195 | ; IMDISP is an advanced replacement for <proidl>TV</proidl> and |
---|
196 | ; <proidl>TVSCL</proidl>. |
---|
197 | ; |
---|
198 | ; - Supports WIN, MAC, X, CGM, PCL, PRINTER, PS, and Z graphics devices, |
---|
199 | ; - Image is automatically byte-scaled (can be disabled), |
---|
200 | ; - Custom byte-scaling of Pseudo color images via the RANGE keyword, |
---|
201 | ; - Pseudo (indexed) color and True color images are handled automatically, |
---|
202 | ; - 8-bit and 24-bit graphics devices are handled automatically, |
---|
203 | ; - Decomposed color settings are handled automatically, |
---|
204 | ; - Image is automatically sized to fit the display (can be disabled), |
---|
205 | ; - The !P.MULTI system variable is honored for multiple image display, |
---|
206 | ; - Image can be positioned via the POSITION keyword, |
---|
207 | ; - Color table splitting via the BOTTOM and NCOLORS keywords, |
---|
208 | ; - Image aspect ratio customization via the ASPECT keyword, |
---|
209 | ; - Resized images can be resampled (default) or interpolated, |
---|
210 | ; - Top down image display via the ORDER keyword (!ORDER is ignored), |
---|
211 | ; - Selectable display channel (R/G/B) via the CHANNEL keyword, |
---|
212 | ; - Background can be set to a specified color via the BACKGROUND keyword, |
---|
213 | ; - Screen can be erased prior to image display via the ERASE keyword, |
---|
214 | ; - Plot axes can be drawn on the image via the AXIS keyword, |
---|
215 | ; - Photographic negative images can be displayed via the NEGATIVE keyword. |
---|
216 | ; |
---|
217 | ; @categories |
---|
218 | ; Picture |
---|
219 | ; |
---|
220 | ; @param IMAGE {in}{required} |
---|
221 | ; Array containing image data. |
---|
222 | ; Pseudo (indexed) color images must have 2 dimensions. |
---|
223 | ; True color images must have 3 dimensions, in either |
---|
224 | ; [3, NX, NY], [NX, 3, NY], or [NX, NY, 3] form. |
---|
225 | ; |
---|
226 | ; @keyword RANGE {type=vector}{default=min and max array values} |
---|
227 | ; For Pseudo Color images only, a vector with two elements |
---|
228 | ; specifying the minimum and maximum values of the image |
---|
229 | ; array to be considered when the image is byte-scaled |
---|
230 | ; This keyword is ignored for True Color images, |
---|
231 | ; or if the NOSCALE keyword is set. |
---|
232 | ; |
---|
233 | ; @keyword BOTTOM {default=0} |
---|
234 | ; Bottom value in the color table to be used |
---|
235 | ; for the byte-scaled image. |
---|
236 | ; This keyword is ignored if the NOSCALE keyword is set. |
---|
237 | ; |
---|
238 | ; @keyword NCOLORS {default=!D.TABLE_SIZE - BOTTOM} |
---|
239 | ; Number of colors in the color table to be used |
---|
240 | ; for the byte-scaled image |
---|
241 | ; This keyword is ignored if the NOSCALE keyword is set. |
---|
242 | ; |
---|
243 | ; @keyword MARGIN {default=0.1 or 0.025 if !P.MULTI is set to display multiple images} |
---|
244 | ; A scalar value specifying the margin to be maintained |
---|
245 | ; around the image in normal coordinates |
---|
246 | ; |
---|
247 | ; @keyword INTERP {default=nearest neighbor sampling} |
---|
248 | ; If set, the resized image will be interpolated using |
---|
249 | ; bilinear interpolation |
---|
250 | ; |
---|
251 | ; @keyword DITHER {default=no dithering} |
---|
252 | ; If set, true color images will be dithered when displayed |
---|
253 | ; on an 8-bit graphics device |
---|
254 | ; |
---|
255 | ; @keyword ASPECT {default=maintain native aspect ratio} |
---|
256 | ; A scalar value specifying the aspect ratio (height/width) |
---|
257 | ; for the displayed image |
---|
258 | ; |
---|
259 | ; @keyword POSITION {default= [0.0,0.0,1.0,1.0]} |
---|
260 | ; On input, a 4-element vector specifying the position |
---|
261 | ; of the displayed image in the form [X0,Y0,X1,Y1] in |
---|
262 | ; in normal coordinates |
---|
263 | ; See the examples below to display an image where only the |
---|
264 | ; offset and size are known (e.g. MAP_IMAGE output). |
---|
265 | ; |
---|
266 | ; @keyword OUT_POS |
---|
267 | ; On output, a 4-element vector specifying the position |
---|
268 | ; actually used to display the image. |
---|
269 | ; |
---|
270 | ; @keyword NOSCALE {default=to byte-scale the image} |
---|
271 | ; If set, the image will not be byte-scaled. |
---|
272 | ; |
---|
273 | ; @keyword NORESIZE {default=To resize the image to fit the display} |
---|
274 | ; If set, the image will not be resized. |
---|
275 | ; |
---|
276 | ; @keyword ORDER {default=To display the image from the bottom up} |
---|
277 | ; If set, the image is displayed from the top down |
---|
278 | ; Note that the system variable !ORDER is always ignored. |
---|
279 | ; |
---|
280 | ; @keyword USEPOS {default=To honor ASPECT and MARGIN when POSITION vector is supplied} |
---|
281 | ; If set, the image will be sized to exactly fit a supplied |
---|
282 | ; POSITION vector, over-riding ASPECT and MARGIN. |
---|
283 | ; |
---|
284 | ; @keyword CHANNEL |
---|
285 | ; Display channel (Red, Green, or Blue) to be written. |
---|
286 | ; 0 => All channels (the default) |
---|
287 | ; 1 => Red channel |
---|
288 | ; 2 => Green channel |
---|
289 | ; 3 => Blue channel |
---|
290 | ; This keyword is only recognized by graphics devices which |
---|
291 | ; support 24-bit decomposed color (WIN, MAC, X). It is ignored |
---|
292 | ; by all other graphics devices. However True color (RGB) |
---|
293 | ; images can be displayed on any device supported by IMDISP. |
---|
294 | ; |
---|
295 | ; @keyword BACKGROUND |
---|
296 | ; If set to a positive integer, the background will be filled |
---|
297 | ; with the color defined by BACKGROUND. |
---|
298 | ; |
---|
299 | ; @keyword ERASE |
---|
300 | ; If set, the screen contents will be erased. Note that if |
---|
301 | ; !P.MULTI is set to display multiple images, the screen is |
---|
302 | ; always erased when the first image is displayed. |
---|
303 | ; |
---|
304 | ; @keyword AXIS |
---|
305 | ; If set, plot axes will be drawn on the image. The default |
---|
306 | ; x and y axis ranges are determined by the size of the image. |
---|
307 | ; When the AXIS keyword is set, IMDISP accepts any keywords |
---|
308 | ; supported by PLOT (e.g. TITLE, COLOR, CHARSIZE etc.). |
---|
309 | ; |
---|
310 | ; @keyword NEGATIVE |
---|
311 | ; If set, a photographic negative of the image is displayed. |
---|
312 | ; The values of BOTTOM and NCOLORS are honored. This keyword |
---|
313 | ; allows True color images scanned from color negatives to be |
---|
314 | ; displayed. It also allows Pseudo color images to be displayed |
---|
315 | ; as negatives without reversing the color table. This keyword |
---|
316 | ; is ignored if the NOSCALE keyword is set. |
---|
317 | ; |
---|
318 | ; @restrictions |
---|
319 | ; The image is displayed on the current graphics device. |
---|
320 | ; |
---|
321 | ; @restrictions |
---|
322 | ; Requires IDL 5.0 or higher (square bracket array syntax). |
---|
323 | ; |
---|
324 | ; @examples |
---|
325 | ; |
---|
326 | ;;- Load test data |
---|
327 | ; |
---|
328 | ; openr, lun, filepath('ctscan.dat', subdir='examples/data'), /get_lun |
---|
329 | ;ctscan = bytarr(256, 256) |
---|
330 | ;readu, lun, ctscan |
---|
331 | ;free_lun, lun |
---|
332 | ;openr, lun, filepath('hurric.dat', subdir='examples/data'), /get_lun |
---|
333 | ;hurric = bytarr(440, 330) |
---|
334 | ;readu, lun, hurric |
---|
335 | ;free_lun, lun |
---|
336 | ;read_jpeg, filepath('rose.jpg', subdir='examples/data'), rose |
---|
337 | ;help, ctscan, hurric, rose |
---|
338 | ; |
---|
339 | ;;- Display single images |
---|
340 | ; |
---|
341 | ;!p.multi = 0 |
---|
342 | ;loadct, 0 |
---|
343 | ;imdisp, hurric, /erase |
---|
344 | ;wait, 3.0 |
---|
345 | ;imdisp, rose, /interp, /erase |
---|
346 | ;wait, 3.0 |
---|
347 | ; |
---|
348 | ;;- Display multiple images without color table splitting |
---|
349 | ;;- (works on 24-bit displays only; top 2 images are garbled on 8-bit displays) |
---|
350 | ; |
---|
351 | ;!p.multi = [0, 1, 3, 0, 0] |
---|
352 | ;loadct, 0 |
---|
353 | ;imdisp, ctscan, margin=0.02 |
---|
354 | ;loadct, 13 |
---|
355 | ;imdisp, hurric, margin=0.02 |
---|
356 | ;imdisp, rose, margin=0.02 |
---|
357 | ;wait, 3.0 |
---|
358 | ; |
---|
359 | ;;- Display multiple images with color table splitting |
---|
360 | ;;- (works on 8-bit or 24-bit displays) |
---|
361 | ; |
---|
362 | ;!p.multi = [0, 1, 3, 0, 0] |
---|
363 | ;loadct, 0, ncolors=64, bottom=0 |
---|
364 | ;imdisp, ctscan, margin=0.02, ncolors=64, bottom=0 |
---|
365 | ;loadct, 13, ncolors=64, bottom=64 |
---|
366 | ;imdisp, hurric, margin=0.02, ncolors=64, bottom=64 |
---|
367 | ;imdisp, rose, margin=0.02, ncolors=64, bottom=128 |
---|
368 | ;wait, 3.0 |
---|
369 | ; |
---|
370 | ;;- Display an image at a specific position, over-riding aspect and margin |
---|
371 | ; |
---|
372 | ;!p.multi = 0 |
---|
373 | ;loadct, 0 |
---|
374 | ;imdisp, hurric, position=[0.0, 0.0, 1.0, 0.5], /usepos, /erase |
---|
375 | ;wait, 3.0 |
---|
376 | ; |
---|
377 | ;;- Display an image with axis overlay |
---|
378 | ; |
---|
379 | ;!p.multi = 0 |
---|
380 | ;loadct, 0 |
---|
381 | ;imdisp, rose, /axis, /erase |
---|
382 | ;wait, 3.0 |
---|
383 | ; |
---|
384 | ;;- Display an image with contour plot overlay |
---|
385 | ; |
---|
386 | ;!p.multi = 0 |
---|
387 | ;loadct, 0 |
---|
388 | ;imdisp, hurric, out_pos=out_pos, /erase |
---|
389 | ;contour, smooth(hurric, 10, /edge), /noerase, position=out_pos, $ |
---|
390 | ; xstyle=1, ystyle=1, levels=findgen(5)*40.0, /follow |
---|
391 | ;wait, 3.0 |
---|
392 | ; |
---|
393 | ;;- Display a small image with correct resizing |
---|
394 | ; |
---|
395 | ;!p.multi = 0 |
---|
396 | ;loadct, 0 |
---|
397 | ;data = (dist(8))[1:7, 1:7] |
---|
398 | ;imdisp, data, /erase |
---|
399 | ;wait, 3.0 |
---|
400 | ;imdisp, data, /interp |
---|
401 | ;wait, 3.0 |
---|
402 | ; |
---|
403 | ;;- Display a true color image without and with interpolation |
---|
404 | ; |
---|
405 | ;!p.multi = 0 |
---|
406 | ;imdisp, rose, /erase |
---|
407 | ;wait, 3.0 |
---|
408 | ;imdisp, rose, /interp |
---|
409 | ;wait, 3.0 |
---|
410 | ; |
---|
411 | ;;- Display a true color image as a photographic negative |
---|
412 | ; |
---|
413 | ;imdisp, rose, /negative, /erase |
---|
414 | ;wait, 3.0 |
---|
415 | ; |
---|
416 | ;;- Display a true color image on PostScript output |
---|
417 | ;;- (note that color table is handled automatically) |
---|
418 | ; |
---|
419 | ;current_device = !d.name |
---|
420 | ;set_plot, 'PS' |
---|
421 | ;device, /color, bits_per_pixel=8, filename='imdisp_true.ps' |
---|
422 | ;imdisp, rose, /axis, title='PostScript True Color Output' |
---|
423 | ;device, /close |
---|
424 | ;set_plot, current_device |
---|
425 | ; |
---|
426 | ;;- Display a pseudo color image on PostScript output |
---|
427 | ; |
---|
428 | ;current_device = !d.name |
---|
429 | ;set_plot, 'PS' |
---|
430 | ;device, /color, bits_per_pixel=8, filename='imdisp_pseudo.ps' |
---|
431 | ;loadct, 0 |
---|
432 | ;imdisp, hurric, /axis, title='PostScript Pseudo Color Output' |
---|
433 | ;device, /close |
---|
434 | ;set_plot, current_device |
---|
435 | ; |
---|
436 | ;;- Display an image where only the offset and size are known |
---|
437 | ; |
---|
438 | ;;- Read world elevation data |
---|
439 | ;file = filepath('worldelv.dat', subdir='examples/data') |
---|
440 | ;openr, lun, file, /get_lun |
---|
441 | ;data = bytarr(360, 360) |
---|
442 | ;readu, lun, data |
---|
443 | ;free_lun, lun |
---|
444 | ;;- Reorganize array so it spans 180W to 180E |
---|
445 | ;world = data |
---|
446 | ;world[0:179, *] = data[180:*, *] |
---|
447 | ;world[180:*, *] = data[0:179, *] |
---|
448 | ;;- Create remapped image |
---|
449 | ;map_set, /orthographic, /isotropic, /noborder |
---|
450 | ;remap = map_image(world, x0, y0, xsize, ysize, compress=1) |
---|
451 | ;;- Convert offset and size to position vector |
---|
452 | ;pos = fltarr(4) |
---|
453 | ;pos[0] = x0 / float(!d.x_vsize) |
---|
454 | ;pos[1] = y0 / float(!d.y_vsize) |
---|
455 | ;pos[2] = (x0 + xsize) / float(!d.x_vsize) |
---|
456 | ;pos[3] = (y0 + ysize) / float(!d.y_vsize) |
---|
457 | ;;- Display the image |
---|
458 | ;loadct, 0 |
---|
459 | ;imdisp, remap, pos=pos, /usepos |
---|
460 | ;map_continents |
---|
461 | ;map_grid |
---|
462 | ; |
---|
463 | ; @history |
---|
464 | ; Liam.Gumley\@ssec.wisc.edu |
---|
465 | ; <a href="http://cimss.ssec.wisc.edu/~gumley"/> |
---|
466 | ; |
---|
467 | ; Copyright (C) 1999, 2000 Liam E. Gumley |
---|
468 | ; |
---|
469 | ; This program is free software; you can redistribute it and/or |
---|
470 | ; modify it under the terms of the GNU General Public License |
---|
471 | ; as published by the Free Software Foundation; either version 2 |
---|
472 | ; of the License, or (at your option) any later version. |
---|
473 | ; |
---|
474 | ; This program is distributed in the hope that it will be useful, |
---|
475 | ; but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
476 | ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
477 | ; GNU General Public License for more details. |
---|
478 | ; |
---|
479 | ; You should have received a copy of the GNU General Public License |
---|
480 | ; along with this program; if not, write to the Free Software |
---|
481 | ; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
---|
482 | ; |
---|
483 | ; @version |
---|
484 | ; $Id$ |
---|
485 | ; |
---|
486 | ;- |
---|
487 | PRO imdisp, IMAGE, RANGE=RANGE, BOTTOM=BOTTOM, NCOLORS=NCOLORS, $ |
---|
488 | MARGIN=MARGIN, INTERP=INTERP, DITHER=DITHER, ASPECT=ASPECT, $ |
---|
489 | POSITION=POSITION, OUT_POS=OUT_POS, NOSCALE=NOSCALE, NORESIZE=NORESIZE, $ |
---|
490 | ORDER=ORDER, USEPOS=USEPOS, CHANNEL=CHANNEL, $ |
---|
491 | BACKGROUND=BACKGROUND, ERASE=ERASE, $ |
---|
492 | AXIS=AXIS, NEGATIVE=NEGATIVE, _EXTRA=EXTRA_KEYWORDS |
---|
493 | ; |
---|
494 | compile_opt idl2, strictarrsubs |
---|
495 | ; |
---|
496 | |
---|
497 | rcs_id = '$Id$' |
---|
498 | |
---|
499 | ;------------------------------------------------------------------------------- |
---|
500 | ;- CHECK INPUT |
---|
501 | ;------------------------------------------------------------------------------- |
---|
502 | |
---|
503 | ;- Check arguments |
---|
504 | if (n_params() ne 1) then message, 'Usage: IMDISP, IMAGE' |
---|
505 | if (n_elements(image) eq 0) then message, 'Argument IMAGE is undefined' |
---|
506 | if (max(!p.multi) eq 0) then begin |
---|
507 | if (n_elements(margin) eq 0) then begin |
---|
508 | if (n_elements(position) eq 4) then margin = 0.0 else margin = 0.1 |
---|
509 | endif |
---|
510 | endif else begin |
---|
511 | if (n_elements(margin) eq 0) then margin = 0.025 |
---|
512 | endelse |
---|
513 | if (n_elements(order) eq 0) then order = 0 |
---|
514 | if (n_elements(channel) eq 0) then channel = 0 |
---|
515 | |
---|
516 | ;- Check position vector |
---|
517 | if (n_elements(position) gt 0) then begin |
---|
518 | if (n_elements(position) ne 4) then $ |
---|
519 | message, 'POSITION must be a 4 element vector of the form [X0, Y0, X1, Y1]' |
---|
520 | if (position[0] lt 0.0) then message, 'POSITION[0] must be GE 0.0' |
---|
521 | if (position[1] lt 0.0) then message, 'POSITION[1] must be GE 0.0' |
---|
522 | if (position[2] gt 1.0) then message, 'POSITION[2] must be LE 1.0' |
---|
523 | if (position[3] gt 1.0) then message, 'POSITION[3] must be LE 1.0' |
---|
524 | if (position[0] ge position[2]) then $ |
---|
525 | message, 'POSITION[0] must be LT POSITION[2]' |
---|
526 | if (position[1] ge position[3]) then $ |
---|
527 | message, 'POSITION[1] must be LT POSITION[3]' |
---|
528 | endif |
---|
529 | |
---|
530 | ;- Check the image dimensions |
---|
531 | result = size(image) |
---|
532 | ndims = result[0] |
---|
533 | if (ndims lt 2) or (ndims gt 3) then $ |
---|
534 | message, 'IMAGE must be a Pseudo Color (2D) or True Color (3D) image array' |
---|
535 | dims = result[1:ndims] |
---|
536 | |
---|
537 | ;- Check that 3D image array is in valid true color format |
---|
538 | true = 0 |
---|
539 | if (ndims eq 3) then begin |
---|
540 | index = where(dims eq 3L, count) |
---|
541 | if (count eq 0) then $ |
---|
542 | message, 'True Color dimensions must be [3,NX,NY], [NX,3,NY], or [NX,NY,3]' |
---|
543 | true = 1 |
---|
544 | truedim = index[0] |
---|
545 | endif |
---|
546 | |
---|
547 | ;- Check scaling range for pseudo color images |
---|
548 | if (true eq 0) then begin |
---|
549 | if (n_elements(range) eq 0) then begin |
---|
550 | min_value = min(image, max=max_value) |
---|
551 | range = [min_value, max_value] |
---|
552 | endif |
---|
553 | if (n_elements(range) ne 2) then $ |
---|
554 | message, 'RANGE keyword must be a 2-element vector' |
---|
555 | endif else begin |
---|
556 | if (n_elements(range) gt 0) then $ |
---|
557 | message, 'RANGE keyword is not used for True Color images', /continue |
---|
558 | endelse |
---|
559 | |
---|
560 | ;- Check for supported graphics devices |
---|
561 | names = ['WIN', 'MAC', 'X', 'CGM', 'PCL', 'PRINTER', 'PS', 'Z'] |
---|
562 | result = where((!d.name eq names), count) |
---|
563 | if (count eq 0) then message, 'Graphics device is not supported' |
---|
564 | |
---|
565 | ;- Get color table information |
---|
566 | if ((!d.flags and 256) ne 0) and (!d.window lt 0) then begin |
---|
567 | window, /free, /pixmap |
---|
568 | wdelete, !d.window |
---|
569 | endif |
---|
570 | if (n_elements(bottom) eq 0) then bottom = 0 |
---|
571 | if (n_elements(ncolors) eq 0) then ncolors = !d.table_size - bottom |
---|
572 | |
---|
573 | ;- Get IDL version number |
---|
574 | version = float(!version.release) |
---|
575 | |
---|
576 | ;- Check for IDL 5.2 or higher if printer device is selected |
---|
577 | if (version lt 5.2) and (!d.name eq 'PRINTER') then $ |
---|
578 | message, 'IDL 5.2 or higher is required for PRINTER device support' |
---|
579 | |
---|
580 | ;------------------------------------------------------------------------------- |
---|
581 | ;- GET RED, GREEN, AND BLUE COMPONENTS OF TRUE COLOR IMAGE |
---|
582 | ;------------------------------------------------------------------------------- |
---|
583 | |
---|
584 | if (true eq 1) then begin |
---|
585 | case truedim of |
---|
586 | 0 : begin |
---|
587 | red = image[0, *, *] |
---|
588 | grn = image[1, *, *] |
---|
589 | blu = image[2, *, *] |
---|
590 | end |
---|
591 | 1 : begin |
---|
592 | red = image[*, 0, *] |
---|
593 | grn = image[*, 1, *] |
---|
594 | blu = image[*, 2, *] |
---|
595 | end |
---|
596 | 2 : begin |
---|
597 | red = image[*, *, 0] |
---|
598 | grn = image[*, *, 1] |
---|
599 | blu = image[*, *, 2] |
---|
600 | end |
---|
601 | endcase |
---|
602 | red = reform(red, /overwrite) |
---|
603 | grn = reform(grn, /overwrite) |
---|
604 | blu = reform(blu, /overwrite) |
---|
605 | endif |
---|
606 | |
---|
607 | ;------------------------------------------------------------------------------- |
---|
608 | ;- COMPUTE POSITION FOR IMAGE |
---|
609 | ;------------------------------------------------------------------------------- |
---|
610 | |
---|
611 | ;- Save first element of !p.multi |
---|
612 | multi_first = !p.multi[0] |
---|
613 | |
---|
614 | ;- Establish image position if not defined |
---|
615 | if (n_elements(position) eq 0) then begin |
---|
616 | if (max(!p.multi) eq 0) then begin |
---|
617 | position = [0.0, 0.0, 1.0, 1.0] |
---|
618 | endif else begin |
---|
619 | plot, [0], /nodata, xstyle=4, ystyle=4, xmargin=[0, 0], ymargin=[0, 0] |
---|
620 | position = [!x.window[0], !y.window[0], !x.window[1], !y.window[1]] |
---|
621 | endelse |
---|
622 | endif |
---|
623 | |
---|
624 | ;- Erase and fill the background if required |
---|
625 | if (multi_first eq 0) then begin |
---|
626 | if keyword_set(erase) then erase |
---|
627 | if (n_elements(background) gt 0) then begin |
---|
628 | polyfill, [-0.01, 1.01, 1.01, -0.01, -0.01], $ |
---|
629 | [-0.01, -0.01, 1.01, 1.01, -0.01], /normal, color=background[0] |
---|
630 | endif |
---|
631 | endif |
---|
632 | |
---|
633 | ;- Compute image aspect ratio if not defined |
---|
634 | if (n_elements(aspect) eq 0) then begin |
---|
635 | case true of |
---|
636 | 0 : result = size(image) |
---|
637 | 1 : result = size(red) |
---|
638 | endcase |
---|
639 | dims = result[1:2] |
---|
640 | aspect = float(dims[1]) / float(dims[0]) |
---|
641 | endif |
---|
642 | |
---|
643 | ;- Save image xrange and yrange for axis overlays |
---|
644 | xrange = [0, dims[0]] |
---|
645 | yrange = [0, dims[1]] |
---|
646 | if (order eq 1) then yrange = reverse(yrange) |
---|
647 | |
---|
648 | ;- Set the aspect ratio and margin to fill the position window if requested |
---|
649 | if keyword_set(usepos) then begin |
---|
650 | xpos_size = float(!d.x_vsize) * (position[2] - position[0]) |
---|
651 | ypos_size = float(!d.y_vsize) * (position[3] - position[1]) |
---|
652 | aspect_value = ypos_size / xpos_size |
---|
653 | margin_value = 0.0 |
---|
654 | endif else begin |
---|
655 | aspect_value = aspect |
---|
656 | margin_value = margin |
---|
657 | endelse |
---|
658 | |
---|
659 | ;- Compute size of displayed image and save output position |
---|
660 | pos = position |
---|
661 | case true of |
---|
662 | 0 : imdisp_imsize, image, x0, y0, xsize, ysize, position=pos, $ |
---|
663 | aspect=aspect_value, margin=margin_value |
---|
664 | 1 : imdisp_imsize, red, x0, y0, xsize, ysize, position=pos, $ |
---|
665 | aspect=aspect_value, margin=margin_value |
---|
666 | endcase |
---|
667 | out_pos = pos |
---|
668 | |
---|
669 | ;------------------------------------------------------------------------------- |
---|
670 | ;- BYTE-SCALE THE IMAGE IF REQUIRED |
---|
671 | ;------------------------------------------------------------------------------- |
---|
672 | |
---|
673 | ;- Choose whether to scale the image or not |
---|
674 | if (keyword_set(noscale) eq 0) then begin |
---|
675 | |
---|
676 | ;- Scale the image |
---|
677 | case true of |
---|
678 | 0 : scaled = imdisp_imscale(image, bottom=bottom, ncolors=ncolors, $ |
---|
679 | range=range, negative=keyword_set(negative)) |
---|
680 | 1 : begin |
---|
681 | scaled_dims = (size(red))[1:2] |
---|
682 | scaled = bytarr(scaled_dims[0], scaled_dims[1], 3) |
---|
683 | scaled[0, 0, 0] = imdisp_imscale(red, bottom=0, ncolors=256, $ |
---|
684 | negative=keyword_set(negative)) |
---|
685 | scaled[0, 0, 1] = imdisp_imscale(grn, bottom=0, ncolors=256, $ |
---|
686 | negative=keyword_set(negative)) |
---|
687 | scaled[0, 0, 2] = imdisp_imscale(blu, bottom=0, ncolors=256, $ |
---|
688 | negative=keyword_set(negative)) |
---|
689 | end |
---|
690 | endcase |
---|
691 | |
---|
692 | endif else begin |
---|
693 | |
---|
694 | ;- Don't scale the image |
---|
695 | case true of |
---|
696 | 0 : scaled = image |
---|
697 | 1 : begin |
---|
698 | scaled_dims = (size(red))[1:2] |
---|
699 | scaled = replicate(red[0], scaled_dims[0], scaled_dims[1], 3) |
---|
700 | scaled[0, 0, 0] = red |
---|
701 | scaled[0, 0, 1] = grn |
---|
702 | scaled[0, 0, 2] = blu |
---|
703 | end |
---|
704 | endcase |
---|
705 | |
---|
706 | endelse |
---|
707 | |
---|
708 | ;------------------------------------------------------------------------------- |
---|
709 | ;- DISPLAY IMAGE ON PRINTER DEVICE |
---|
710 | ;------------------------------------------------------------------------------- |
---|
711 | |
---|
712 | if (!d.name eq 'PRINTER') then begin |
---|
713 | |
---|
714 | ;- Display the image |
---|
715 | case true of |
---|
716 | 0 : begin |
---|
717 | device, /index_color |
---|
718 | tv, scaled, x0, y0, xsize=xsize, ysize=ysize, order=order |
---|
719 | end |
---|
720 | 1 : begin |
---|
721 | device, /true_color |
---|
722 | tv, scaled, x0, y0, xsize=xsize, ysize=ysize, order=order, true=3 |
---|
723 | end |
---|
724 | endcase |
---|
725 | |
---|
726 | ;- Draw axes if required |
---|
727 | if keyword_set(axis) then $ |
---|
728 | plot, [0], /nodata, /noerase, position=out_pos, $ |
---|
729 | xrange=xrange, xstyle=1, yrange=yrange, ystyle=1, $ |
---|
730 | _extra=extra_keywords |
---|
731 | |
---|
732 | ;- Return to caller |
---|
733 | return |
---|
734 | |
---|
735 | endif |
---|
736 | |
---|
737 | ;------------------------------------------------------------------------------- |
---|
738 | ;- DISPLAY IMAGE ON GRAPHICS DEVICES WHICH HAVE SCALEABLE PIXELS |
---|
739 | ;------------------------------------------------------------------------------- |
---|
740 | |
---|
741 | if ((!d.flags and 1) ne 0) then begin |
---|
742 | |
---|
743 | ;- Display the image |
---|
744 | case true of |
---|
745 | 0 : tv, scaled, x0, y0, xsize=xsize, ysize=ysize, order=order |
---|
746 | 1 : begin |
---|
747 | tvlct, r, g, b, /get |
---|
748 | loadct, 0, /silent |
---|
749 | tv, scaled, x0, y0, xsize=xsize, ysize=ysize, order=order, true=3 |
---|
750 | tvlct, r, g, b |
---|
751 | end |
---|
752 | endcase |
---|
753 | |
---|
754 | ;- Draw axes if required |
---|
755 | if keyword_set(axis) then $ |
---|
756 | plot, [0], /nodata, /noerase, position=out_pos, $ |
---|
757 | xrange=xrange, xstyle=1, yrange=yrange, ystyle=1, $ |
---|
758 | _extra=extra_keywords |
---|
759 | |
---|
760 | ;- Return to caller |
---|
761 | return |
---|
762 | |
---|
763 | endif |
---|
764 | |
---|
765 | ;------------------------------------------------------------------------------- |
---|
766 | ;- RESIZE THE IMAGE |
---|
767 | ;------------------------------------------------------------------------------- |
---|
768 | |
---|
769 | ;- Resize the image |
---|
770 | if (keyword_set(noresize) eq 0) then begin |
---|
771 | if (true eq 0) then begin |
---|
772 | resized = imdisp_imregrid(scaled, xsize, ysize, interp=keyword_set(interp)) |
---|
773 | endif else begin |
---|
774 | resized = replicate(scaled[0], xsize, ysize, 3) |
---|
775 | resized[0, 0, 0] = imdisp_imregrid(reform(scaled[*, *, 0]), xsize, ysize, $ |
---|
776 | interp=keyword_set(interp)) |
---|
777 | resized[0, 0, 1] = imdisp_imregrid(reform(scaled[*, *, 1]), xsize, ysize, $ |
---|
778 | interp=keyword_set(interp)) |
---|
779 | resized[0, 0, 2] = imdisp_imregrid(reform(scaled[*, *, 2]), xsize, ysize, $ |
---|
780 | interp=keyword_set(interp)) |
---|
781 | endelse |
---|
782 | endif else begin |
---|
783 | resized = temporary(scaled) |
---|
784 | x0 = 0 |
---|
785 | y0 = 0 |
---|
786 | endelse |
---|
787 | |
---|
788 | ;------------------------------------------------------------------------------- |
---|
789 | ;- GET BIT DEPTH FOR THIS DISPLAY |
---|
790 | ;------------------------------------------------------------------------------- |
---|
791 | |
---|
792 | ;- If this device supports windows, make sure a window has been opened |
---|
793 | if (!d.flags and 256) ne 0 then begin |
---|
794 | if (!d.window lt 0) then begin |
---|
795 | window, /free, /pixmap |
---|
796 | wdelete, !d.window |
---|
797 | endif |
---|
798 | endif |
---|
799 | |
---|
800 | ;- Set default display depth |
---|
801 | depth = 8 |
---|
802 | |
---|
803 | ;- Get actual bit depth on supported displays |
---|
804 | if (!d.name eq 'WIN') or (!d.name eq 'MAC') or (!d.name eq 'X') then begin |
---|
805 | if (version ge 5.1) then begin |
---|
806 | device, get_visual_depth=depth |
---|
807 | endif else begin |
---|
808 | if (!d.n_colors gt 256) then depth = 24 |
---|
809 | endelse |
---|
810 | endif |
---|
811 | |
---|
812 | ;------------------------------------------------------------------------------- |
---|
813 | ;- SELECT DECOMPOSED COLOR MODE (ON OR OFF) FOR 24-BIT DISPLAYS |
---|
814 | ;------------------------------------------------------------------------------- |
---|
815 | |
---|
816 | if (!d.name eq 'WIN') or (!d.name eq 'MAC') or (!d.name eq 'X') then begin |
---|
817 | if (depth gt 8) then begin |
---|
818 | if (version ge 5.2) then device, get_decomposed=entry_decomposed else $ |
---|
819 | entry_decomposed = 0 |
---|
820 | if (true eq 1) or (channel gt 0) then device, decomposed=1 else $ |
---|
821 | device, decomposed=0 |
---|
822 | endif |
---|
823 | endif |
---|
824 | |
---|
825 | ;------------------------------------------------------------------------------- |
---|
826 | ;- DISPLAY THE IMAGE |
---|
827 | ;------------------------------------------------------------------------------- |
---|
828 | |
---|
829 | ;- If the display is 8-bit and the image is true color, |
---|
830 | ;- convert image from true color to indexed color |
---|
831 | if (depth le 8) and (true eq 1) then begin |
---|
832 | resized = color_quan(temporary(resized), 3, r, g, b, $ |
---|
833 | colors=ncolors, dither=keyword_set(dither)) + byte(bottom) |
---|
834 | tvlct, r, g, b, bottom |
---|
835 | true = 0 |
---|
836 | endif |
---|
837 | |
---|
838 | ;- Set channel value for supported devices |
---|
839 | if (!d.name eq 'WIN') or (!d.name eq 'MAC') or (!d.name eq 'X') then begin |
---|
840 | channel_value = channel |
---|
841 | endif else begin |
---|
842 | channel_value = 0 |
---|
843 | endelse |
---|
844 | |
---|
845 | ;- Display the image |
---|
846 | case true of |
---|
847 | 0 : tv, resized, x0, y0, order=order, channel=channel_value |
---|
848 | 1 : tv, resized, x0, y0, order=order, true=3 |
---|
849 | endcase |
---|
850 | |
---|
851 | ;------------------------------------------------------------------------------- |
---|
852 | ;- RESTORE THE DECOMPOSED COLOR MODE FOR 24-BIT DISPLAYS |
---|
853 | ;------------------------------------------------------------------------------- |
---|
854 | |
---|
855 | if ((!d.name eq 'WIN') or (!d.name eq 'MAC') or (!d.name eq 'X')) and $ |
---|
856 | (depth gt 8) then begin |
---|
857 | device, decomposed=entry_decomposed |
---|
858 | if (!d.name eq 'MAC') then tv, [0], -1, -1 |
---|
859 | endif |
---|
860 | |
---|
861 | ;------------------------------------------------------------------------------- |
---|
862 | ;- DRAW AXES IF REQUIRED |
---|
863 | ;------------------------------------------------------------------------------- |
---|
864 | |
---|
865 | if keyword_set(axis) then $ |
---|
866 | plot, [0], /nodata, /noerase, position=out_pos, $ |
---|
867 | xrange=xrange, xstyle=1, yrange=yrange, ystyle=1, $ |
---|
868 | _extra=extra_keywords |
---|
869 | |
---|
870 | END |
---|