Colours

From Vectorlab
Jump to: navigation, search

A discussion on the use of colours in VectorWorks. By Joel Sciamma

The information on this page pertains to VectorWorks 12.x and below. For a discussion of colours in VectorWorks 2008+, see Colors in VectorWorks 2008+.

With contributions by

The VectorWorks colour palette

There are some interesting aspects to the standard VectorWorks colour palette that may not be immediately apparent. They certainly were not apparent to me when I was trying to build a script that assigned colours to objects then checked if the colour had subsequently been changed manually. The results were not what I was expecting.

The standard or default colour palette contains 256 colours and each colour is assigned an integer value which can be used by various VectorScript calls to set the colour attributes of referenced objects. The values for these colour attributes can also be read by scripts for further analysis and processing. This standard palette is the one that is applied to every new VectorWorks document and therefore the one most likely to be the environment within which our scripts operate.

However, as supplied, the standard colour palette does not contain 256 unique colours.

Unaccountably, from the 16.2 million colours that are today potentially available, some of the colours in the palette are duplicated. The duplicates can be found by running the following script which tests if the colour indexes return the same RGB value when passed through RGBToColorIndex.

PROCEDURE ColConv;
VAR
	Red, Green, Blue, Colour, Check, ArrayPointer: LONGINT;
	Discrepancies: ARRAY [1..256] OF STRING;

{=================================== Main =====================================}

BEGIN
   {$debug}
	ArrayPointer := 1;

		{--- Traverse all the colours in the palette ---}
	FOR Colour := 0 TO 255 DO
		BEGIN
			ColorIndexToRGB(Colour, Red, Green, Blue);		{Get the RGB values from the index}
			RGBToColorIndex(Red, Green, Blue, Check);		{Translate back to an index}

				{--- Compare the two indices and write any discrepancies to the array ---}
			IF Colour <> Check THEN
				BEGIN
					Discrepancies[ArrayPointer] := Concat(Colour, ' / ', Check);
					ArrayPointer := ArrayPointer + 1;
				END;
		END;

	Message('Completed.');
END;

Run(ColConv);

To use the script put a break on the message line, start execution and then, when the script stops at the break, read the contents of the array, the results of which are shown here:

The array discrepancy listing

Taking this data and sorting it into a more convenient form we get this list of 16 pairs of duplicate colours:

2 144
3 166
4 37
5 69
6 149
7 171
16 125
21 65
26 142
27 130
31 96
32 127
35 232
44 201
155 206
158 45

We can now show the mappings on the standard palette itself to make it clearer what is happening:

Duplicated colour pairs
.

Most of the duplicated colours map from colours which are in the group of locked system colours but not all: 45-158 and 155-206 lie outside of that group.

What this data is saying is that if you convert a palette colour to RGB then convert it back to a colour index, for 16 of them you will receive a different result, but the colour is the same.

[ What is the significance of the Mac colours? ]

Another oddity is that colour indexes are not allocated to the palette sequentially and quite a few are out of position (11 in fact) such as 255 and 254 in the top left and 1 in the bottom right. Why this should be so needs to be explained by NNA and is probably due to some scheme devised long ago in a galaxy far away. Anybody?

Having the saturated colours clustered in the top left certainly has usability advantages but does not explain the duplicates.

The shifted indexes

The consequence of the shifted indexes is that one cannot sequentially traverse the palette in any direction and be guaranteed of a darker or lighter shade relative to your starting point - which is annoying.

There does not appear to be a relationship between these out of position indexes and the duplicated colours. Some are involved but not all. This is probably because the relationship between the index and the colour to found there is completely arbitrary due to the ability to create a custom palette where the index position is invariant (no matter what colour you assign to the bottom left of the palette, it will always be cell 240).

What duplicated colours imply for VectorScript coding

When using the standard palette, the duplicated colours will obviously have implications for your code because, for the exceptions found above, you cannot assume that setting the colour of a fill or line will return the same index value later. It means that you cannot reliably use colour as an attribute for message passing between scripts unless you use a lookup table containing the values above that change or always use the RGB values for your tests.

Colour quantisation

