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