rgbscript 0.6 README.txt


USER INFO

U1. Rgbscript How To

Prints a color spectrum on an Inkscape page as a series of fields, each with its own color. The
field size depends on the number of fields specified {fieldnum}. Fields maye be separated {fieldsep}
and/or skipped {fieldskip}. An initial color may be specified {startcolor}: blue (0x0000ff), green
(0x00ff00) or red (0xff0000). The default initial color is red. It determines the colors produced in
the first (top) field set. After the field set for this color has been printed, the code will switch
to the next color. The default sequence for printing field sets is R-B-G: a red(dish) set in top,
followed by a blue(ish) one and a green(ish) one after that. Depending on the number of fields
specified, the procedure is then repeated.

The default R-B-G rendering can be changed to R-G-B by setting {swapgb}. In some cases a start color
of red will result in a yellow first field. This is because of the fact that the G (green) bytes are
also initially set high. The level of opacity of the fields printed can be specified with
{fieldopacity}.

RGB byte pairs are incremented or decremented by a specified amount {colorstep; default: 0x33}. The
script will keep iterating through the range of colors in a circular fashion until the specified
number of fields is reached. The field size is calculated dynamically from the page size and the
number of fields (as well as a separator, if specified). This means that after the script has been
executed, the entire page should be filled (with some margin due to rounding of values). In some
cases the output will exceed the page boundaries.

No warnings or error messages are ever issued, nor will the script ever exit because of for example
a mangled user-supplied value. Any such errors will show up on the screen as garbled (and at times
interesting) output. Blacked out fields are a sure sign of invalid input.

RGB colors can be represented by hexadecimal byte pairs like 0x37 or 0xff. These byte pairs are at
the heart of rgbscript's processing. The script does not know, and does not want to know about
decimal RGB values like (324, 11, 215). It favors the elegance of 'hex'. Maybe in a future version
a conversion routine will be added. A more useful thing to have for now would be a configuration
parser, which would allow for the settings to be stored in a separate file.

The colors displayed on the screen can be inverted with {invertcolors}. A background color will
be printed if {showbackground} is set; its color can be specified with {backgroundcolor} (the
background can still be hidden in Inkscape from the Layers tab). The default background color is
white.

The script can be run over and over again against a single Inkscape page. Not setting a bakground
(or only setting one during the first run) can yield interesting overlaps in combination with
field skipping {fieldskip, fieldoffset}. Field separation {fieldsep} is used for separating
output fields, which tends to ENORMOUSLY enhance the aesthetics of the output (it really is a world
of difference).

Perhaps the most useful option for altering the standard behaviors is {turnaround}. It will limit
the scope of colors printed, and can lead to quite wonderful results. The default value is
0xff (the 'ceiling' value) divided by the {colorstep}. Any value higher than this would result in an
overflow of RGB values, and it is therefore automatically limited to this value.

Rgbscript supplies five different so-called color sets, specified with {colorset}. If no color set
is specified, the 'standard' color set is used. The color sets are:

standard		rather straightforward reds, greens and blues; this is the only set with a
			smooth transition between colors 
high			somewhat pale and grayish colors
bright			neon-like colors
dark			yellow/magenta/cyan; these start bright, but quickly plunge into almost black
primary		like 'dark', but red/blue/green instead.


More information about colors rendered is found in section M3 of the Maintainer Info part of this
text. Feel free to ignore the diagrams and details.

The settings marked as 'exotic' can be considered experimental. None of these can be expected to
render anything meaningful or of any particular interest. The functionality of some of these
settings overlaps. Field blackout and other signs of overflow/underflow can be prevented by setting
{wrapcolors}, but the overall picture may look just as erratic, and the resulting colors won't
necessarily display any underlying logic.

Operation can be fairly complex because of the way in which different features interact. Some
combinations will work, others won't. Many possible combinations of values do not even make logical
sense. Getting one's mind around the various interactions may take time and experimentation.


U2. Configurable parameters

Color settings
colorset		the color set to use for this run
startcolor		initial color: 'red', 'green' or blue; 'red' is the default.
invertcolors		invert the colors?
colorstep		the value by which RGB bytes are incresed/decreased on every run
turnaround		the number of increments/decrements using colorstep before switching to the 
			next color; this limits the scope of change for each color