The palette colour choices also have a quantisation effect upon colours that you specify with a call like SetFillBack. You may assume from the ever terse function description that you can set any colour you like by specifying any of the available RGB values and that the object will then take your setting. In reality, VectorWorks substitutes the nearest colour in the palette to the one you actually asked for. This means that no colour can exist in the document that is not already included in the colour palette. A VectorWorks document is therefore (images apart) limited to displaying a maximum of 256 different colours - the ones in the current palette, no matter what RGB values you pass to calls such as SetFillBack.

To try it, run this script which attempts to assign an RGB value not in the standard palette:

PROCEDURE MakeMyDay;
VAR
	Red, Green, Blue: LONGINT;

BEGIN
	SetFillBack(FSActLayer, 52428, 39321, 26224);
	GetFillBack(FSActLayer, Red, Green, Blue);
	Message(Red, ' / ', Green, ' / ', Blue);
END;

Run(MakeMyDay);

Furthermore, the colour index that you pass to ColorIndexToRGB only defines a fixed position in the palette and not necessarily a colour. Anything could be in that position if the palette is not the standard issue.

The implications of custom palettes for scripting

It gets even more interesting when you take custom colour palettes into account.

It is possible, though eccentric, that a user could build an entire palette with just one colour (duplicate colours are permitted when editing the colour palette) - then where will your colour handling script be?

For those scripts that use colour in a critical way, there is a reasonable case to be made to analyse the current palette before assigning or testing colours and changing the behaviour of the script accordingly if you think custom palettes might be involved.

Reading the actual RGB values and comparing them with a table of values expected to be there might be a good defensive position for these kinds of scripts.

Interestingly, if you assign colours to objects in a document using the standard palette then customise those same colours, VectorWorks will attempt to reassign a colour from somewhere in the new palette to the existing objects which is close to the one it previously had and not the one you changed in the modified palette. For existing documents this adds another unpredictable element to using colours in scripts.

If your script assumes a certain colour green will be applied from an index in the standard palette but the user has customised it, then they will get the colour at that position for new objects and existing objects will be shifted to some other index to try to keep them looking the same. Always specifying an RGB value seems like the closest way to get the colour you want but it is by no means a guarantee.

Here is a summary of the related colour utilities to be found in VectorWorks 12.5 - from the manual:

To change the default color palette:

  1. Ensure that no objects are selected.
  2. Select File > Document Settings > Color Palette - The Edit Color Palette dialog box opens.
  3. Select a color to edit and then adjust its values.
    Create a VectorWorks file that contains only an edited color palette to import into other drawings as needed.
  4. Click OK.

This creates a custom palette for the document in which it resides. Now you have a different set of 256 (or less) colours to play with and all bets are off as to the relationship of the colour index to the actual colour at that location.

Creating a Color Chart

This command creates a color chart in the active layer of the current file that reflects the colors in the color palette of the document. It can be used as a print color guide. To create a color chart:

  1. Select Tools > Utilities > Create Color Chart
  2. Confirm that a color chart of the active layer in the current file should be generated.
    If desired, select Show color palette index numbers to show the color index numbers in the chart.

The index numbers are internal to the color palette and always remain in the same order.

What you see after you click OK is the current palette drawn in the active layer with every colour labelled with its ID. If the labels are too small to read, select the new object and choose a new text size - 12pt is a good start. If the document is new, this object is the same as the one shown in the VectorScript appendix. If you have created a custom palette then this is what will be created by this command.

Creating a Color Value File

This procedure creates a text file listing the RGB and HLS values of the color palette contained in the current file. To create a color palette file:

  1. Select Tools > Utilities > Read Color Palette
    The Read Color Palette dialog box opens. Confirm that a text file should be created, listing the RGB and HLS values of the color palette in the current file.
  2. The Save File dialog box opens. Specify a file name and location.
  3. Click Save. The operation is confirmed with a message box.

The partial listing from the text file thus created looks like this with VectorWorks 12.5:

