[2] | 1 | ;+ |
---|
| 2 | ; |
---|
[231] | 3 | ; @file_comments |
---|
[133] | 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. |
---|
[2] | 13 | ; |
---|
[136] | 14 | ; (The 16 supported colors in GETCOLOR come from the McIDAS color |
---|
| 15 | ; table offered on the IDL newsgroup by Liam Gumley.) |
---|
[2] | 16 | ; |
---|
[231] | 17 | ; @categories |
---|
| 18 | ; Graphics, Color |
---|
[2] | 19 | ; |
---|
[327] | 20 | ; @param thiscolor {in}{optional} |
---|
[136] | 21 | ; A string with the "name" of the color. Valid names are: |
---|
[2] | 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 | ; |
---|
[137] | 39 | ; The color YELLOW is returned if the color name can't be resolved. |
---|
| 40 | ; Case is unimportant. |
---|
[2] | 41 | ; |
---|
[231] | 42 | ; @param index {in}{optional} |
---|
[136] | 43 | ; The color table index where the specified color should be loaded. |
---|
[2] | 44 | ; |
---|
[137] | 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: |
---|
[2] | 50 | ; |
---|
| 51 | ; Device, Decomposed=0 |
---|
| 52 | ; colors = GetColor() |
---|
| 53 | ; TVLCT, colors, 100 |
---|
| 54 | ; |
---|
[137] | 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 | ; |
---|
[231] | 70 | ; @keyword NAMES |
---|
[136] | 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. |
---|
[2] | 76 | ; |
---|
[136] | 77 | ; listID = Widget_List(baseID, Value=GetColor(/Names), YSize=16) |
---|
[2] | 78 | ; |
---|
[231] | 79 | ; @keyword LOAD |
---|
[136] | 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. |
---|
[2] | 91 | ; |
---|
[136] | 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 |
---|
[163] | 96 | ; IDL 5.2 and higher. |
---|
[2] | 97 | ; |
---|
[231] | 98 | ; @keyword TRUE |
---|
[136] | 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. |
---|
[2] | 105 | ; |
---|
[231] | 106 | ; @restrictions |
---|
[136] | 107 | ; The TRUE keyword causes the START keyword to be ignored. |
---|
[231] | 108 | ; The NAMES keyword causes the COLOR, INDEX, START, and TRUE parameters to be |
---|
[136] | 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. |
---|
[2] | 114 | ; |
---|
[231] | 115 | ; @examples |
---|
[371] | 116 | ; |
---|
[136] | 117 | ; To load a yellow color in color index 100 and plot in yellow, type: |
---|
[2] | 118 | ; |
---|
[371] | 119 | ; IDL> yellow = GETCOLOR('yellow', 100) |
---|
| 120 | ; IDL> PLOT, data, COLOR=yellow |
---|
[2] | 121 | ; |
---|
[137] | 122 | ; or, |
---|
[2] | 123 | ; |
---|
[371] | 124 | ; IDL> PLOT, data, COLOR=GETCOLOR('yellow', 100) |
---|
[2] | 125 | ; |
---|
[136] | 126 | ; To do the same thing on a 24-bit color system with decomposed color on, type: |
---|
[2] | 127 | ; |
---|
[371] | 128 | ; IDL> PLOT, data, COLOR=GETCOLOR('yellow', /TRUE) |
---|
[2] | 129 | ; |
---|
[137] | 130 | ; or in IDL 5.2 and higher, |
---|
[2] | 131 | ; |
---|
[371] | 132 | ; IDL> DEVICE, Decomposed=1 |
---|
| 133 | ; IDL> PLOT, data, COLOR=GETCOLOR('yellow') |
---|
[2] | 134 | ; |
---|
[136] | 135 | ; To load all 16 colors into the current color table, starting at |
---|
| 136 | ; color index 200, type: |
---|
[2] | 137 | ; |
---|
[371] | 138 | ; IDL> TVLCT, GETCOLOR(), 200 |
---|
[2] | 139 | ; |
---|
[136] | 140 | ; To add the color names to a list widget: |
---|
[2] | 141 | ; |
---|
[371] | 142 | ; IDL> listID = Widget_List(baseID, Value=GetColor(/Names), YSize=16) |
---|
[2] | 143 | ; |
---|
[137] | 144 | ; To load all 16 colors and have the color indices returned in a structure: |
---|
[2] | 145 | ; |
---|
[371] | 146 | ; IDL> DEVICE, Decomposed=0 |
---|
| 147 | ; IDL> colors = GetColor(/Load, Start=1) |
---|
| 148 | ; IDL> HELP, colors, /Structure |
---|
| 149 | ; IDL> PLOT, data, COLOR=colors.yellow |
---|
[2] | 150 | ; |
---|
[136] | 151 | ; To get the direct color values as 24-bit integers in color structure fields: |
---|
[2] | 152 | ; |
---|
[371] | 153 | ; IDL> DEVICE, Decomposed=1 |
---|
| 154 | ; IDL> colors = GetColor(/Load) |
---|
| 155 | ; IDL> PLOT, data, COLOR=colors.yellow |
---|
[133] | 156 | ; |
---|
[136] | 157 | ; Note that the START keyword value is ignored if on a 24-bit device, |
---|
| 158 | ; so it is possible to write completely device-independent code by |
---|
| 159 | ; writing code like this: |
---|
[133] | 160 | ; |
---|
[371] | 161 | ; IDL> colors = GetColor(/Load) |
---|
| 162 | ; IDL> PLOT, data, Color=colors.yellow; IDL> DEVICE, Decomposed=0 |
---|
| 163 | ; IDL> colors = GetColor(/Load, Start=1) |
---|
| 164 | ; IDL> HELP, colors, /Structure |
---|
| 165 | ; IDL> PLOT, data, COLOR=colors.yellow |
---|
[2] | 166 | ; |
---|
[136] | 167 | ; To get the direct color values as 24-bit integers in color structure fields: |
---|
[133] | 168 | ; |
---|
[371] | 169 | ; IDL> DEVICE, Decomposed=1 |
---|
| 170 | ; IDL> colors = GetColor(/Load) |
---|
| 171 | ; IDL> PLOT, data, COLOR=colors.yellow |
---|
[133] | 172 | ; |
---|
[136] | 173 | ; Note that the START keyword value is ignored if on a 24-bit device, |
---|
| 174 | ; so it is possible to write completely device-independent code by |
---|
| 175 | ; writing code like this: |
---|
[2] | 176 | ; |
---|
[371] | 177 | ; IDL> colors = GetColor(/Load) |
---|
| 178 | ; IDL> PLOT, data, Color=colors.yellow |
---|
[2] | 179 | ; |
---|
[231] | 180 | ; @history |
---|
[137] | 181 | ; Written by: David Fanning, 10 February 96. |
---|
| 182 | ; Fixed a bug in which N_ELEMENTS was spelled wrong. 7 Dec 96. DWF |
---|
| 183 | ; Added the McIDAS colors to the program. 24 Feb 99. DWF |
---|
| 184 | ; Added the INDEX parameter to the program 8 Mar 99. DWF |
---|
| 185 | ; Added the NAMES keyword at insistence of Martin Schultz. 10 Mar 99. DWF |
---|
[163] | 186 | ; Reordered the colors so black is first and white is last. 7 June 99. DWF |
---|
[137] | 187 | ; Added automatic recognition of DECOMPOSED=1 state. 7 June 99. DWF |
---|
| 188 | ; Added LOAD AND START keywords. 7 June 99. DWF. |
---|
[133] | 189 | ; |
---|
[231] | 190 | ; @version |
---|
| 191 | ; $Id$ |
---|
[327] | 192 | ; |
---|
[2] | 193 | ;- |
---|
[327] | 194 | FUNCTION getcolor, thiscolor, index, TRUE=truecolor $ |
---|
| 195 | , NAMES=colornames, LOAD=load, START=start |
---|
[114] | 196 | ; |
---|
| 197 | compile_opt idl2, strictarrsubs |
---|
| 198 | ; |
---|
[2] | 199 | |
---|
| 200 | ; Set up the color vectors. |
---|
| 201 | |
---|
| 202 | names = ['Black', 'Magenta', 'Cyan', 'Yellow', 'Green'] |
---|
| 203 | rvalue = [ 0, 255, 0, 255, 0 ] |
---|
| 204 | gvalue = [ 0, 0, 255, 255, 255 ] |
---|
| 205 | bvalue = [ 0, 255, 255, 0, 0 ] |
---|
| 206 | names = [names, 'Red', 'Blue', 'Navy', 'Gold', 'Pink'] |
---|
| 207 | rvalue = [rvalue, 255, 0, 0, 255, 255 ] |
---|
| 208 | gvalue = [gvalue, 0, 0, 0, 187, 127 ] |
---|
| 209 | bvalue = [bvalue, 0, 255, 115, 0, 127 ] |
---|
| 210 | names = [names, 'Aqua', 'Orchid', 'Gray', 'Sky', 'Beige', 'White'] |
---|
| 211 | rvalue = [rvalue, 112, 219, 127, 0, 255, 255 ] |
---|
| 212 | gvalue = [gvalue, 219, 112, 127, 163, 171, 255 ] |
---|
| 213 | bvalue = [bvalue, 147, 219, 127, 255, 127, 255 ] |
---|
| 214 | |
---|
| 215 | ; Did the user ask for a specific color? If not, return |
---|
| 216 | ; all the colors. If the user asked for a specific color, |
---|
| 217 | ; find out if a 24-bit value is required. Return to main |
---|
| 218 | ; IDL level if an error occurs. |
---|
| 219 | |
---|
| 220 | ON_Error, 1 |
---|
| 221 | np = N_Params() |
---|
| 222 | IF Keyword_Set(start) EQ 0 THEN start = !D.TABLE_SIZE - 17 |
---|
| 223 | |
---|
| 224 | ; User ask for the color names? |
---|
| 225 | |
---|
| 226 | IF Keyword_Set(colornames) THEN RETURN, names ELSE names = StrUpCase(names) |
---|
| 227 | |
---|
| 228 | ; If no positional parameter, return all colors. |
---|
| 229 | |
---|
| 230 | IF np EQ 0 THEN BEGIN |
---|
| 231 | |
---|
| 232 | ; Did the user want a 24-bit value? If so, call COLOR24. |
---|
| 233 | |
---|
| 234 | IF Keyword_Set(trueColor) THEN BEGIN |
---|
| 235 | returnColor = LonArr(16) |
---|
| 236 | FOR j=0,15 DO returnColor[j] = Color24([rvalue[j], gvalue[j], bvalue[j]]) |
---|
| 237 | |
---|
| 238 | ; If LOAD keyword set, return a color structure. |
---|
| 239 | |
---|
| 240 | IF Keyword_Set(load) THEN BEGIN |
---|
| 241 | returnValue = Create_Struct('black', returnColor[0]) |
---|
| 242 | FOR j=1,15 DO returnValue = Create_Struct(returnValue, names[j], returnColor[j]) |
---|
| 243 | returnColor = returnValue |
---|
| 244 | ENDIF |
---|
| 245 | |
---|
| 246 | RETURN, returnColor |
---|
| 247 | ENDIF |
---|
| 248 | |
---|
| 249 | ; If color decomposition is ON, return 24-bit values. |
---|
| 250 | |
---|
| 251 | IF Float(!Version.Release) GE 5.2 THEN BEGIN |
---|
| 252 | IF (!D.Name EQ 'X' OR !D.Name EQ 'WIN' OR !D.Name EQ 'MAC') THEN BEGIN |
---|
| 253 | Device, Get_Decomposed=decomposedState |
---|
| 254 | ENDIF ELSE decomposedState = 0 |
---|
| 255 | IF decomposedState EQ 1 THEN BEGIN |
---|
| 256 | returnColor = LonArr(16) |
---|
| 257 | FOR j=0,15 DO returnColor[j] = Color24([rvalue[j], gvalue[j], bvalue[j]]) |
---|
| 258 | IF Keyword_Set(load) THEN BEGIN |
---|
| 259 | returnValue = Create_Struct('black', returnColor[0]) |
---|
| 260 | FOR j=1,15 DO returnValue = Create_Struct(returnValue, names[j], returnColor[j]) |
---|
| 261 | RETURN, returnValue |
---|
| 262 | ENDIF |
---|
| 263 | RETURN, returnColor |
---|
| 264 | ENDIF |
---|
| 265 | |
---|
| 266 | IF Keyword_Set(load) THEN BEGIN |
---|
| 267 | TVLCT, Reform([rvalue, gvalue, bvalue], 16, 3), start |
---|
| 268 | returnValue = Create_Struct('black', start) |
---|
| 269 | FOR j=1,15 DO returnValue = Create_Struct(returnValue, names[j], start+j) |
---|
| 270 | RETURN, returnValue |
---|
| 271 | ENDIF |
---|
| 272 | |
---|
| 273 | returnColor = REFORM([rvalue, gvalue, bvalue], 16, 3) |
---|
| 274 | RETURN, returnColor |
---|
| 275 | |
---|
| 276 | ENDIF |
---|
| 277 | |
---|
| 278 | IF Keyword_Set(load) THEN BEGIN |
---|
| 279 | TVLCT, Reform([rvalue, gvalue, bvalue], 16, 3), start |
---|
| 280 | returnValue = Create_Struct('black', start) |
---|
| 281 | FOR j=1,15 DO returnValue = Create_Struct(returnValue, names[j], start+j) |
---|
| 282 | RETURN, returnValue |
---|
| 283 | ENDIF |
---|
| 284 | |
---|
| 285 | returnColor = REFORM([rvalue, gvalue, bvalue], 16, 3) |
---|
| 286 | RETURN, returnColor |
---|
| 287 | |
---|
| 288 | ENDIF |
---|
| 289 | |
---|
| 290 | ; Check synonyms of colors. |
---|
| 291 | |
---|
| 292 | IF StrUpCase(thisColor) EQ 'GREY' THEN thisColor = 'GRAY' |
---|
| 293 | IF StrUpCase(thisColor) EQ 'CHARCOAL' THEN thisColor = 'GRAY' |
---|
| 294 | IF StrUpCase(thisColor) EQ 'AQUAMARINE' THEN thisColor = 'AQUA' |
---|
| 295 | IF StrUpCase(thisColor) EQ 'SKYBLUE' THEN thisColor = 'SKY' |
---|
| 296 | |
---|
| 297 | ; Make sure the parameter is an uppercase string. |
---|
| 298 | |
---|
| 299 | varInfo = SIZE(thisColor) |
---|
[114] | 300 | IF varInfo[varInfo[0] + 1] NE 7 THEN $ |
---|
[242] | 301 | ras = report('The color name must be a string.') |
---|
[2] | 302 | thisColor = STRUPCASE(thisColor) |
---|
| 303 | |
---|
| 304 | ; Get the color triple for this color. |
---|
| 305 | |
---|
| 306 | colorIndex = WHERE(names EQ thisColor) |
---|
| 307 | |
---|
[136] | 308 | ; If you can't find it. Issue an informational message, |
---|
[2] | 309 | ; set the index to a YELLOW color, and continue. |
---|
| 310 | |
---|
[114] | 311 | IF colorIndex[0] LT 0 THEN BEGIN |
---|
[242] | 312 | ras= report("Can't find color. Returning YELLOW.", /INFORMATIONAL) |
---|
[2] | 313 | colorIndex = 3 |
---|
| 314 | ENDIF |
---|
| 315 | |
---|
| 316 | ; Get the color triple. |
---|
| 317 | |
---|
[114] | 318 | r = rvalue[colorIndex] |
---|
| 319 | g = gvalue[colorIndex] |
---|
| 320 | b = bvalue[colorIndex] |
---|
[2] | 321 | returnColor = REFORM([r, g, b], 1, 3) |
---|
| 322 | |
---|
| 323 | ; Did the user want a 24-bit value? If so, call COLOR24. |
---|
| 324 | |
---|
| 325 | IF KEYWORD_SET(trueColor) THEN BEGIN |
---|
| 326 | returnColor = COLOR24(returnColor) |
---|
| 327 | RETURN, returnColor |
---|
| 328 | ENDIF |
---|
| 329 | |
---|
| 330 | ; If color decomposition is ON, return 24-bit value. |
---|
| 331 | |
---|
| 332 | IF Float(!Version.Release) GE 5.2 THEN BEGIN |
---|
| 333 | |
---|
| 334 | IF (!D.Name EQ 'X' OR !D.Name EQ 'WIN' OR !D.Name EQ 'MAC') THEN BEGIN |
---|
| 335 | Device, Get_Decomposed=decomposedState |
---|
| 336 | ENDIF ELSE decomposedState = 0 |
---|
| 337 | |
---|
| 338 | IF decomposedState EQ 1 THEN BEGIN |
---|
| 339 | |
---|
| 340 | ; Before you change return color, load index if requested. |
---|
| 341 | |
---|
| 342 | IF N_Elements(index) NE 0 THEN BEGIN |
---|
| 343 | index = 0 > index < (!D.Table_Size-1) |
---|
| 344 | TVLCT, returnColor, index |
---|
| 345 | ENDIF |
---|
| 346 | |
---|
| 347 | returnColor = COLOR24(returnColor) |
---|
| 348 | RETURN, returnColor |
---|
| 349 | ENDIF |
---|
| 350 | ENDIF |
---|
| 351 | |
---|
| 352 | ; Did the user specify a color index? If so, load it. |
---|
| 353 | |
---|
| 354 | IF N_Elements(index) NE 0 THEN BEGIN |
---|
| 355 | index = 0 > index < (!D.Table_Size-1) |
---|
| 356 | TVLCT, returnColor, index |
---|
| 357 | returnColor = index |
---|
| 358 | ENDIF |
---|
| 359 | |
---|
| 360 | RETURN, returnColor |
---|
| 361 | END |
---|