1 | ;+ |
---|
2 | ; |
---|
3 | ; @file_comments |
---|
4 | ; The original purpose of this function was to enable the |
---|
5 | ; user to specify one of the 16 colors supported by the |
---|
6 | ; McIDAS color map by name. Over time, however, the function |
---|
7 | ; has become a general purpose function for handling and |
---|
8 | ; supporting drawing colors in a device-independent way. |
---|
9 | ; In particular, I have been looking for ways to write color |
---|
10 | ; handling code that will work transparently on both 8-bit and |
---|
11 | ; 24-bit machines. On 24-bit machines, the code should work the |
---|
12 | ; same where color decomposition is turned on or off. |
---|
13 | ; |
---|
14 | ; (The 16 supported colors in GETCOLOR come from the McIDAS color |
---|
15 | ; table offered on the IDL newsgroup by Liam Gumley.) |
---|
16 | ; |
---|
17 | ; @categories |
---|
18 | ; Graphics, Color |
---|
19 | ; |
---|
20 | ; @param thiscolor {in}{optional} |
---|
21 | ; A string with the "name" of the color. Valid names are: |
---|
22 | ; black |
---|
23 | ; magenta |
---|
24 | ; cyan |
---|
25 | ; yellow |
---|
26 | ; green |
---|
27 | ; red |
---|
28 | ; blue |
---|
29 | ; navy |
---|
30 | ; gold |
---|
31 | ; pink |
---|
32 | ; aqua |
---|
33 | ; orchid |
---|
34 | ; gray |
---|
35 | ; sky |
---|
36 | ; beige |
---|
37 | ; white |
---|
38 | ; |
---|
39 | ; The color YELLOW is returned if the color name can't be resolved. |
---|
40 | ; Case is unimportant. |
---|
41 | ; |
---|
42 | ; @param index {in}{optional} |
---|
43 | ; The color table index where the specified color should be loaded. |
---|
44 | ; |
---|
45 | ; @returns |
---|
46 | ; If no positional parameter is present, then the return value is either a 16-by-3 |
---|
47 | ; byte array containing the RGB values of all 16 colors or it is a 16-element |
---|
48 | ; long integer array containing color values that can be decomposed into colors. |
---|
49 | ; The 16-by-3 array is appropriate for loading color tables with the TVLCT command: |
---|
50 | ; |
---|
51 | ; Device, Decomposed=0 |
---|
52 | ; colors = GetColor() |
---|
53 | ; TVLCT, colors, 100 |
---|
54 | ; |
---|
55 | ; If function is called with just this single input parameter, |
---|
56 | ; the return value is either a 1-by-3 array containing the RGB values of |
---|
57 | ; that particular color, or a 24-bit integer that can be "decomposed" into |
---|
58 | ; that particular color, depending upon the state of the TRUE keyword and |
---|
59 | ; upon whether color decomposition is turned on or off. The state of color |
---|
60 | ; decomposition can ONLY be determined if the program is being run in |
---|
61 | ; IDL 5.2 or higher. |
---|
62 | ; |
---|
63 | ; If index parameter is passed, then the return value of the function is the |
---|
64 | ; index number and not the color triple. (If color decomposition is turned |
---|
65 | ; on AND the user specifies an index parameter, the color is loaded in the |
---|
66 | ; color table at the proper index, but a 24-bit value is returned to the |
---|
67 | ; user in IDL 5.2 and higher.) |
---|
68 | ; |
---|
69 | ; |
---|
70 | ; @keyword NAMES |
---|
71 | ; If this keyword is set, the return value of the function is |
---|
72 | ; a 16-element string array containing the names of the colors. |
---|
73 | ; These names would be appropriate, for example, in building |
---|
74 | ; a list widget with the names of the colors. If the NAMES |
---|
75 | ; keyword is set, the COLOR and INDEX parameters are ignored. |
---|
76 | ; |
---|
77 | ; listID = Widget_List(baseID, Value=GetColor(/Names), YSize=16) |
---|
78 | ; |
---|
79 | ; @keyword LOAD |
---|
80 | ; If this keyword is set, all 16 colors are automatically loaded |
---|
81 | ; starting at the color index specified by the START keyword. |
---|
82 | ; Note that setting this keyword means that the return value of the |
---|
83 | ; function will be a structure, with each field of the structure |
---|
84 | ; corresponding to a color name. The value of each field will be |
---|
85 | ; an index number (set by the START keyword) corresponding to the |
---|
86 | ; associated color, or a 24-bit long integer value that creates the |
---|
87 | ; color on a true-color device. What you have as the field values is |
---|
88 | ; determined by the TRUE keyword or whether color decomposition is on |
---|
89 | ; or off in the absence of the TRUE keyword. It will either be a 1-by-3 |
---|
90 | ; byte array or a long integer value. |
---|
91 | ; |
---|
92 | ; @keyword START {default=!D.TABLE_SIZE - 17} |
---|
93 | ; The starting color index number if the LOAD keyword is set. This keyword |
---|
94 | ; value is ignored unless the LOAD keyword is also set. The keyword is also |
---|
95 | ; ignored if the TRUE keyword is set or if color decomposition in on in |
---|
96 | ; IDL 5.2 and higher. |
---|
97 | ; |
---|
98 | ; @keyword TRUE |
---|
99 | ; If this keyword is set, the specified color triple is returned |
---|
100 | ; as a 24-bit integer equivalent. The lowest 8 bits correspond to |
---|
101 | ; the red value; the middle 8 bits to the green value; and the |
---|
102 | ; highest 8 bits correspond to the blue value. In IDL 5.2 and higher, |
---|
103 | ; if color decomposition is turned on, it is as though this keyword |
---|
104 | ; were set. |
---|
105 | ; |
---|
106 | ; @restrictions |
---|
107 | ; The TRUE keyword causes the START keyword to be ignored. |
---|
108 | ; The NAMES keyword causes the COLOR, INDEX, START, and TRUE parameters to be |
---|
109 | ; ignored. |
---|
110 | ; The COLOR parameter is ignored if the LOAD keyword is used. |
---|
111 | ; On systems where it is possible to tell the state of color decomposition |
---|
112 | ; (i.e., IDL 5.2 and higher), a 24-bit value (or values) is automatically |
---|
113 | ; returned if color decomposition is ON. |
---|
114 | ; |
---|
115 | ; @examples |
---|
116 | ; To load a yellow color in color index 100 and plot in yellow, type: |
---|
117 | ; |
---|
118 | ; IDL> yellow = GETCOLOR('yellow', 100) |
---|
119 | ; IDL> PLOT, data, COLOR=yellow |
---|
120 | ; |
---|
121 | ; or, |
---|
122 | ; |
---|
123 | ; IDL> PLOT, data, COLOR=GETCOLOR('yellow', 100) |
---|
124 | ; |
---|
125 | ; To do the same thing on a 24-bit color system with decomposed color on, type: |
---|
126 | ; |
---|
127 | ; IDL> PLOT, data, COLOR=GETCOLOR('yellow', /TRUE) |
---|
128 | ; |
---|
129 | ; or in IDL 5.2 and higher, |
---|
130 | ; |
---|
131 | ; IDL> DEVICE, Decomposed=1 |
---|
132 | ; IDL> PLOT, data, COLOR=GETCOLOR('yellow') |
---|
133 | ; |
---|
134 | ; To load all 16 colors into the current color table, starting at |
---|
135 | ; color index 200, type: |
---|
136 | ; |
---|
137 | ; IDL> TVLCT, GETCOLOR(), 200 |
---|
138 | ; |
---|
139 | ; To add the color names to a list widget: |
---|
140 | ; |
---|
141 | ; IDL> listID = Widget_List(baseID, Value=GetColor(/Names), YSize=16) |
---|
142 | ; |
---|
143 | ; To load all 16 colors and have the color indices returned in a structure: |
---|
144 | ; |
---|
145 | ; IDL> DEVICE, Decomposed=0 |
---|
146 | ; IDL> colors = GetColor(/Load, Start=1) |
---|
147 | ; IDL> HELP, colors, /Structure |
---|
148 | ; PLOT, data, COLOR=colors.yellow |
---|
149 | ; |
---|
150 | ; To get the direct color values as 24-bit integers in color structure fields: |
---|
151 | ; |
---|
152 | ; IDL> DEVICE, Decomposed=1 |
---|
153 | ; IDL> colors = GetColor(/Load) |
---|
154 | ; IDL> PLOT, data, COLOR=colors.yellow |
---|
155 | ; |
---|
156 | ; Note that the START keyword value is ignored if on a 24-bit device, |
---|
157 | ; so it is possible to write completely device-independent code by |
---|
158 | ; writing code like this: |
---|
159 | ; |
---|
160 | ; IDL> colors = GetColor(/Load) |
---|
161 | ; IDL> PLOT, data, Color=colors.yellow; IDL> DEVICE, Decomposed=0 |
---|
162 | ; IDL> colors = GetColor(/Load, Start=1) |
---|
163 | ; IDL> HELP, colors, /Structure |
---|
164 | ; PLOT, data, COLOR=colors.yellow |
---|
165 | ; |
---|
166 | ; To get the direct color values as 24-bit integers in color structure fields: |
---|
167 | ; |
---|
168 | ; IDL> DEVICE, Decomposed=1 |
---|
169 | ; IDL> colors = GetColor(/Load) |
---|
170 | ; IDL> PLOT, data, COLOR=colors.yellow |
---|
171 | ; |
---|
172 | ; Note that the START keyword value is ignored if on a 24-bit device, |
---|
173 | ; so it is possible to write completely device-independent code by |
---|
174 | ; writing code like this: |
---|
175 | ; |
---|
176 | ; IDL> colors = GetColor(/Load) |
---|
177 | ; IDL> PLOT, data, Color=colors.yellow |
---|
178 | ; |
---|
179 | ; @history |
---|
180 | ; Written by: David Fanning, 10 February 96. |
---|
181 | ; Fixed a bug in which N_ELEMENTS was spelled wrong. 7 Dec 96. DWF |
---|
182 | ; Added the McIDAS colors to the program. 24 Feb 99. DWF |
---|
183 | ; Added the INDEX parameter to the program 8 Mar 99. DWF |
---|
184 | ; Added the NAMES keyword at insistence of Martin Schultz. 10 Mar 99. DWF |
---|
185 | ; Reordered the colors so black is first and white is last. 7 June 99. DWF |
---|
186 | ; Added automatic recognition of DECOMPOSED=1 state. 7 June 99. DWF |
---|
187 | ; Added LOAD AND START keywords. 7 June 99. DWF. |
---|
188 | ; |
---|
189 | ; @version |
---|
190 | ; $Id$ |
---|
191 | ; |
---|
192 | ;- |
---|
193 | FUNCTION getcolor, thiscolor, index, TRUE=truecolor $ |
---|
194 | , NAMES=colornames, LOAD=load, START=start |
---|
195 | ; |
---|
196 | compile_opt idl2, strictarrsubs |
---|
197 | ; |
---|
198 | |
---|
199 | ; Set up the color vectors. |
---|
200 | |
---|
201 | names = ['Black', 'Magenta', 'Cyan', 'Yellow', 'Green'] |
---|
202 | rvalue = [ 0, 255, 0, 255, 0 ] |
---|
203 | gvalue = [ 0, 0, 255, 255, 255 ] |
---|
204 | bvalue = [ 0, 255, 255, 0, 0 ] |
---|
205 | names = [names, 'Red', 'Blue', 'Navy', 'Gold', 'Pink'] |
---|
206 | rvalue = [rvalue, 255, 0, 0, 255, 255 ] |
---|
207 | gvalue = [gvalue, 0, 0, 0, 187, 127 ] |
---|
208 | bvalue = [bvalue, 0, 255, 115, 0, 127 ] |
---|
209 | names = [names, 'Aqua', 'Orchid', 'Gray', 'Sky', 'Beige', 'White'] |
---|
210 | rvalue = [rvalue, 112, 219, 127, 0, 255, 255 ] |
---|
211 | gvalue = [gvalue, 219, 112, 127, 163, 171, 255 ] |
---|
212 | bvalue = [bvalue, 147, 219, 127, 255, 127, 255 ] |
---|
213 | |
---|
214 | ; Did the user ask for a specific color? If not, return |
---|
215 | ; all the colors. If the user asked for a specific color, |
---|
216 | ; find out if a 24-bit value is required. Return to main |
---|
217 | ; IDL level if an error occurs. |
---|
218 | |
---|
219 | ON_Error, 1 |
---|
220 | np = N_Params() |
---|
221 | IF Keyword_Set(start) EQ 0 THEN start = !D.TABLE_SIZE - 17 |
---|
222 | |
---|
223 | ; User ask for the color names? |
---|
224 | |
---|
225 | IF Keyword_Set(colornames) THEN RETURN, names ELSE names = StrUpCase(names) |
---|
226 | |
---|
227 | ; If no positional parameter, return all colors. |
---|
228 | |
---|
229 | IF np EQ 0 THEN BEGIN |
---|
230 | |
---|
231 | ; Did the user want a 24-bit value? If so, call COLOR24. |
---|
232 | |
---|
233 | IF Keyword_Set(trueColor) THEN BEGIN |
---|
234 | returnColor = LonArr(16) |
---|
235 | FOR j=0,15 DO returnColor[j] = Color24([rvalue[j], gvalue[j], bvalue[j]]) |
---|
236 | |
---|
237 | ; If LOAD keyword set, return a color structure. |
---|
238 | |
---|
239 | IF Keyword_Set(load) THEN BEGIN |
---|
240 | returnValue = Create_Struct('black', returnColor[0]) |
---|
241 | FOR j=1,15 DO returnValue = Create_Struct(returnValue, names[j], returnColor[j]) |
---|
242 | returnColor = returnValue |
---|
243 | ENDIF |
---|
244 | |
---|
245 | RETURN, returnColor |
---|
246 | ENDIF |
---|
247 | |
---|
248 | ; If color decomposition is ON, return 24-bit values. |
---|
249 | |
---|
250 | IF Float(!Version.Release) GE 5.2 THEN BEGIN |
---|
251 | IF (!D.Name EQ 'X' OR !D.Name EQ 'WIN' OR !D.Name EQ 'MAC') THEN BEGIN |
---|
252 | Device, Get_Decomposed=decomposedState |
---|
253 | ENDIF ELSE decomposedState = 0 |
---|
254 | IF decomposedState EQ 1 THEN BEGIN |
---|
255 | returnColor = LonArr(16) |
---|
256 | FOR j=0,15 DO returnColor[j] = Color24([rvalue[j], gvalue[j], bvalue[j]]) |
---|
257 | IF Keyword_Set(load) THEN BEGIN |
---|
258 | returnValue = Create_Struct('black', returnColor[0]) |
---|
259 | FOR j=1,15 DO returnValue = Create_Struct(returnValue, names[j], returnColor[j]) |
---|
260 | RETURN, returnValue |
---|
261 | ENDIF |
---|
262 | RETURN, returnColor |
---|
263 | ENDIF |
---|
264 | |
---|
265 | IF Keyword_Set(load) THEN BEGIN |
---|
266 | TVLCT, Reform([rvalue, gvalue, bvalue], 16, 3), start |
---|
267 | returnValue = Create_Struct('black', start) |
---|
268 | FOR j=1,15 DO returnValue = Create_Struct(returnValue, names[j], start+j) |
---|
269 | RETURN, returnValue |
---|
270 | ENDIF |
---|
271 | |
---|
272 | returnColor = REFORM([rvalue, gvalue, bvalue], 16, 3) |
---|
273 | RETURN, returnColor |
---|
274 | |
---|
275 | ENDIF |
---|
276 | |
---|
277 | IF Keyword_Set(load) THEN BEGIN |
---|
278 | TVLCT, Reform([rvalue, gvalue, bvalue], 16, 3), start |
---|
279 | returnValue = Create_Struct('black', start) |
---|
280 | FOR j=1,15 DO returnValue = Create_Struct(returnValue, names[j], start+j) |
---|
281 | RETURN, returnValue |
---|
282 | ENDIF |
---|
283 | |
---|
284 | returnColor = REFORM([rvalue, gvalue, bvalue], 16, 3) |
---|
285 | RETURN, returnColor |
---|
286 | |
---|
287 | ENDIF |
---|
288 | |
---|
289 | ; Check synonyms of colors. |
---|
290 | |
---|
291 | IF StrUpCase(thisColor) EQ 'GREY' THEN thisColor = 'GRAY' |
---|
292 | IF StrUpCase(thisColor) EQ 'CHARCOAL' THEN thisColor = 'GRAY' |
---|
293 | IF StrUpCase(thisColor) EQ 'AQUAMARINE' THEN thisColor = 'AQUA' |
---|
294 | IF StrUpCase(thisColor) EQ 'SKYBLUE' THEN thisColor = 'SKY' |
---|
295 | |
---|
296 | ; Make sure the parameter is an uppercase string. |
---|
297 | |
---|
298 | varInfo = SIZE(thisColor) |
---|
299 | IF varInfo[varInfo[0] + 1] NE 7 THEN $ |
---|
300 | ras = report('The color name must be a string.') |
---|
301 | thisColor = STRUPCASE(thisColor) |
---|
302 | |
---|
303 | ; Get the color triple for this color. |
---|
304 | |
---|
305 | colorIndex = WHERE(names EQ thisColor) |
---|
306 | |
---|
307 | ; If you can't find it. Issue an informational message, |
---|
308 | ; set the index to a YELLOW color, and continue. |
---|
309 | |
---|
310 | IF colorIndex[0] LT 0 THEN BEGIN |
---|
311 | ras= report("Can't find color. Returning YELLOW.", /INFORMATIONAL) |
---|
312 | colorIndex = 3 |
---|
313 | ENDIF |
---|
314 | |
---|
315 | ; Get the color triple. |
---|
316 | |
---|
317 | r = rvalue[colorIndex] |
---|
318 | g = gvalue[colorIndex] |
---|
319 | b = bvalue[colorIndex] |
---|
320 | returnColor = REFORM([r, g, b], 1, 3) |
---|
321 | |
---|
322 | ; Did the user want a 24-bit value? If so, call COLOR24. |
---|
323 | |
---|
324 | IF KEYWORD_SET(trueColor) THEN BEGIN |
---|
325 | returnColor = COLOR24(returnColor) |
---|
326 | RETURN, returnColor |
---|
327 | ENDIF |
---|
328 | |
---|
329 | ; If color decomposition is ON, return 24-bit value. |
---|
330 | |
---|
331 | IF Float(!Version.Release) GE 5.2 THEN BEGIN |
---|
332 | |
---|
333 | IF (!D.Name EQ 'X' OR !D.Name EQ 'WIN' OR !D.Name EQ 'MAC') THEN BEGIN |
---|
334 | Device, Get_Decomposed=decomposedState |
---|
335 | ENDIF ELSE decomposedState = 0 |
---|
336 | |
---|
337 | IF decomposedState EQ 1 THEN BEGIN |
---|
338 | |
---|
339 | ; Before you change return color, load index if requested. |
---|
340 | |
---|
341 | IF N_Elements(index) NE 0 THEN BEGIN |
---|
342 | index = 0 > index < (!D.Table_Size-1) |
---|
343 | TVLCT, returnColor, index |
---|
344 | ENDIF |
---|
345 | |
---|
346 | returnColor = COLOR24(returnColor) |
---|
347 | RETURN, returnColor |
---|
348 | ENDIF |
---|
349 | ENDIF |
---|
350 | |
---|
351 | ; Did the user specify a color index? If so, load it. |
---|
352 | |
---|
353 | IF N_Elements(index) NE 0 THEN BEGIN |
---|
354 | index = 0 > index < (!D.Table_Size-1) |
---|
355 | TVLCT, returnColor, index |
---|
356 | returnColor = index |
---|
357 | ENDIF |
---|
358 | |
---|
359 | RETURN, returnColor |
---|
360 | END |
---|