Palette Position Color Value - RGB Color Value - HLS
Row Col index R G B H L S
1 1 0 65535 65535 65535 0.00 1.0000 0.0000
1 2 255 0 0 0 0.00 0.0000 0.0000
1 3 2 0 65535 65535 180.00 0.5000 1.0000
1 4 3 65535 0 65535 300.00 0.5000 1.0000
1 5 4 0 0 65535 240.00 0.5000 1.0000
1 6 5 65535 65535 0 60.00 0.5000 1.0000
1 7 6 0 65535 0 120.00 0.5000 1.0000
1 8 7 65535 0 0 0.00 0.5000 1.0000
1 9 8 32896 32896 32896 0.00 0.5020 0.0000
1 10 9 41120 41120 42148 240.00 0.6353 0.0215
1 11 10 65535 64507 61680 44.00 0.9706 1.0000
1 12 11 577 43860 60159 196.41 0.4634 0.9810

etc.

This is another way to observe the duplicated colours in the standard palette and also a way to potentially analyse the colours in the current palette.

This is also typical of the asymmetry one often gets with VectorWorks - there is no method to build a colour palette from values in a file, which would be very handy.

Converting Color Values

This command converts a color value expressed in RGB format to a color value expressed in HLS format, or vice versa. Either format can be expressed integrally or as a percentage. To convert color values:

  1. Select Tools > Utilities > Convert Color - The Convert Color dialog box opens.
  2. Select the Color Depth, and then enter a value in RGB or HLS color format. The corresponding values are displayed.
  3. Click Use Percentages to get the percentage values for either format.
  4. Click OK when finished.

This tool does a very similar job to the Mac colour palette, giving equivalent values for the different colour systems.

Proposal for a new palette that has no duplicates

It should be possible to construct a palette which contains 256 unique colours and groups them in a way that makes it easier to choose them manually and programmatically.

Ideally, for the main colour swatches, it should avoid columns and rows where shifted indexes reside so the progression is sequential. I would think that the rows beginning 48-224 are ideal for creating grey scales, RGB tints, earth and land colours etc. With such a palette you could more easily find the right colour and also use scripts to move up and down the tints in each row in a logical way. This is also an opportunity to stretch the scales so that some very light tints can be added.

This is a little project which might have been already solved, so if you already have such a palette it would be great to share it here and examine the pros and cons.

In conclusion, the standard colour palette is an array of 256 non-unique colours with non-sequential indexes which define the only colours objects can have in the document. The mechanism of quantising ensures that your RGB colour choices are only applied unchanged if they match one of the palette colours and if not they may be altered in ways that might be unexpected.

Standard color palettes from previous VW versions

By Raymond Mullin

MiniCad+ 2-3 MiniCad+ 4 - MiniCad 5 MiniCad 6
ColorPalette MC2-3.jpg ColorPalette MC4-5.jpg ColorPalette MC6.jpg
MiniCad 7 VectorWorks 8 VectorWorks 9-12
ColorPalette MC7.jpg ColorPalette VW8.jpg ColorPalette VW10-12.jpg

The "Gradients Trick"

by Matt Panzer

Creating Precision Colors by Using Gradients as Solid Colors

VectorScript cannot create the exact color you requested by using Red, Green, Blue (RGB) values. The only thing that can be done is to have VectorWorks map the RGB values to the closest equivalent color on the document’s 256 color palette. The results are less than satisfactory and are usually not very useable.

There is another option for 2D object fills and that is to create a gradient that uses only one color. My first incarnation of this trick was to create a gradient with the 2 segments both at position 1. This worked fine for the purpose, but when a user needed to edit the color, choosing the right segment to edit was a bit cumbersome. This is because the segments are atop one another – making the desired segment difficult to select. I refined this method by simply making two segments the same color. Both methods work, but the latter allows easier segment selection, however it also requires both colors to be edited.

Creating solid gradients gives you custom colors to which you can give meaningful names. Custom named colors is a much-needed feature in VectorWorks, but with this technique we have them now (at least in a limited way). As I mentioned, solid gradients can only be used as 2D fills (not as pen colors, nor for 3D fills).

Doodle 9