swapgb			print R-G-B instead of R-B-G?
showbackground		print a background?
backgroundcolor	color of the background layer
printvalues		print a list of color values before printing output?

Field settings
fieldnum		the number of fields to be printed; >>> THE ONLY REQUIRED SETTING <<<
fieldopacity		sets the opacity of the field printed
fieldsep		field separation in the Inkscape output, in pixels
fieldskip		number of fields to skip between two printed ones
invertskip		inverts the skipping
skipoffset		the position to start showing fields from; this is only used in combination
			with field skipping; the value should be less or equal to fieldskip

Exotic ('never mind') settings:
rgbthreshold		value at which to declare underflow
rgbceiling		value at which to declare SWITCHTIME
wrapcolors		will 'wrap' color values exceeding the 000000-ffffff range
			affects the entire RGB triplet; much a best-guess effort
gluefields		(in development)
fitfields		with gluefields: fits fields onto the page

--------------------------------------------------------------------------------------------------
Example:
fieldnum = 45
colorstep = 0x11
startcolor = 'green
invertcolors = 'yes'
fieldsep = 4
turnaround = 5
--------------------------------------------------------------------------------------------------

One reason why there are so many options is that in this case the developer uses their own software
(wouldn't it be great if that were always the case?). Each of these settings has proven very useful.
For the same reason, the code has reached a high level of stability.


U3. Known bugs

- turnaround only works with standard color set


====================================================================================================



MAINTAINER INFO


M1. Quick demonstration of principles by example

Probably the best way to introduce the rgbscript internals is by concrete examples using actual
RGB color codes. RGB color values are represented by byte pairs, like 0x99. These will be referred
to as such below. Wherever it is clear from the context that hexadecimal numbers are being
referred to, 0x99 may also be simply be called '99'.

-------------------------------------------------------------------------------------------
Important: the terms [RGB] byte pair, RGB value and RGB color all refer to the same thing,
only from different perspectives. In some cases even short forms like 'pair' will be used.
-------------------------------------------------------------------------------------------

All examples below assume red as the start color, which is the default. Other start colors are
handled analogously. Sticking with red for the examples should provide some consistency and avoid
confusion. There is plenty of that already in the very principles covered.


A run table for standard colors, starting with red (ff0000), with a colorstep of 0x33 and no fancy
settings looks as follows:

F  display	+l -r		color

1  ff0000	+B -R		red
2  cc0033	+B -R
3  990066	+B -R
4  660099	+B -R
5  3300cc	+B -R			switch

6  0000ff	+G -B		blue
7  0033cc	+G -B
8  006699	+G -B
9  009966	+G -B
10 00cc33	+G -B			switch

11 00ff00	+R -G		green
12 33cc00	+R -G
13 669900	+R -G
14 996600	+R -G
15 cc3300	+R -G			switch

16 ff0000	+B -R		red			<- back to start value

Hex byte pair values are multiples of 00, 33, 66, 99, cc, ff (dec 51, 102, 153, 204, 255), which
means that the colors rendered belong to the ancient 'web safe' ones.

More or less visualized (F is field number, starting with 1):

F  		00   33  66  99  cc  ff

1  ff0000	GB                   R 
2  cc0033	G    B           R
3  990066	G        B   R
4  660099	G        R   B 
5  3300cc	G    R           B

6  0000ff	RG                   B
7  0033cc	R    G           B
8  006699	R        G   B 
9  009966	R        B   G
10 00cc33	R    B           G

11 00ff00	BR                   G
12 33cc00	B    R           G
13 669900	B        R   G
14 996600	B        G   R
15 cc3300	B    G           R  

16 ff0000	GB                   R			<- back to start value

It is clear that only a tiny subset of the possible byte combinations, i.e. colors, is generated.
The highest amount of colors rendered, with an increment value of 1, is 255 (R) + 255 (G) + 255 (B)
= 765. In particular, the algorith misses out on several key RGB combinations: values like 000000
(black), ffffff (white) or, more importantly, ff6600, which is the web idea of orange, are never
reached. Being unable to render even a secondary color can be considered a shortcoming, since it
severely restricts what could be called the 'spectral space'. This space is already expanded by
supplying different color sets. Combining the results from these sets can be considered a TODO.

For the 'high' color set the bigger picture looks quite similar.

F:		00  33  66  99  cc  ff

1  ffff00	B                   RG 
2  cccc33	     B           RG
3  999966	         B   RG
4  666699	         RG  B 
5  3333cc	   *R*G          B

6  ff00ff	 G                   B*R*		<- byte pair recharge for R
7  cc33cc	     G           BR
8  996699	         G   BR
9  669966	        BR  G
10 33cc33	  *B*R          G
11 00ffff	R                   G*B*		<- byte pair recharge for B

12 33cccc		    R           GB
13 669999	        R   GB
14 996666	        GB  R
15 cc3333	  *G*B          R  

16 ffff00	 B                   R*G*		<- byte pair recharge for G: back to start value

The color codes marked with asterisks (*) show a jump in the value during recharging: instead of
becoming 00 (after 33) it is reset to ff for the next color run. This causes a 'jolt' between field
sets in the output. This jolting will become even more dramatic with the color sets which follow.

The flow for the primary color set, for example, is as follows:

F	value		00  33  66  99  cc  ff

1:	ff0000		GB                  R		<- R set high at initialization
2:	cc0000		GB              R
3:	990000		GB          R
4:	660000		GB      R
5:	330000	        GB  R

6:	0000ff		RG                  B   	<- recharge of B
7:	0000cc		RG              B
8:	000099		RG          B
9:	000066		RG      B
10:	000033		RG  B

11:	00ff00		BR                  G   	<- recharge of G
12:	00cc00		BR              G
13:	009900		BR          G
14:	006600		BR      G
15:	003300		BR  G

16:	ff0000		GB                  R   	<- recharge: back to initial value

The recharges generate a sawtooth motion through the available values, which gives the output a
bumpy quality, even more so than with high colors. For a smooth transition between color field sets,
'glue fields' would need to be inserted. This is a major TODO.

The high colors feature doesn't expand the output color space, it merely alters it: the result is
the exact same number of possible output colors as with the standard color set. The same key colors
mentioned above, like orange, are still beyond reach.


M2. RGB to LMR mapping

LMR refers to a set of index pointers to elements of the RGB list, which allow the script to rotate
through the list and offer a level of abstraction.

The names of these indices are:

lindex		left index, points to whichever serves the role of 'left' byte pair
mindex		middle index, points to whichever serves the role of 'middle' byte pair
rindex		right index, points to whichever serves the role of 'right' byte pair

The role played by a byte pair at any given time determines the way in which it is handled: the
value may be incremented, decremented, or the byte pair is ignored. Most notably, a byte pair's
role determines its final value before a switch, described shortly.

The way in which RGB byte pairs are initially mapped to LMR indices depends on the start color:

Start color:	L:	M:	R:
red		R	G	B
green		G	B	R
blue		B	R	G

This is the initial mapping. It is the only occasion on which 'LMR meets RGB'. After this, only
LMR matters. Initialization is performed by anchoring the L index to a specific byte pair (color).
The remaining indices are set relative to L. There are occasions (with the swapgb parameter set) on
which the LMR scheme changes to LRM (see below: '4. LMR vs LRM, or: the R-B-G versus R-G-B output
issue'). This case isn't covered in the following examples, since it is a mere administrative issue,
and has no effect on the principles of operation which are to be explained.

Once a particular RGB color has been processed a 'switch' occurs: the code moves to the next
color in the list. During these switches the entire set of LMR indices is shifted one position to
the left (default) or right (with swapgb), causing each to point to what was previously an adjacent
RGB byte pair (color).

To visualize the initial mapping for red as the start color:

LMR:            L              M              R
         -------------- -------------- --------------
RGB:    |       R      |       G      |       B      |
         -------------- -------------- --------------

With startcolor = 'green', it looks like follows:

LMR:            L              M              R
         -------------- -------------- --------------
RGB:    |       G      |       B      |       R      |
         -------------- -------------- --------------

A left shift of the LMR indices yields the following picture for red:

LMR:            M              R              L
         -------------- -------------- --------------
RGB:    |       R      |       G      |       B      |
         -------------- -------------- --------------

This shifts L to point to blue, and since L is the determinant index, this means that a blue set of
fields will be printed. Another shift yields green:

LMR:            R              L              M
         -------------- -------------- --------------
RGB:    |       R      |       G      |       B      |
         -------------- -------------- --------------

This is equivalent to the picture shown for startcolor green. During execution the set of LMR
pointers keeps rotating through the RGB set this way. The code focuses on these pointers and is
completely oblivious to RGB colors.


At initialization time, the L byte pair is always set high, regardless of color set and start color.
The initial value of the other RGB byte pairs depends on the color set selected:

		L	W	R
standard	ff	00	00
high		ff	ff	00
bright		ff	ff	00
dark		ff	ff	00
primary	ff	00	00


The distinction between these color sets is determined by the initial value, as well as by the way
in which this value is subsequently handled:

		L	W	R
standard	--		++
high		--	--	++
bright			--
dark		--
primary	--

Mind-boggling? These things will become perfectly clear by looking at the different ways in which
the RGB byte pairs are handled with each color set.


M3. Color sets

With an increment/decrement value {colorstep} of 0x33, the default, five different fields are
printed before each switch (these are clearly hex numbers):

00 + 33 = 66
33 + 33 = 66
66 + 33 = 99
99 + 33 = cc
cc + 33 = ff

At this point these is nowhere else to go, since the topmost value an RGB byte pair (and of any byte
pair of course) can represent is is 0xff, or decimal 255. The same story for an initial value
being decremented in steps from 0xff to 0x00.

As said, which byte pairs are set initially and changed afterwards, and in which way, depends on the
color set selected. There are five different color sets: standard, high, bright, dark and primary.
Each renders its distinct set of colors.

The color sets will be covered in terms of LMR rather than specific colors. A single LMR iteration
may apply to any of the RGB ones shown above. It can be considered RGB-neutral.


M3.1 Primary colors

00  33  66  99  cc  ff
MR                  L
MR              L
MR          L
MR      L
MR  L
(M*R*L)			<- value at switch, not printed (this would be 0x000000: black)
MR                  *L*  	<- switch: recharge the old R byte pair (blue) as the new L

This is the simplest procedure of them all: it simply sets one byte pair high and decrements it.
It does require a 'recharge' of the L pair however, which involves setting the value high (0xff)
for the next color:

Index:		Color:		Init value:	End value:	Next color:	Init value:
L		red		ff		00		blue		*ff*	    <- recharge
M		green		00		00		red		00
R		blue		00		*00*		green		00

In other words, at switch time all byte pairs are 00, whereas an *ff* is required for the blue new L
pair. This done manually, so to speak: there is no natural flow of one set of values into another.
The entry for 'standard' colors will show that not in all cases is such a recharge required.

The value 0x000000/black, the 'sixth color', is intercepted by the recharge performed during the
switch, which sets the old R pair, now the L pair (with start color red and a left shift: blue, so
far left 00), high. It therefore never gets shown in the output.

Consisting of only one byte pair (RGB color), these 'primary' colors (which they are indeed: they
show up as red, green and blue) start out looking bright and clear, but quickly veer off toward black
with each successive iteration.

If all this seems confusing: it is. ENORMOUSLY.


M3.2 Standard colors

00   33  66  99  cc  ff
MR                   L
M    R           L
M        R   L
M        L   R
M    L           R
(ML)                 (R)	<- value at switch: the next 'pure' color, e.g. red -> blue
MR                   L		<- no recharge, a shift is enough; 'pure' color is printed

Index: 	Color:		Init value:	End value:	Next color:	Init value:
L		red		ff		00		blue		ff
M		green		00		00		red		00
R		blue		00		ff		green		00

This simultaneous increment of one byte pair while decrementing another formed the initial
challenge for writing the script.

The switch requires the blue byte pair to be high, which is already naturally case, since it was
incremented as the old R pair. No recharge is therefore needed. Note that, from a coding perspective,
this does involve a degree of implicit behavior: the value is _assumed_ high, and is never tested as
such (this is where the LMR vs LRM issue, described later, plays up).

Again, with start color red and a left shift, the old R pair was blue, which now becomes the L one.
This time, with a recharge skipped, rather than being intercepted (iverwritten), the 'sixth color'
gets to serve as the first of the next field set.

Also note that in this case too the M pair remains 00 throughout, which means that none of the
colors produced contain any white (which may manifest itself as grayish tones), for in an RGB scheme
white requires all RGB values to be non-zero. The result are again clear colors.

With these two color sets the main principles of the script's operation (increments and decrements,
switches, recharges) have been covered. The other color sets are no more than variations on these
principles.


M3.3 High colors

00  33  66  99  cc  ff
R                   LM
    R           LM
        R   LM
        LM  R
    LM          R
(LM)                (R)	<- value at switch, not printed (e.g. 0x0000ff: 'pure' blue)
R                   LM   	<- recharged to low/high/high (e.g. 0xff00ff: magenta)

High colors run the same way as standard colors, but with the M pair set high and decremented along
with the L one. The result is a lot of white, which shows itself in a rather grayish output.

Index:		Color:		Init value:	End value:	Next color:	Init value:
L		red		ff		*00*		L blue		ff
M		green		ff		00		M red		*ff*	    <- recharge
R		blue		00		ff		R green	00


M3.4 Bright colors

00  33  66  99  cc  ff
R                   LM
R               M   L
R           M       L
R       M           L
R   M               L
(RM)                (L)	<- value at switch, not printed (e.g. 0xff0000: 'pure' red)
R                   LM   	<- recharged to low/high/high (e.g. 0xff00ff: magenta)


These 'bright' colors do live up to their name: their intrusiveness and blatancy matches that of
so-called neon colors. A lack of any white (in this case the R pair remains 00) causes them to look
clear, and their lightness adds a brilliancy not found in any of the other sets. This lightness is
provided by the L pair, which remains at its highest value throughout.

This is the only color set in which ff6600/orange appears.

Index:		Color:		Init value:	End value:	Next color:	Init value:
L		red		ff		ff		blue		*ff*	    <- recharge
M		green		ff		00		red		ff
R		blue		00		00		green		00


M3.5 Dark colors

00  33  66  99  cc  ff
R                   LM
R               LM    
R           LM        
R       LM            
R   LM
(LMR)				<- value at switch, not printed (again 0x000000: black)
R                   LM   	<- recharged to low/high/high (e.g. 0xff00ff: magenta)

This set produces an output very similar to that of the primary color set. Rather than a single
byte pair, two adjacent ones are initially set high, and decremented. As two-color creations, these
'dark' colors start out looking vivid, without any graytones, and as with the primary colors they
rapidly plunge into darkness. The colors rendered are the logical complements of the 'primary' ones:
yellow vs blue, cyan vs red, magenta vs green. 

Index:		Color:		Init value:	End value:	Next color:	Init value:
L		red		ff		00		blue		*ff*	    <- recharge
M		green		00		00		red		*ff*	    <- recharge
R		blue		ff		00		green		00

The fact that yellow appears in the high, bright and dark color sets may give rise to confusion,
since it is a secondary color both in real life (i.e. with pigments) and in an RGB scheme. It may
suggest that other secondary colors appear in these sets as well, which is not the case. The web
colors labeled secondary, apart from 0xffff00 (yellow), are 6600ff (purple) and 0xff6600 (orange).
These only happen to appear in the 'bright' color set.


M4. LMR vs LRM, or: the R-B-G versus R-G-B output issue

A left shift of the indices automatically results in blue coming after red, green after blue, red
after green. As a result, the output follows a R-B-G scheme: red in top, followed by blue and then
green, and back to red (all of course depending on the number of fields available). Turning this
into R-G-B would seem straightforward: just perform a right shift of indices instead: green will
follow red, blue follows green and after blue the output returns to red.

It is not that simple, however, since a mere change in shift direction doesn't take into account
the roles byte pairs play as L, M or R pairs. This can best be demonstrated by looking at the
results of the two types of shift.

Left shift:

initial indices			L	M	R
after a left shift			M	R	L

M points to previous L			has for example been decremented to 00
R points to  previous M		has for example been incremented to ff

Right shift:

initial indices			L	M	R
after a right shift			R	L	M

M points to previous R			has for example been incremented to ff
R points to previous L			has for example been decremented to 00

Now, if the code says 'increment M and decrement R', this will lead to the desired result with the
left shift. With the right shift it will generate erratic values, such as ff+11 or 00-33, clear
cases of overflow and underflow, respectively.

An exchange of the R and M indices is therfore required as well. This will effectively take into
account the different PREVIOUS roles played by the byte pairs pointed to.

Depending on the color set in question, various different side effects will show in the output. In
some cases very interesting colors are produced, which may very well serve as a basis for creating
new color sets at some point in the future.