;+
; NAME:
; FSC_COLOR
;
; PURPOSE:
;
; The purpose of this function is to obtain drawing colors
; by name and in a device/decomposition independent way. The
; color names and values may be read in as a file, or 88
; color names and values are supplied from the program. These
; were obtained from the file rgb.txt, found on most X-Window
; distributions. Representative colors were chose from across
; the color spectrum. To see a list of colors available, type:
; Print, FSC_Color(/Names), Format='(6A15)'.
;
; AUTHOR:
;
; FANNING SOFTWARE CONSULTING:
; David Fanning, Ph.D.
; 1645 Sheely Drive
; Fort Collins, CO 80526 USA
; Phone: 970-221-0438
; E-mail: davidf@dfanning.com
; Coyote's Guide to IDL Programming: http://www.dfanning.com
;
; CATEGORY:
;
; Graphics, Color Specification.
;
; CALLING SEQUENCE:
;
; color = FSC_COLOR(theColor, theColorIndex)
;
; NORMAL CALLING SEQUENCE FOR DEVICE-INDEPENDENT COLOR:
;
; If you write your graphics code *exactly* as it is written below, then
; the same code will work in all graphics devices I have tested.
; These include the PRINTER, PS, and Z devices, as well as X, WIN, and MAC.
;
; In practice, graphics code is seldom written like this. (For a variety of
; reasons, but laziness is high on the list.) So I have made the
; program reasonably tolerant of poor programming practices. I just
; point this out as a place you might return to before you write me
; a nice note saying my program "doesn't work". :-)
;
; axisColor = FSC_COLOR("Green", !D.Table_Size-2)
; backColor = FSC_COLOR("Charcoal", !D.Table_Size-3)
; dataColor = FSC_COLOR("Yellow", !D.Table_Size-4)
; thisDevice = !D.Name
; Set_Plot, 'toWhateverYourDeviceIsGoingToBe', /Copy
; Device, .... ; Whatever you need here to set things up properly.
; IF (!D.Flags AND 256) EQ 0 THEN $
; POLYFILL, [0,1,1,0,0], [0,0,1,1,0], /Normal, Color=backColor
; Plot, Findgen(11), Color=axisColor, Background=backColor, /NoData, $
; NoErase= ((!D.Flags AND 256) EQ 0)
; OPlot, Findgen(11), Color=dataColor
; Device, .... ; Whatever you need here to wrap things up properly.
; Set_Plot, thisDevice
;
; OPTIONAL INPUT PARAMETERS:
;
; theColor: A string with the "name" of the color. To see a list
; of the color names available set the NAMES keyword. This may
; also be a vector of color names. Colors available are these:
;
; Almond Antique White Aquamarine Beige Bisque Black
; Blue Blue Violet Brown Burlywood Charcoal Chartreuse
; Chocolate Coral Cornsilk Cyan Dark Goldenrod Dark Gray
; Dark Green Dark Khaki Dark Orchid Dark Salmon Deep Pink Dodger Blue
; Firebrick Forest Green Gold Goldenrod Gray Green
; Green Yellow Honeydew Hot Pink Indian Red Ivory Khaki
; Lavender Lawn Green Light Coral Light Cyan Light Gray Light Salmon
; Light Yellow Lime Green Linen Magenta Maroon Medium Gray
; Medium Orchid Moccasin Navy Olive Olive Drab Orange
; Orange Red Orchid Pale Goldenrod Pale Green Papaya Peru
; Pink Plum Powder Blue Purple Red Rose
; Rosy Brown Royal Blue Saddle Brown Salmon Sandy Brown Sea Green
; Seashell Sienna Sky Blue Slate Gray Snow Spring Green
; Steel Blue Tan Thistle Tomato Turquoise Violet
; Violet Red Wheat White Yellow
;
; Also, these system color names are available in IDL 5.6 and higher: Frame, Text, Active,
; Shadow, Highlight, Edge, Selected, Face.
;
; The color WHITE is used if this parameter is absent or a color name is mis-spelled. To see a list
; of the color names available in the program, type this:
;
; Print, FSC_COLOR(/Names), Format='(6A15)'
;
; theColorIndex: The color table index (or vector of indices the same length
; as the color name vector) where the specified color is loaded. The color table
; index parameter should always be used if you wish to obtain a color value in a
; color-decomposition-independent way in your code. See the NORMAL CALLING
; SEQUENCE for details. If theColor is a vector, and theColorIndex is a scalar,
; then the colors will be loaded starting at theColorIndex.
;
; RETURN VALUE:
;
; The value that is returned by FSC_COLOR depends upon the keywords
; used to call it, on the version of IDL you are using,and on the depth
; of the display device when the program is invoked. In general,
; the return value will be either a color index number where the specified
; color is loaded by the program, or a 24-bit color value that can be
; decomposed into the specified color on true-color systems. (Or a vector
; of such numbers.)
;
; If you are running IDL 5.2 or higher, the program will determine which
; return value to use, based on the color decomposition state at the time
; the program is called. If you are running a version of IDL before IDL 5.2,
; then the program will return the color index number. This behavior can
; be overruled in all versions of IDL by setting the DECOMPOSED keyword.
; If this keyword is 0, the program always returns a color index number. If
; the keyword is 1, the program always returns a 24-bit color value.
;
; If the TRIPLE keyword is set, the program always returns the color triple,
; no matter what the current decomposition state or the value of the DECOMPOSED
; keyword. Normally, the color triple is returned as a 1 by 3 column vector.
; This is appropriate for loading into a color index with TVLCT:
;
; IDL> TVLCT, FSC_Color('Yellow', /Triple), !P.Color
;
; But sometimes (e.g, in object graphics applications) you want the color
; returned as a row vector. In this case, you should set the ROW keyword
; as well as the TRIPLE keyword:
;
; viewobj= Obj_New('IDLgrView', Color=FSC_Color('charcoal', /Triple, /Row))
;
; If the ALLCOLORS keyword is used, then instead of a single value, modified
; as described above, then all the color values are returned in an array. In
; other words, the return value will be either an NCOLORS-element vector of color
; table index numbers, an NCOLORS-element vector of 24-bit color values, or
; an NCOLORS-by-3 array of color triples.
;
; If the NAMES keyword is set, the program returns a vector of
; color names known to the program.
;
; If the color index parameter is not used, and a 24-bit value is not being
; returned, then colorIndex is typically set to !D.Table_Size-1. However,
; this behavior is changed on 8-bit devices (e.g., the PostScript device,
; or the Z-graphics buffer) and on 24-bit devices that are *not* using
; decomposed color. On these devices, the colors are loaded at an
; offset of !D.Table_Size - ncolors - 2, and the color index parameter reflects
; the actual index of the color where it will be loaded. This makes it possible
; to use a formulation as below:
;
; Plot, data, Color=FSC_Color('Dodger Blue')
;
; on 24-bit displays *and* in PostScript output! Note that if you specify a color
; index (the safest thing to do), then it will always be honored.
;
; INPUT KEYWORD PARAMETERS:
;
; ALLCOLORS: Set this keyword to return indices, or 24-bit values, or color
; triples, for all the known colors, instead of for a single color.
;
; DECOMPOSED: Set this keyword to 0 or 1 to force the return value to be
; a color table index or a 24-bit color value, respectively.
;
; FILENAME: The string name of an ASCII file that can be opened to read in
; color values and color names. There should be one color per row
; in the file. Please be sure there are no blank lines in the file.
; The format of each row should be:
;
; redValue greenValue blueValue colorName
;
; Color values should be between 0 and 255. Any kind of white-space
; separation (blank characters, commas, or tabs) are allowed. The color
; name should be a string, but it should NOT be in quotes. A typical
; entry into the file would look like this:
;
; 255 255 0 Yellow
;
; NAMES: If this keyword is set, the return value of the function is
; a ncolors-element string array containing the names of the colors.
; These names would be appropriate, for example, in building
; a list widget with the names of the colors. If the NAMES
; keyword is set, the COLOR and INDEX parameters are ignored.
;
; listID = Widget_List(baseID, Value=GetColor(/Names), YSize=16)
;
; ROW: If this keyword is set, the return value of the function when the TRIPLE
; keyword is set is returned as a row vector, rather than as the default
; column vector. This is required, for example, when you are trying to
; use the return value to set the color for object graphics objects. This
; keyword is completely ignored, except when used in combination with the
; TRIPLE keyword.
;
; SELECTCOLOR: Set this keyword if you would like to select the color name with
; the PICKCOLORNAME program. Selecting this keyword automaticallys sets
; the INDEX positional parameter. If this keyword is used, any keywords
; appropriate for PICKCOLORNAME can also be used. If this keyword is used,
; the first positional parameter can be either a color name or the color
; table index number. The program will figure out what you want.
;
; TRIPLE: Setting this keyword will force the return value of the function to
; *always* be a color triple, regardless of color decomposition state or
; visual depth of the machine. The value will be a three-element column
; vector unless the ROW keyword is also set.
;
; In addition, any keyword parameter appropriate for PICKCOLORNAME can be used.
; These include BOTTOM, COLUMNS, GROUP_LEADER, INDEX, and TITLE.
;
; OUTPUT KEYWORD PARAMETERS:
;
; CANCEL: This keyword is always set to 0, unless that SELECTCOLOR keyword is used.
; Then it will correspond to the value of the CANCEL output keyword in PICKCOLORNAME.
;
; COLORSTRUCTURE: This output keyword (if set to a named variable) will return a
; structure in which the fields will be the known color names (without spaces)
; and the values of the fields will be either color table index numbers or
; 24-bit color values. If you have specified a vector of color names, then
; this will be a structure containing just those color names as fields.
;
; NCOLORS: The number of colors recognized by the program. It will be 88 by default.
;
; COMMON BLOCKS:
; None.
;
; SIDE EFFECTS:
; None.
;
; ADDITIONAL PROGRAMS REQUIRED:
;
; PICKCOLORNAME: This file can be found in the Coyote Library:
;
; http://www.dfanning.com/programs/pickcolorname.pro
;
; EXAMPLE:
;
; To get drawing colors in a device-decomposed independent way:
;
; axisColor = FSC_COLOR("Green", !D.Table_Size-2)
; backColor = FSC_COLOR("Charcoal", !D.Table_Size-3)
; dataColor = FSC_COLOR("Yellow", !D.Table_Size-4)
; Plot, Findgen(11), Color=axisColor, Background=backColor, /NoData
; OPlot, Findgen(11), Color=dataColor
;
; To set the viewport color in object graphics:
;
; theView = Obj_New('IDLgrView', Color=FSC_Color('Charcoal', /Triple))
;
; To change the viewport color later:
;
; theView->SetProperty, Color=FSC_Color('Antique White', /Triple)
;
; To load the drawing colors "red", "green", and "yellow" at indices 100-102, type this:
;
; IDL> TVLCT, FSC_Color(["red", "green", and "yellow"], /Triple), 100
;
; MODIFICATION HISTORY:
; Written by: David W. Fanning, 19 October 2000. Based on previous
; GetColor program.
; Fixed a problem with loading colors with TVLCT on a PRINTER device. 13 Mar 2001. DWF.
; Added the ROW keyword. 30 March 2001. DWF.
; Added the PICKCOLORNAME code to the file, since I keep forgetting to
; give it to people. 15 August 2001. DWF.
; Added ability to specify color names and indices as vectors. 5 Nov 2002. DWF.
; Fixed a problem with the TRIPLE keyword when specifying a vector of color names. 14 Feb 2003. DWF.
; Fixed a small problem with the starting index when specifying ALLCOLORS. 24 March 2003. DWF.
; Added system color names. 23 Jan 2004. DWF
; Added work-around for WHERE function "feature" when theColor is a one-element array. 22 July 2004. DWF.
; Added support for 8-bit graphics devices when color index is not specified. 25 August 2004. DWF.
; Fixed a small problem with creating color structure when ALLCOLORS keyword is set. 26 August 2004. DWF.
; Extended the color index fix for 8-bit graphics devices on 25 August 2004 to
; 24-bit devices running with color decomposition OFF. I've concluded most of
; the people using IDL don't have any idea how color works, so I am trying to
; make it VERY simple, and yet still maintain the power of this program. So now,
; in general, for most simple plots, you don't have to use the colorindex parameter
; and you still have a very good chance of getting what you expect in a device-independent
; manner. Of course, it would be *nice* if you could use that 24-bit display you paid
; all that money for, but I understand your reluctance. :-) 11 October 2004. DWF.
; Have renamed the first positional parameter so that this variable doesn't change
; while the program is running. 7 December 2004. DWF.
; Fixed an error I introduced on 7 December 2004. Sigh... 7 January 2005. DWF.
;-
;
;###########################################################################
;
; LICENSE
;
; This software is OSI Certified Open Source Software.
; OSI Certified is a certification mark of the Open Source Initiative.
;
; Copyright © 2000-2005 Fanning Software Consulting.
;
; This software is provided "as-is", without any express or
; implied warranty. In no event will the authors be held liable
; for any damages arising from the use of this software.
;
; Permission is granted to anyone to use this software for any
; purpose, including commercial applications, and to alter it and
; redistribute it freely, subject to the following restrictions:
;
; 1. The origin of this software must not be misrepresented; you must
; not claim you wrote the original software. If you use this software
; in a product, an acknowledgment in the product documentation
; would be appreciated, but is not required.
;
; 2. Altered source versions must be plainly marked as such, and must
; not be misrepresented as being the original software.
;
; 3. This notice may not be removed or altered from any source distribution.
;
; For more information on Open Source Software, visit the Open Source
; web site: http://www.opensource.org.
;
;###########################################################################
FUNCTION FSC_Color_Error_Message, theMessage, Traceback=traceback, $
NoName=noName, _Extra=extra
On_Error, 2
; Check for presence and type of message.
IF N_Elements(theMessage) EQ 0 THEN theMessage = !Error_State.Msg
s = Size(theMessage)
messageType = s[s[0]+1]
IF messageType NE 7 THEN BEGIN
Message, "The message parameter must be a string.", _Extra=extra
ENDIF
; Get the call stack and the calling routine's name.
Help, Calls=callStack
callingRoutine = (StrSplit(StrCompress(callStack[1])," ", /Extract))[0]
; Are widgets supported? Doesn't matter in IDL 5.3 and higher.
widgetsSupported = ((!D.Flags AND 65536L) NE 0) OR Float(!Version.Release) GE 5.3
IF widgetsSupported THEN BEGIN
IF Keyword_Set(noName) THEN answer = Dialog_Message(theMessage, _Extra=extra) ELSE BEGIN
IF StrUpCase(callingRoutine) EQ "$MAIN$" THEN answer = Dialog_Message(theMessage, _Extra=extra) ELSE $
answer = Dialog_Message(StrUpCase(callingRoutine) + ": " + theMessage, _Extra=extra)
ENDELSE
ENDIF ELSE BEGIN
Message, theMessage, /Continue, /NoPrint, /NoName, /NoPrefix, _Extra=extra
Print, '%' + callingRoutine + ': ' + theMessage
answer = 'OK'
ENDELSE
; Provide traceback information if requested.
IF Keyword_Set(traceback) THEN BEGIN
Help, /Last_Message, Output=traceback
Print,''
Print, 'Traceback Report from ' + StrUpCase(callingRoutine) + ':'
Print, ''
FOR j=0,N_Elements(traceback)-1 DO Print, " " + traceback[j]
ENDIF
RETURN, answer
END ;-------------------------------------------------------------------------------
PRO FSC_Color_PickColorName_CenterTLB, tlb
; Center the top-level base widget.
screenSize = Get_Screen_Size()
screenSize[0] = screenSize[0] < 1024
xCenter = screenSize(0) / 2
yCenter = screenSize(1) / 2
geom = Widget_Info(tlb, /Geometry)
xHalfSize = geom.Scr_XSize / 2
yHalfSize = geom.Scr_YSize / 2
Widget_Control, tlb, XOffset = xCenter-xHalfSize, $
YOffset = yCenter-yHalfSize
END ;-------------------------------------------------------------------------------
FUNCTION FSC_Color_PickColorName_RGB_to_24Bit, number
; Convert RGB values to 24-bit number values.
IF Size(number, /N_Dimensions) EQ 1 THEN BEGIN
RETURN, number[0] + (number[1] * 2L^8) + (number[2] * 2L^16)
ENDIF ELSE BEGIN
RETURN, number[*,0] + (number[*,1] * 2L^8) + (number[*,2] * 2L^16)
ENDELSE
END ;-------------------------------------------------------------------------------
FUNCTION FSC_Color_PickColorName_Count_Rows, filename, MaxRows = maxrows
; This utility routine is used to count the number of
; rows in an ASCII data file.
IF N_Elements(maxrows) EQ 0 THEN maxrows = 500L
IF N_Elements(filename) EQ 0 THEN BEGIN
filename = Dialog_Pickfile()
IF filename EQ "" THEN RETURN, -1
ENDIF
OpenR, lun, filename, /Get_Lun
Catch, error
IF error NE 0 THEN BEGIN
count = count-1
Free_Lun, lun
RETURN, count
ENDIF
RESTART:
count = 1L
line = ''
FOR j=count, maxrows DO BEGIN
ReadF, lun, line
count = count + 1
; Try again if you hit MAXROWS without encountering the
; end of the file. Double the MAXROWS parameter.
IF j EQ maxrows THEN BEGIN
maxrows = maxrows * 2
Point_Lun, lun, 0
GOTO, RESTART
ENDIF
ENDFOR
RETURN, -1
END ;-------------------------------------------------------------------------------
PRO FSC_Color_PickColorName_Select_Color, event
; This event handler permits color selection by clicking on a color window.
IF event.type NE 0 THEN RETURN
Widget_Control, event.top, Get_UValue=info, /No_Copy
; Get the color names from the window you clicked on and set it.
Widget_Control, event.id, Get_UValue=thisColorName
Widget_Control, event.top, Update=0
Widget_Control, info.labelID, Set_Value=thisColorName
Widget_Control, event.top, Update=1
; Get the color value and load it as the current color.
WSet, info.mixWID
info.theName = thisColorName
theIndex = Where(info.colorNames EQ StrUpCase(StrCompress(thisColorName, /Remove_All)))
theIndex = theIndex[0]
info.nameIndex = theIndex
IF info.theDepth GT 8 THEN BEGIN
PolyFill, [0,0,1,1,0], [0,1,1,0,0], /Normal, Color=info.colors24[theIndex]
ENDIF ELSE BEGIN
TVLCT, info.red[theIndex], info.green[theIndex], info.blue[theIndex], info.mixcolorIndex
PolyFill, [0,0,1,1,0], [0,1,1,0,0], /Normal, Color=info.mixcolorIndex
ENDELSE
Widget_Control, event.top, Set_UValue=info, /No_Copy
END ;---------------------------------------------------------------------------
PRO FSC_Color_PickColorName_Buttons, event
; This event handler responds to CANCEL and ACCEPT buttons.
Widget_Control, event.top, Get_UValue=info, /No_Copy
; Which button is this?
Widget_Control, event.id, Get_Value=buttonValue
; Branch on button value.
CASE buttonValue OF
'Cancel': BEGIN
; Simply destroy the widget. The pointer info is already
; set up for a CANCEL event.
Widget_Control, event.top, /Destroy
ENDCASE
'Accept': BEGIN
; Get the new color table after the color has been selected.
TVLCT, r, g, b, /Get
; Save the new color and name in the pointer.
*(info.ptr) = {cancel:0.0, r:info.red[info.nameIndex], g:info.green[info.nameIndex], $
b:info.blue[info.nameIndex], name:info.theName}
; Destoy the widget.
Widget_Control, event.top, /Destroy
ENDCASE
ENDCASE
END ;---------------------------------------------------------------------------
FUNCTION FSC_Color_PickColorName, theName, $ ; The name of the starting color.
Bottom=bottom, $ ; The index number where the colors should be loaded.
Cancel=cancelled, $ ; An output keyword set to 1 if the user cancelled or an error occurred.
Columns = ncols, $ ; The number of columns to display the colors in.
Filename=filename, $ ; The name of the file which contains color names and values.
Group_Leader=group_leader, $ ; The group leader of the TLB. Required for modal operation.
Index=index, $ ; The color index number where the final selected color should be loaded.
Title=title ; The title of the top-level base widget.
; Error handling for this program module.
Catch, theError
IF theError NE 0 THEN BEGIN
Catch, /Cancel
ok = FSC_Color_Error_Message(/Traceback)
cancel = 1
IF N_Elements(theName) NE 0 THEN RETURN, theName ELSE RETURN, 'White'
ENDIF
; Get depth of visual display.
IF (!D.Flags AND 256) NE 0 THEN Device, Get_Visual_Depth=theDepth ELSE theDepth = 8
; Is there a filename? If so, get colors from there.
IF N_Elements(filename) NE 0 THEN BEGIN
; Count the number of rows in the file.
NCOLORS = FSC_Color_PickColorName_Count_Rows(filename)
; Read the data.
OpenR, lun, filename, /Get_Lun
red = BytArr(NCOLORS)
green = BytArr(NCOLORS)
blue = BytArr(NCOLORS)
colors = StrArr(NCOLORS)
redvalue = 0B
greenvalue = 0B
bluevalue = 0B
namevalue = ""
FOR j=0L, NCOLORS-1 DO BEGIN
ReadF, lun, redvalue, greenvalue, bluevalue, namevalue
colors[j] = namevalue
red[j] = redvalue
green[j] = greenvalue
blue[j] = bluevalue
ENDFOR
; Trim the colors array of blank characters.
colors = StrTrim(colors, 2)
; Calculate the number of columns to display colors in.
IF N_Elements(ncols) EQ 0 THEN ncols = Fix(Sqrt(ncolors))
Free_Lun, lun
ENDIF ELSE BEGIN
IF theDepth GT 8 THEN BEGIN
; The colors with their names.
NCOLORS = 88
IF N_Elements(ncols) EQ 0 THEN ncols = 11
colors= ['White']
red = [ 255]
green = [ 255]
blue = [ 255]
colors= [ colors, 'Snow', 'Ivory','Light Yellow', 'Cornsilk', 'Beige', 'Seashell' ]
red = [ red, 255, 255, 255, 255, 245, 255 ]
green = [ green, 250, 255, 255, 248, 245, 245 ]
blue = [ blue, 250, 240, 224, 220, 220, 238 ]
colors= [ colors, 'Linen','Antique White', 'Papaya', 'Almond', 'Bisque', 'Moccasin' ]
red = [ red, 250, 250, 255, 255, 255, 255 ]
green = [ green, 240, 235, 239, 235, 228, 228 ]
blue = [ blue, 230, 215, 213, 205, 196, 181 ]
colors= [ colors, 'Wheat', 'Burlywood', 'Tan', 'Light Gray', 'Lavender','Medium Gray' ]
red = [ red, 245, 222, 210, 230, 230, 210 ]
green = [ green, 222, 184, 180, 230, 230, 210 ]
blue = [ blue, 179, 135, 140, 230, 250, 210 ]
colors= [ colors, 'Gray', 'Slate Gray', 'Dark Gray', 'Charcoal', 'Black', 'Light Cyan' ]
red = [ red, 190, 112, 110, 70, 0, 224 ]
green = [ green, 190, 128, 110, 70, 0, 255 ]
blue = [ blue, 190, 144, 110, 70, 0, 255 ]
colors= [ colors,'Powder Blue', 'Sky Blue', 'Steel Blue','Dodger Blue', 'Royal Blue', 'Blue' ]
red = [ red, 176, 135, 70, 30, 65, 0 ]
green = [ green, 224, 206, 130, 144, 105, 0 ]
blue = [ blue, 230, 235, 180, 255, 225, 255 ]
colors= [ colors, 'Navy', 'Honeydew', 'Pale Green','Aquamarine','Spring Green', 'Cyan' ]
red = [ red, 0, 240, 152, 127, 0, 0 ]
green = [ green, 0, 255, 251, 255, 250, 255 ]
blue = [ blue, 128, 240, 152, 212, 154, 255 ]
colors= [ colors, 'Turquoise', 'Sea Green','Forest Green','Green Yellow','Chartreuse', 'Lawn Green' ]
red = [ red, 64, 46, 34, 173, 127, 124 ]
green = [ green, 224, 139, 139, 255, 255, 252 ]
blue = [ blue, 208, 87, 34, 47, 0, 0 ]
colors= [ colors, 'Green', 'Lime Green', 'Olive Drab', 'Olive','Dark Green','Pale Goldenrod']
red = [ red, 0, 50, 107, 85, 0, 238 ]
green = [ green, 255, 205, 142, 107, 100, 232 ]
blue = [ blue, 0, 50, 35, 47, 0, 170 ]
colors =[ colors, 'Khaki', 'Dark Khaki', 'Yellow', 'Gold','Goldenrod','Dark Goldenrod']
red = [ red, 240, 189, 255, 255, 218, 184 ]
green = [ green, 230, 183, 255, 215, 165, 134 ]
blue = [ blue, 140, 107, 0, 0, 32, 11 ]
colors= [ colors,'Saddle Brown', 'Rose', 'Pink', 'Rosy Brown','Sandy Brown', 'Peru']
red = [ red, 139, 255, 255, 188, 244, 205 ]
green = [ green, 69, 228, 192, 143, 164, 133 ]
blue = [ blue, 19, 225, 203, 143, 96, 63 ]
colors= [ colors,'Indian Red', 'Chocolate', 'Sienna','Dark Salmon', 'Salmon','Light Salmon' ]
red = [ red, 205, 210, 160, 233, 250, 255 ]
green = [ green, 92, 105, 82, 150, 128, 160 ]
blue = [ blue, 92, 30, 45, 122, 114, 122 ]
colors= [ colors, 'Orange', 'Coral', 'Light Coral', 'Firebrick', 'Brown', 'Hot Pink' ]
red = [ red, 255, 255, 240, 178, 165, 255 ]
green = [ green, 165, 127, 128, 34, 42, 105 ]
blue = [ blue, 0, 80, 128, 34, 42, 180 ]
colors= [ colors, 'Deep Pink', 'Magenta', 'Tomato', 'Orange Red', 'Red', 'Violet Red' ]
red = [ red, 255, 255, 255, 255, 255, 208 ]
green = [ green, 20, 0, 99, 69, 0, 32 ]
blue = [ blue, 147, 255, 71, 0, 0, 144 ]
colors= [ colors, 'Maroon', 'Thistle', 'Plum', 'Violet', 'Orchid','Medium Orchid']
red = [ red, 176, 216, 221, 238, 218, 186 ]
green = [ green, 48, 191, 160, 130, 112, 85 ]
blue = [ blue, 96, 216, 221, 238, 214, 211 ]
colors= [ colors,'Dark Orchid','Blue Violet', 'Purple']
red = [ red, 153, 138, 160 ]
green = [ green, 50, 43, 32 ]
blue = [ blue, 204, 226, 240 ]
ENDIF ELSE BEGIN
NCOLORS = 16
IF N_Elements(ncols) EQ 0 THEN ncols = 8
colors = ['Black', 'Magenta', 'Cyan', 'Yellow', 'Green']
red = [ 0, 255, 0, 255, 0 ]
green = [ 0, 0, 255, 255, 255 ]
blue = [ 0, 255, 255, 0, 0 ]
colors = [colors, 'Red', 'Blue', 'Navy', 'Pink', 'Aqua']
red = [red, 255, 0, 0, 255, 112]
green = [green, 0, 0, 0, 127, 219]
blue = [blue, 0, 255, 115, 127, 147]
colors = [colors, 'Orchid', 'Sky', 'Beige', 'Charcoal', 'Gray','White']
red = [red, 219, 0, 245, 80, 135, 255 ]
green = [green, 112, 163, 245, 80, 135, 255 ]
blue = [blue, 219, 255, 220, 80, 135, 255 ]
ENDELSE
ENDELSE
; Add system color names for IDL version 5.6 and higher.
IF Float(!Version.Release) GE 5.6 THEN BEGIN
tlb = Widget_Base()
sc = Widget_Info(tlb, /System_Colors)
Widget_Control, tlb, /Destroy
frame = sc.window_frame
text = sc.window_text
active = sc.active_border
shadow = sc.shadow_3d
highlight = sc.light_3d
edge = sc.light_edge_3d
selected = sc.highlight
face = sc.face_3d
colors = [colors, 'Frame', 'Text', 'Active', 'Shadow']
red = [red, frame[0], text[0], active[0], shadow[0]]
green = [green, frame[1], text[1], active[1], shadow[1]]
blue = [blue, frame[2], text[2], active[2], shadow[2]]
colors = [colors, 'Highlight', 'Edge', 'Selected', 'Face']
red = [red, highlight[0], edge[0], selected[0], face[0]]
green = [green, highlight[1], edge[1], selected[1], face[1]]
blue = [blue, highlight[2], edge[2], selected[2], face[2]]
ENDIF
; Save decomposed state and restore it, if possible.
IF Float(!Version.Release) GE 5.2 THEN BEGIN
Device, Get_Decomposed=decomposedState
ENDIF ELSE decomposedState = 0
; Different color decomposition based on visual depth.
IF theDepth GT 8 THEN BEGIN
Device, Decomposed=1
colors24 = FSC_Color_PickColorName_RGB_to_24Bit([[red], [green], [blue]])
ENDIF ELSE BEGIN
IF NCOLORS GT !D.Table_Size THEN $
Message, /NoName, 'Number of colors exceeds color table size. Returning...'
Device, Decomposed=0
colors24 = -1
ENDELSE
; Check argument values. All arguments are optional.
IF N_Elements(theName) EQ 0 THEN theName = 'White'
IF Size(theName, /TName) NE 'STRING' THEN $
Message, 'Color name argument must be STRING type.', /NoName
theName = StrCompress(theName, /Remove_All)
IF N_Elements(bottom) EQ 0 THEN bottom = 0 > (!D.Table_Size - (NCOLORS + 2))
mixcolorIndex = bottom
IF N_Elements(title) EQ 0 THEN title='Select a Color'
; We will work with all uppercase names.
colorNames = StrUpCase(StrCompress(colors, /Remove_All))
; Get the current color table vectors before we change anything.
; This will allow us to restore the color table when we depart.
TVLCT, r_old, g_old, b_old, /Get
; Load the colors if needed. The "bottom" index is reserved as the "mixing color" index.
IF theDepth LE 8 THEN TVLCT, red, green, blue, bottom+1
; Can you find the color name in the colors array?
nameIndex = WHERE(colorNames EQ StrUpCase(theName), count)
IF count EQ 0 THEN BEGIN
Message, 'Unable to resolve color name: ' + StrUpCase(theName) + '. Replacing with WHITE.', /Informational
theName = 'White'
nameIndex = WHERE(colorNames EQ StrUpCase(theName), count)
IF count EQ 0 THEN Message, /NoName, 'Unable to resolve color name: ' + StrUpCase(theName) + '. Returning...'
ENDIF
nameIndex = nameIndex[0]
; Who knows how the user spelled the color? Make it look nice.
theName = colors[nameIndex]
; Load the mixing color in the mixcolorIndex.
IF theDepth LE 8 THEN TVLCT, red[nameIndex], green[nameIndex], blue[nameIndex], mixcolorIndex
; Create the widgets. TLB is MODAL or BLOCKING, depending upon presence of
; Group_Leader variable.
IF N_Elements(group_leader) EQ 0 THEN BEGIN
tlb = Widget_Base(Title=title, Column=1, /Base_Align_Center)
ENDIF ELSE BEGIN
tlb = Widget_Base(Title=title, Column=1, /Base_Align_Center, /Modal, $
Group_Leader=group_leader)
ENDELSE
; Draw widgets for the possible colors. Store the color name in the UVALUE.
colorbaseID = Widget_Base(tlb, Column=ncols, Event_Pro='FSC_Color_PickColorName_Select_Color')
drawID = LonArr(NCOLORS)
FOR j=0,NCOLORS-1 DO BEGIN
drawID[j] = Widget_Draw(colorbaseID, XSize=20, YSize=15, $
UValue=colors[j], Button_Events=1)
ENDFOR
; Set up the current or mixing color draw widget.
currentID = Widget_Base(tlb, Column=1, Base_Align_Center=1)
labelID = Widget_Label(currentID, Value=theName, /Dynamic_Resize)
mixColorID = Widget_Draw(currentID, XSize=60, YSize=15)
; CANCEL and ACCEPT buttons.
buttonbase = Widget_Base(tlb, ROW=1, Align_Center=1, Event_Pro='FSC_Color_PickColorName_Buttons')
cancelID = Widget_Button(buttonbase, VALUE='Cancel')
acceptID = Widget_Button(buttonbase, VALUE='Accept')
; Center the TLB.
FSC_Color_PickColorName_CenterTLB, tlb
Widget_Control, tlb, /Realize
; Load the drawing colors.
wids = IntArr(NCOLORS)
IF theDepth GT 8 THEN BEGIN
FOR j=0,NCOLORS-1 DO BEGIN
Widget_Control, drawID[j], Get_Value=thisWID
wids[j] = thisWID
WSet, thisWID
PolyFill, [0,0,1,1,0], [0,1,1,0,0], /Normal, Color=colors24[j]
ENDFOR
ENDIF ELSE BEGIN
FOR j=1,NCOLORS DO BEGIN
Widget_Control, drawID[j-1], Get_Value=thisWID
wids[j-1] = thisWID
WSet, thisWID
PolyFill, [0,0,1,1,0], [0,1,1,0,0], /Normal, Color=bottom + j
ENDFOR
ENDELSE
; Load the current or mixing color.
Widget_Control, mixColorID, Get_Value=mixWID
WSet, mixWID
IF theDepth GT 8 THEN BEGIN
PolyFill, [0,0,1,1,0], [0,1,1,0,0], /Normal, Color=colors24[nameIndex]
ENDIF ELSE BEGIN
PolyFill, [0,0,1,1,0], [0,1,1,0,0], /Normal, Color=mixcolorIndex
ENDELSE
; Pointer to hold the color form information.
ptr = Ptr_New({cancel:1.0, r:0B, g:0B, b:0B, name:theName})
; Info structure for program information.
info = { ptr:ptr, $ ; The pointer to the form information.
mixColorIndex:mixColorIndex, $
colorNames:colorNames, $
nameIndex:nameIndex, $
red:red, $
green:green, $
blue:blue, $
colors24:colors24, $
mixWid:mixWid, $
theDepth:theDepth, $
labelID:labelID, $
theName:theName $
}
; Store the info structure in the UVALUE of the TLB.
Widget_Control, tlb, Set_UValue=info, /No_Copy
; Set up program event loop. This will be blocking widget
; if called from the IDL command line. Program operation
; will stop here until widget interface is destroyed.
XManager, 'pickcolor', tlb
; Retrieve the color information from the pointer and free
; the pointer.
colorInfo = *ptr
Ptr_Free, ptr
; Set the Cancel flag.
cancelled = colorInfo.cancel
; Restore color table, taking care to load the color index if required.
IF N_Elements(index) NE 0 AND (NOT cancelled) THEN BEGIN
r_old[index] = colorInfo.r
g_old[index] = colorInfo.g
b_old[index] = colorInfo.b
ENDIF
TVLCT, r_old, g_old, b_old
; Restore decomposed state if possible.
IF Float(!Version.Release) GE 5.2 THEN Device, Decomposed=decomposedState
; Return the color name.
RETURN, colorInfo.name
END
FUNCTION FSC_Color_Count_Rows, filename, MaxRows = maxrows
; This utility routine is used to count the number of
; rows in an ASCII data file.
IF N_Elements(maxrows) EQ 0 THEN maxrows = 500L
IF N_Elements(filename) EQ 0 THEN BEGIN
filename = Dialog_Pickfile()
IF filename EQ "" THEN RETURN, -1
ENDIF
OpenR, lun, filename, /Get_Lun
Catch, theError
IF theError NE 0 THEN BEGIN
Catch, /Cancel
count = count-1
Free_Lun, lun
RETURN, count
ENDIF
RESTART:
count = 1L
line = ''
FOR j=count, maxrows DO BEGIN
ReadF, lun, line
count = count + 1
; Try again if you hit MAXROWS without encountering the
; end of the file. Double the MAXROWS parameter.
IF j EQ maxrows THEN BEGIN
maxrows = maxrows * 2
Point_Lun, lun, 0
GOTO, RESTART
ENDIF
ENDFOR
RETURN, -1
END ;-------------------------------------------------------------------------------
FUNCTION FSC_Color_Color24, color
; This FUNCTION accepts a [red, green, blue] triple that
; describes a particular color and returns a 24-bit long
; integer that is equivalent to (can be decomposed into)
; that color. The triple can be either a row or column
; vector of 3 elements or it can be an N-by-3 array of
; color triples.
ON_ERROR, 2
s = Size(color)
IF s[0] EQ 1 THEN BEGIN
IF s[1] NE 3 THEN Message, 'Input color parameter must be a 3-element vector.'
RETURN, color[0] + (color[1] * 2L^8) + (color[2] * 2L^16)
ENDIF ELSE BEGIN
IF s[2] GT 3 THEN Message, 'Input color parameter must be an N-by-3 array.'
RETURN, color[*,0] + (color[*,1] * 2L^8) + (color[*,2] * 2L^16)
ENDELSE
END ;--------------------------------------------------------------------------------------------
FUNCTION FSC_Color, theColour, colorIndex, $
AllColors=allcolors, $
ColorStructure=colorStructure, $
Cancel=cancelled, $
Decomposed=decomposedState, $
_Extra=extra, $
Filename=filename, $
Names=names, $
NColors=ncolors, $
Row=row, $
SelectColor=selectcolor, $
Triple=triple
; Error handling.
Catch, theError
IF theError NE 0 THEN BEGIN
Catch, /Cancel
ok = FSC_Color_Error_Message(/Traceback)
cancelled = 1
RETURN, !P.Color
ENDIF
; I don't want to change the original variable.
IF N_Elements(theColour) NE 0 THEN theColor = theColour ELSE theColor = 'WHITE'
; Load the colors.
IF N_Elements(filename) NE 0 THEN BEGIN
; Count the number of rows in the file.
ncolors = FSC_Color_Count_Rows(filename)
; Read the data.
OpenR, lun, filename, /Get_Lun
rvalue = BytArr(NCOLORS)
gvalue = BytArr(NCOLORS)
bvalue = BytArr(NCOLORS)
colors = StrArr(NCOLORS)
redvalue = 0B
greenvalue = 0B
bluevalue = 0B
colorvalue = ""
FOR j=0L, NCOLORS-1 DO BEGIN
ReadF, lun, redvalue, greenvalue, bluevalue, colorvalue
rvalue[j] = redvalue
gvalue[j] = greenvalue
bvalue[j] = bluevalue
colors[j] = colorvalue
ENDFOR
Free_Lun, lun
; Trim the colors array of blank characters.
colors = StrTrim(colors, 2)
ENDIF ELSE BEGIN
; Set up the color vectors.
colors = ['White']
rvalue = [ 255]
gvalue = [ 255]
bvalue = [ 255]
colors = [ colors, 'Snow', 'Ivory','Light Yellow', 'Cornsilk', 'Beige', 'Seashell' ]
rvalue = [ rvalue, 255, 255, 255, 255, 245, 255 ]
gvalue = [ gvalue, 250, 255, 255, 248, 245, 245 ]
bvalue = [ bvalue, 250, 240, 224, 220, 220, 238 ]
colors = [ colors, 'Linen','Antique White', 'Papaya', 'Almond', 'Bisque', 'Moccasin' ]
rvalue = [ rvalue, 250, 250, 255, 255, 255, 255 ]
gvalue = [ gvalue, 240, 235, 239, 235, 228, 228 ]
bvalue = [ bvalue, 230, 215, 213, 205, 196, 181 ]
colors = [ colors, 'Wheat', 'Burlywood', 'Tan', 'Light Gray', 'Lavender','Medium Gray' ]
rvalue = [ rvalue, 245, 222, 210, 230, 230, 210 ]
gvalue = [ gvalue, 222, 184, 180, 230, 230, 210 ]
bvalue = [ bvalue, 179, 135, 140, 230, 250, 210 ]
colors = [ colors, 'Gray', 'Slate Gray', 'Dark Gray', 'Charcoal', 'Black', 'Light Cyan' ]
rvalue = [ rvalue, 190, 112, 110, 70, 0, 224 ]
gvalue = [ gvalue, 190, 128, 110, 70, 0, 255 ]
bvalue = [ bvalue, 190, 144, 110, 70, 0, 255 ]
colors = [ colors,'Powder Blue', 'Sky Blue', 'Steel Blue','Dodger Blue', 'Royal Blue', 'Blue' ]
rvalue = [ rvalue, 176, 135, 70, 30, 65, 0 ]
gvalue = [ gvalue, 224, 206, 130, 144, 105, 0 ]
bvalue = [ bvalue, 230, 235, 180, 255, 225, 255 ]
colors = [ colors, 'Navy', 'Honeydew', 'Pale Green','Aquamarine','Spring Green', 'Cyan' ]
rvalue = [ rvalue, 0, 240, 152, 127, 0, 0 ]
gvalue = [ gvalue, 0, 255, 251, 255, 250, 255 ]
bvalue = [ bvalue, 128, 240, 152, 212, 154, 255 ]
colors = [ colors, 'Turquoise', 'Sea Green','Forest Green','Green Yellow','Chartreuse', 'Lawn Green' ]
rvalue = [ rvalue, 64, 46, 34, 173, 127, 124 ]
gvalue = [ gvalue, 224, 139, 139, 255, 255, 252 ]
bvalue = [ bvalue, 208, 87, 34, 47, 0, 0 ]
colors = [ colors, 'Green', 'Lime Green', 'Olive Drab', 'Olive','Dark Green','Pale Goldenrod']
rvalue = [ rvalue, 0, 50, 107, 85, 0, 238 ]
gvalue = [ gvalue, 255, 205, 142, 107, 100, 232 ]
bvalue = [ bvalue, 0, 50, 35, 47, 0, 170 ]
colors = [ colors, 'Khaki', 'Dark Khaki', 'Yellow', 'Gold','Goldenrod','Dark Goldenrod']
rvalue = [ rvalue, 240, 189, 255, 255, 218, 184 ]
gvalue = [ gvalue, 230, 183, 255, 215, 165, 134 ]
bvalue = [ bvalue, 140, 107, 0, 0, 32, 11 ]
colors = [ colors,'Saddle Brown', 'Rose', 'Pink', 'Rosy Brown','Sandy Brown', 'Peru' ]
rvalue = [ rvalue, 139, 255, 255, 188, 244, 205 ]
gvalue = [ gvalue, 69, 228, 192, 143, 164, 133 ]
bvalue = [ bvalue, 19, 225, 203, 143, 96, 63 ]
colors = [ colors, 'Indian Red', 'Chocolate', 'Sienna','Dark Salmon', 'Salmon','Light Salmon' ]
rvalue = [ rvalue, 205, 210, 160, 233, 250, 255 ]
gvalue = [ gvalue, 92, 105, 82, 150, 128, 160 ]
bvalue = [ bvalue, 92, 30, 45, 122, 114, 122 ]
colors = [ colors, 'Orange', 'Coral', 'Light Coral', 'Firebrick', 'Brown', 'Hot Pink' ]
rvalue = [ rvalue, 255, 255, 240, 178, 165, 255 ]
gvalue = [ gvalue, 165, 127, 128, 34, 42, 105 ]
bvalue = [ bvalue, 0, 80, 128, 34, 42, 180 ]
colors = [ colors, 'Deep Pink', 'Magenta', 'Tomato', 'Orange Red', 'Red', 'Violet Red' ]
rvalue = [ rvalue, 255, 255, 255, 255, 255, 208 ]
gvalue = [ gvalue, 20, 0, 99, 69, 0, 32 ]
bvalue = [ bvalue, 147, 255, 71, 0, 0, 144 ]
colors = [ colors, 'Maroon', 'Thistle', 'Plum', 'Violet', 'Orchid','Medium Orchid']
rvalue = [ rvalue, 176, 216, 221, 238, 218, 186 ]
gvalue = [ gvalue, 48, 191, 160, 130, 112, 85 ]
bvalue = [ bvalue, 96, 216, 221, 238, 214, 211 ]
colors = [ colors,'Dark Orchid','Blue Violet', 'Purple' ]
rvalue = [ rvalue, 153, 138, 160 ]
gvalue = [ gvalue, 50, 43, 32 ]
bvalue = [ bvalue, 204, 226, 240 ]
ENDELSE
; Add system color names for IDL version 5.6 and higher.
IF Float(!Version.Release) GE 5.6 THEN BEGIN
tlb = Widget_Base()
sc = Widget_Info(tlb, /System_Colors)
Widget_Control, tlb, /Destroy
frame = sc.window_frame
text = sc.window_text
active = sc.active_border
shadow = sc.shadow_3d
highlight = sc.light_3d
edge = sc.light_edge_3d
selected = sc.highlight
face = sc.face_3d
colors = [colors, 'Frame', 'Text', 'Active', 'Shadow']
rvalue = [rvalue, frame[0], text[0], active[0], shadow[0]]
gvalue = [gvalue, frame[1], text[1], active[1], shadow[1]]
bvalue = [bvalue, frame[2], text[2], active[2], shadow[2]]
colors = [colors, 'Highlight', 'Edge', 'Selected', 'Face']
rvalue = [rvalue, highlight[0], edge[0], selected[0], face[0]]
gvalue = [gvalue, highlight[1], edge[1], selected[1], face[1]]
bvalue = [bvalue, highlight[2], edge[2], selected[2], face[2]]
ENDIF
; How many colors do we have?
ncolors = N_Elements(colors)
; Get the decomposed state of the IDL session right now.
IF N_Elements(decomposedState) EQ 0 THEN BEGIN
IF Float(!Version.Release) GE 5.2 THEN BEGIN
IF (!D.Name EQ 'X' OR !D.Name EQ 'WIN' OR !D.Name EQ 'MAC') THEN BEGIN
Device, Get_Decomposed=decomposedState
ENDIF ELSE decomposedState = 0
ENDIF ELSE decomposedState = 0
ENDIF ELSE decomposedState = Keyword_Set(decomposedState)
; Get depth of visual display.
IF (!D.Flags AND 256) NE 0 THEN Device, Get_Visual_Depth=theDepth ELSE theDepth = 8
IF (theDepth EQ 8) OR (decomposedState EQ 0) THEN offset = !D.Table_Size - ncolors - 2 ELSE offset = 0
; Did the user want to select a color name? If so, we set
; the color name and color index, unless the user provided
; them. In the case of a single positional parameter, we treat
; this as the color index number as long as it is not a string.
cancelled = 0.0
IF Keyword_Set(selectcolor) THEN BEGIN
CASE N_Params() OF
0: BEGIN
colorIndex = !P.Color < 255
theColor = FSC_Color_PickColorName(Filename=filename, _Extra=extra, Cancel=cancelled)
IF cancelled THEN RETURN, !P.Color
END
1: BEGIN
IF Size(theColor, /TName) NE 'STRING' THEN BEGIN
colorIndex = theColor
theColor='White'
ENDIF ELSE colorIndex = !P.Color < 255
theColor = FSC_Color_PickColorName(theColor, Filename=filename, _Extra=extra, Cancel=cancelled)
IF cancelled THEN RETURN, !P.Color
END
2: BEGIN
theColor = FSC_Color_PickColorName(theColor, Filename=filename, _Extra=extra, Cancel=cancelled)
IF cancelled THEN RETURN, !P.Color
END
ENDCASE
ENDIF
; Make sure you have a color name and color index.
CASE N_Elements(theColor) OF
0: BEGIN
theColor = 'White'
IF N_Elements(colorIndex) EQ 0 THEN BEGIN
IF theDepth GT 8 THEN BEGIN
colorIndex = !P.Color < (!D.Table_Size - 1)
ENDIF ELSE BEGIN
colorIndex = Where(StrUpCase(colors) EQ StrUpCase(theColor), count) + offset
colorIndex = colorIndex[0]
IF count EQ 0 THEN Message, 'Cannot find color: ' + StrUpCase(theColor), /NoName
ENDELSE
ENDIF ELSE colorIndex = 0 > colorIndex < (!D.Table_Size - 1)
ENDCASE
1: BEGIN
type = Size(theColor, /TNAME)
IF type NE 'STRING' THEN Message, 'The color must be expressed as a color name.'
theColor = theColor[0] ; Make it a scalar or you run into a WHERE function "feature". :-(
IF N_Elements(colorIndex) EQ 0 THEN BEGIN
IF (theDepth GT 8) AND (decomposedState EQ 1) THEN BEGIN
colorIndex = !P.Color < (!D.Table_Size - 1)
ENDIF ELSE BEGIN
colorIndex = Where(StrUpCase(colors) EQ StrUpCase(theColor), count) + offset
colorIndex = colorIndex[0]
IF count EQ 0 THEN Message, 'Cannot find color: ' + StrUpCase(theColor), /NoName
ENDELSE
ENDIF ELSE colorIndex = 0 > colorIndex < (!D.Table_Size - 1)
ENDCASE
ELSE: BEGIN
type = Size(theColor, /TNAME)
IF type NE 'STRING' THEN Message, 'The colors must be expressed as color names.'
ncolors = N_Elements(theColor)
CASE N_Elements(colorIndex) OF
0: colorIndex = Indgen(ncolors) + (!D.Table_Size - (ncolors + 1))
1: colorIndex = Indgen(ncolors) + colorIndex
ELSE: IF N_Elements(colorIndex) NE ncolors THEN $
Message, 'Index vector must be the same length as color name vector.'
ENDCASE
; Did the user want color triples?
IF Keyword_Set(triple) THEN BEGIN
colors = LonArr(ncolors, 3)
FOR j=0,ncolors-1 DO colors[j,*] = FSC_Color(theColor[j], colorIndex[j], Filename=filename, $
Decomposed=decomposedState, /Triple)
RETURN, colors
ENDIF ELSE BEGIN
colors = LonArr(ncolors)
FOR j=0,ncolors-1 DO colors[j] = FSC_Color(theColor[j], colorIndex[j], Filename=filename, $
Decomposed=decomposedState)
RETURN, colors
ENDELSE
END
ENDCASE
; Make sure the color parameter is an uppercase string.
varInfo = Size(theColor)
IF varInfo[varInfo[0] + 1] NE 7 THEN $
Message, 'The color name parameter must be a string.', /NoName
theColor = StrUpCase(StrCompress(StrTrim(theColor,2), /Remove_All))
; Check synonyms of color names.
IF StrUpCase(theColor) EQ 'GREY' THEN theColor = 'GRAY'
IF StrUpCase(theColor) EQ 'LIGHTGREY' THEN theColor = 'LIGHTGRAY'
IF StrUpCase(theColor) EQ 'MEDIUMGREY' THEN theColor = 'MEDIUMGRAY'
IF StrUpCase(theColor) EQ 'SLATEGREY' THEN theColor = 'SLATEGRAY'
IF StrUpCase(theColor) EQ 'DARKGREY' THEN theColor = 'DARKGRAY'
IF StrUpCase(theColor) EQ 'AQUA' THEN theColor = 'AQUAMARINE'
IF StrUpCase(theColor) EQ 'SKY' THEN theColor = 'SKYBLUE'
IF StrUpCase(theColor) EQ 'NAVY BLUE' THEN theColor = 'NAVY'
IF StrUpCase(theColor) EQ 'NAVYBLUE' THEN theColor = 'NAVY'
; Did the user ask for the color names? If so, return them now.
IF Keyword_Set(names) THEN RETURN, Reform(colors, 1, ncolors)
; Process the color names.
theNames = StrUpCase( StrCompress( StrTrim( colors, 2 ), /Remove_All ) )
; Find the asked-for color in the color names array.
theIndex = Where(theNames EQ theColor, foundIt)
theIndex = theIndex[0]
; If the color can't be found, report it and continue with
; the first color in the color names array.
IF foundIt EQ 0 THEN BEGIN
Message, "Can't find color " + theColor + ". Substituting " + StrUpCase(colors[0]) + ".", /Informational
theColor = theNames[0]
theIndex = 0
ENDIF
; Get the color triple for this color.
r = rvalue[theIndex]
g = gvalue[theIndex]
b = bvalue[theIndex]
; Did the user want a color triple? If so, return it now.
IF Keyword_Set(triple) THEN BEGIN
IF Keyword_Set(allcolors) THEN BEGIN
IF Keyword_Set(row) THEN RETURN, Transpose([[rvalue], [gvalue], [bvalue]]) ELSE RETURN, [[rvalue], [gvalue], [bvalue]]
ENDIF ELSE BEGIN
IF Keyword_Set(row) THEN RETURN, [r, g, b] ELSE RETURN, [[r], [g], [b]]
ENDELSE
ENDIF
; Otherwise, we are going to return either an index
; number where the color has been loaded, or a 24-bit
; value that can be decomposed into the proper color.
IF decomposedState THEN BEGIN
; Need a color structure?
IF Arg_Present(colorStructure) THEN BEGIN
theColors = FSC_Color_Color24([[rvalue], [gvalue], [bvalue]])
colorStructure = Create_Struct(theNames[0], theColors[0])
FOR j=1, ncolors-1 DO colorStructure = Create_Struct(colorStructure, theNames[j], theColors[j])
ENDIF
IF Keyword_Set(allcolors) THEN BEGIN
RETURN, FSC_Color_Color24([[rvalue], [gvalue], [bvalue]])
ENDIF ELSE BEGIN
RETURN, FSC_Color_Color24([r, g, b])
ENDELSE
ENDIF ELSE BEGIN
IF Keyword_Set(allcolors) THEN BEGIN
; Need a color structure?
IF Arg_Present(colorStructure) THEN BEGIN
allcolorIndex = !D.Table_Size - ncolors - 2
IF allcolorIndex LT 0 THEN $
Message, 'Number of colors exceeds available color table values. Returning.', /NoName
IF (allcolorIndex + ncolors) GT 255 THEN $
Message, 'Number of colors exceeds available color table indices. Returning.', /NoName
theColors = IndGen(ncolors) + allcolorIndex
colorStructure = Create_Struct(theNames[0], theColors[0])
FOR j=1, ncolors-1 DO colorStructure = Create_Struct(colorStructure, theNames[j], theColors[j])
ENDIF
IF N_Elements(colorIndex) EQ 0 THEN colorIndex = !D.Table_Size - ncolors - 2
IF colorIndex LT 0 THEN $
Message, 'Number of colors exceeds available color table values. Returning.', /NoName
IF (colorIndex + ncolors) GT 255 THEN BEGIN
colorIndex = !D.Table_Size - ncolors - 2
ENDIF
IF !D.Name NE 'PRINTER' THEN TVLCT, rvalue, gvalue, bvalue, colorIndex
RETURN, IndGen(ncolors) + colorIndex
ENDIF ELSE BEGIN
; Need a color structure?
IF Arg_Present(colorStructure) THEN BEGIN
colorStructure = Create_Struct(theColor, colorIndex)
ENDIF
IF !D.Name NE 'PRINTER' THEN TVLCT, rvalue[theIndex], gvalue[theIndex], bvalue[theIndex], colorIndex
RETURN, colorIndex
ENDELSE
ENDELSE
END ;-------------------------------------------------------------------------------------------------------