The image above was created using Doodle 9 (written in VectorScript) in VectorWorks 9 (before gradients). The “marker” stroke color is an existing color from the 256 color palette. The script’s task was to find (and use) a darker color of the same hue behind the strokes. This is the result of VectorWorks trying to map specific RGB values to the document color palette. The result is not acceptable, in my opinion.

Doodle 9

This image was created using Doodle 12 in VectorWorks 12 (the same results are seen with VectorWorks 10 and 11). The script’s task is the same. The difference is that Doodle 12 created a solid gradient rather than rely on the limited number of colors on the palette. As you can see, this result is spot on!

Using Solid Gradients brings a much higher level of color ability to VectorWorks for 2D illustrations. Plus, you can name the color so you’ll know what it was for (a paint color, sky color, etc.). It seems odd to have such accurate gradient color control with virtually unlimited colors, when the rest of the programs basic color ability is so terribly limited.

Solid gradient's script

The script below creates a Solid Gradient according to the RGB value constants. The gradient will be named Solid (and appended with the color's RGB values).

PROCEDURE CreateSolidGradientProc;
{
Created by Matt Panzer, PanzerCAD Services, Inc.
June 14, 2007
}

{
Each RGB constant value is to be between 0 and 255.
}
CONST
kRedValue		=	255;
kGreenValue		=	0;
kBlueValue		=	0;

VAR
GradientIndex			: INTEGER;
GradientSegmentIndex	: INTEGER;
GradientHand			: HANDLE;
GradientName			: STRING;

BEGIN
	GradientName := ConCat('Solid ', Num2Str(0, kRedValue), '-', Num2Str(0, kGreenValue), '-', Num2Str(0, kBlueValue) );
		
	GradientHand := GetObject(GradientName);
	
	IF GradientHand <> NIL
	THEN AlrtDialog('An object of this name already exists! This operation will cancel.')
	ELSE
	BEGIN
		GradientHand := CreateGradient( GradientName );
		
		FOR GradientSegmentIndex := 1 TO 2
			DO SetGradientData( GradientHand, GradientSegmentIndex, 0, 0.5, kRedValue, kGreenValue, kBlueValue );
		
		AlrtDialog(Concat('A gradient named ''', GradientName, ''' has been crated.'))
	END;
END;

RUN(CreateSolidGradientProc);

Searching the needle

Fascinated by the article of Joel, I wished to analyze a bit what for a history the colors have. Researching from scratch, being by no means wise enough about colors, I came out with some answers. Hoping someone with true answers to jump in, I start, as usual keep in mind a permanent "Under construction" as to what follows... By Orso b. schmid

RGB 3-bit

The first 8 values of the VectorWorks colour palette contain the standard 3-bit RGB colors:

basic 3-bits colors
Color
Name white black cyan
(aqua)
magenta
(fuchsia)
blue yellow green red
Hex value FFFFFF 000000 00FFFF FF00FF 0000FF FFFF00 00FF00 FF0000
Binary value 111 000 011 101 001 110 010 100

RGBI 4-bit (VGA standard colors)

Windows has reserved 20 of the 256 colors for title bars, menu bars, etc. so that their colors stay the same for different applications; these colors are usually not changed by applications. 16 of the colors (marked with thick black squares) consist of full-intensity (light) and half-intensity (dark) versions of the primary colors and their combinations, plus white, black, and two shades of gray, reminiscent of the 16 colors hard-wired into CGA displays: frequently called VGA graphic palette.

Windows' ButtonFace, ButtonShadow, and ButtonHilight colors (marked with thick red squares), may be changed in the Display Properties/Appearances section of the Control Panel.

An official description of Window's system colours can be found at Microsoft Developer Network.

16 Windows reserved colors + 4 buttons colors.

Gray scale

A gray scale set of 12 colors excluding white (FFFFFF) and black (000000) is positioned at the end of the "blocked" colors:

grayscale
Note
A simple algorithm for converting a whatever color to grayscale is:
0.3 * red 0.59 * green 0.11 * blu
The luminance of a color is calculated as follows:
luminance = (0.30078125 * color.r ) + (0.58984375 * color.g ) + (0.109375 * color.b )

See Also

Further reading

Color lists