"[S]eparate the calculation phase from the colouring phase"—Claude Heiland-Allen

# Theory

## How to use color in your program

First

Steps:

• check your data ( type, range)
• check color profiles of your graphic devices
• Device calibration
• choose what feature of the data you want to highlight
• check the result/ optimize it

### colour management

• profile of each graphic device (scanner, digital camera, monitor and printer) and operating system

rendering intent

• perceptual rendering: images will be reproduced on prints or displays
• colorimetric intent: images will be simulating one device on another such as a print on a display ( proofing)
• saturation intent: business graphics with maximum colourfulness on the print

color fidelity refers to the successful interoperability of color data, from image creation to output across multiple targets, such that color reproduction quality consistent with the user’s intent can be achieved

### color profile

ICC:

• a 3x3 matrix
• a one-dimensional tone curve for each colour channel
• a thre-dimensional look-up table (LUT)
• a second 1D tone curve for each channel

iccmax

### color space

• color space[1]
• discrete samples from color space
• CMS = Color Matching System = industry standards in the classification of spot color systems
• manufactures and their color charts

List[2]

• CMY
• CMYK
• HSL
• HSB
• HSV
• CIE L*AB
• Hunter LAB
• OK LAB: A perceptual color space for image processing
• LCH(uv)
• LCH(OK)
• LUV
• RGB
• XYZ
• YXY

#### RGB

Types

• linear RGB ( non-corrected )
• The gamma-corrected color spaces = non-linear
• sRGB: A Standard Default Color Space for the Internet[3]
• DCI P3
• Display P3 ( wide color gamut)

#### OKLAB

A color in Oklab is represented with three coordinates Lab:[4]

• L – perceived lightness ( a unitless number in the range [0,1] )
• a – how green/red the color is
• b – how blue/yellow the color is

It's corresponding polar form is called Oklch.

The standard coordinate can also be transformed into polar form ( Lch), with the coordinates:

• L = lightness
• c = chroma
• h = hue
${\displaystyle C={\sqrt {a^{2}+b^{2}}}}$
${\displaystyle h^{\circ }={\text{atan2}}(b,a)}$

In reverse direction:

${\displaystyle a=C\cos(h^{\circ })}$
${\displaystyle b=C\sin(h^{\circ })}$

Converting from linear sRGB to Oklab in c++

// https://bottosson.github.io/misc/ok_color.h
struct Lab {float L; float a; float b;};
struct RGB {float r; float g; float b;};

Lab linear_srgb_to_oklab(RGB c)
{
float l = 0.4122214708f * c.r + 0.5363325363f * c.g + 0.0514459929f * c.b;
float m = 0.2119034982f * c.r + 0.6806995451f * c.g + 0.1073969566f * c.b;
float s = 0.0883024619f * c.r + 0.2817188376f * c.g + 0.6299787005f * c.b;

float l_ = cbrtf(l);
float m_ = cbrtf(m);
float s_ = cbrtf(s);

return {
0.2104542553f*l_ + 0.7936177850f*m_ - 0.0040720468f*s_,
1.9779984951f*l_ - 2.4285922050f*m_ + 0.4505937099f*s_,
0.0259040371f*l_ + 0.7827717662f*m_ - 0.8086757660f*s_,
};
}

RGB oklab_to_linear_srgb(Lab c)
{
float l_ = c.L + 0.3963377774f * c.a + 0.2158037573f * c.b;
float m_ = c.L - 0.1055613458f * c.a - 0.0638541728f * c.b;
float s_ = c.L - 0.0894841775f * c.a - 1.2914855480f * c.b;

float l = l_*l_*l_;
float m = m_*m_*m_;
float s = s_*s_*s_;

return {
+4.0767416621f * l - 3.3077115913f * m + 0.2309699292f * s,
-1.2684380046f * l + 2.6097574011f * m - 0.3413193965f * s,
-0.0041960863f * l - 0.7034186147f * m + 1.7076147010f * s,
};
}


#### CMS

Spot color classification has led to thousands of discrete colors being given unique names or numbers. There are several industry standards in the classification of spot color systems, such as:

• PANTONE, the dominant spot color printing system in the United States and Europe.
• Toyo, a common spot color system in Japan.
• DIC Color System Guide, another spot color system common in Japan – it is based on Munsell color theory.[5]
• ANPA, a palette of 300 colors specified by the American Newspaper Publishers Association for spot color usage in newspapers.
• GCMI, a standard for color used in package printing developed by the Glass Packaging Institute (formerly known as the Glass Container Manufacturers Institute, hence the abbreviation).
• HKS is a color system which contains 120 spot colors and 3,250 tones for coated and uncoated paper. HKS is an abbreviation of three German color manufacturers: Hostmann-Steinberg Druckfarben, Kast + Ehinger Druckfarben and H. Schmincke & Co.
• RAL is a color matching system used in Europe. The so-called RAL CLASSIC system is mainly used for varnish and powder coating.

Because each color system creates their own colors from scratch, spot colors from one system may be impossible to find within the library of another.

• AS2700 = Australian Standard colours (AS 2700)

### Dynamic range

Dynamic range:[6]

• SDR (Standard Dynamic Range): 0.05 nits - 100 nits
• HDR (High Dynamic Range): 0.0005 nits - 10,000 nits
• Human DR: Human vision: can detect brightness levels as low as 0.000001 nits and as high as 100,000,000 nits

The candela per square metre is the unit of w:luminance in the w:International System of Units (SI). The nit (symbol: nt) is a non-SI name also used for this unit [7] [8]

1 nt = 1 cd/m2


Defining HDR image and image sequence formats and attributes

• Peak luminance
• White points
• Contrast – spatial and temporal
• Dark levels

3 levels of monitor brightness:

• a low brightness if they have a peak brightness below 300 nits
• a standard brightness if they have a peak brightness between 300 and 350 nits (SDR)
• a high brightness if they have a peak brightness above 350 nits ( HDR )

High dynamic range (HDR)

Formats that are only used for HDR storage purpose:

HDR formats that can be used for both storage and transmission to displays, such as:

#### Color volume

Color volume is the set of all available color at all available hue, saturation and brightness.[9][10] It's the result of a 2D color space or 2D color gamut (that represent chromaticity) combined with the dynamic range.[11][12][13]

The term has been used to describe HDR's higher color volume than SDR (i.e. peak brightness of at least 1,000 cd/m2 higher than SDR's 100 cd/m2 limit and wider color gamut than w:Rec. 709 / w:sRGB).[9][11][14][15][16]

Color volume[17]

• SDR Color Volume = 200 cd/m2
• HLG Color Volume = 1 000 cd/m2
• PQ Color Volume = 10 000 cd/m2

### color gamut

In color reproduction, including computer graphics and photography, the gamut, or color gamut, is a certain complete subset of colors. The most common usage refers to the subset of colors which can be accurately represented in a given circumstance, such as within a given color space or by a certain output device, like monitor.

the difference between the RGB and CMYK color gamuts: the CMYK color gamut is much smaller than the RGB color gamut, thus the CMYK colors look muted.

If you were to print the image on a CMYK device (an offset press or maybe even an inkjet printer) the two sides would likely look much more similar, since the combination of cyan, yellow, magenta, and black cannot reproduce the range (gamut) of color that a computer monitor displays. This is a constant issue for those who work in print production. Clients produce bright and colorful images on their computers and are disappointed to see them look muted in print. (An exception is photo processing. In photo processing, like snapshots or 8x10 glossies, most of the RGB gamut is reproduced.)

### Color operators

Simple rolor operators, an analytical color operators that can be parameterized on a single input variable f(x)[18]

• brightness
• gamma
• contrast
• color balance

#### Gamma correction

Gamma value

• real world = 1.0
• floating point images ( HDRI) = 1.0
• integer ( SDRI with sRGB) images = 2.2

### Transfer function

• function relating image luminance with image samples
 ${\displaystyle T:scalarvalue\to colorvalue}$


Examples: [22]

• gray(x) returns a shade of gray. The argument x should be in the range 0–1. If x=0, black is returned; if x=1, white is returned.
• rgb(r,g,b) returns a color with the specified RGB components, which should be in the range 0–1.
• cmyk(c,m,y,k) returns a color with the specified CMYK components, which should be in the range 0–1.
• hsb(h,s,b) returns a color with the specified coordinates in hue–saturation–brightness color space, which should be in the range 0–1.
• hsl(h,s,l)

Normalisation = resecale to standard range[23]

 ${\displaystyle scalarvalue{\xrightarrow {normalize}}[0,1]{\xrightarrow {transferfunction}}colorvalue}$


Types:

• separated transfer functions for color and opacity in ParaView[24]
• Multi-Dimensional Transfer Functions[25]
• "The Transfer Function technique is a volume ray casting and rendering technique that assigns a different color and a different opacity/transparency value in different ranges of intensity values. This is done with a histogram based function, the "transfer function". The transfer function consists several control points, and each one of them corresponds to an intensity value and it has an RGB color and an opacity/transparency value. The intensity value of a control point is displayed with its color and opacity/transparency value, and the intensity values between two control points are displayed with the interpolated colors and the interpolated opacity/transparency values of the two control points. With the use of the transfer function, the different parts of the human body are displayed with a different color and a different opacity/transparency value." from Sante DICOM Viewer 3D Pro[26]
• HDR Transfer_function

#### Tone mapping

• "The process of compressing a single frame of HDR data (real or synthetic) into a range displayable by monitors is called tone mapping." [27]
• "Tone mapping is the process of transforming floating point color values to the expected [0.0, 1.0] range known as low dynamic range without losing too much detail, often accompanied with a specific stylistic color balance."[28]
 ${\displaystyle HDR\xrightarrow {tone\ mapping} LDR}$


Types with respect to range:

• global
• local

• linear functions for raw image formats, Note that some OETF and EOTF have an initial linear portion followed by a non-linear part (e.g. sRGB and Rec.70 )
• The identity transfer: output = input
• gamma functions
• logarithmic functions
• HDR: transfer functions for high dynamic range images ( HDR, HDRI )
• The identity transfer: output = input
• Normalizating function, Linear compression, the "-autolevel" function: For all inputs, outputs are in the range [0,1]. Divide by the maximum, then the maximum input is transformed to 1.0.
• Compress highlights, For non-negatives input values, output values are in the range [0,1]. Negative inputs create negative outputs. The gradient at (0,0) is 1.0. At input=1, output=0.5. For large inputs, the output approaches 1.0 and the gradient approaches zero
• S-curve: compress highlights and shadows
• Hybrid Log-Gamma (HLG) transfer function ( Hybrid Log Gamma HDR = HLG HDR)
• Perceptual quantizer (PQ) transfer function

Image magic code

convert <SomeDirectory>\*.png -evaluate-sequence median MEDIAN.png


### Color value

#### format

Color can be specified using one of the formats

• point in the space - direct color
• hex RGB
• hex RGBA
• rgb
• rgba
• hsl
• hsla
• cmyk
• name ( string)
• indexed color: index number from color palette

Alpha color chanel

• in OpenGl unintuitively, alpha = opaqueness, so alpha = 1 means fully opaque while alpha = 0 means fully transparent.

In PIL ( Python Imaging Library ) pixel color format is defined by modes[29]:

• 1 (1-bit pixels, black and white, stored with one pixel per byte)
• L (8-bit pixels, black and white)
• P (8-bit pixels, mapped to any other mode using a colour palette)
• RGB (3x8-bit pixels, true colour)
• RGBA (4x8-bit pixels, true colour with transparency mask)
• CMYK (4x8-bit pixels, colour separation)
• YCbCr (3x8-bit pixels, colour video format)
• I (32-bit signed integer pixels)
• F (32-bit floating point pixels)
• LA (L with alpha)
• RGBX (true colour with padding)
• RGBa (true colour with premultiplied alpha).

#### Number type (precision)

• integer ( natural numbers)
• unsigned char = range from 0 to 255 which gives 256 numbers
• integer
• real number
• float precision, example : 1.0f
• double precision
• hexadecimal color code (HEX color notation )[30]

Examples

• in OpenGl each of color components has a value between 0.0 and 1.0 = in a range of [0,1]. Here 1.0 means as much of that color as possible, and 0.0 means none of that color.

glColor3f(0.5f, 0.0f, 1.0f); // (0.5, 0, 1) is half red and full blue, giving dark purple.
glm::vec3 coral(1.0f, 0.5f, 0.31f);  // coral color definition in glm library and C++


Example in GIMP

• gray scale precision in Gimp
• At integer precision
• An 8-bit integer grayscale image provides 255 available tonal steps from 0 (black) to 255 (white).
• A 16-bit integer grayscale image provides 65535 available tonal steps from 0 (black) to 65535 (white).
• A 32-bit integer grayscale image theoretically will provide 4294967295 tonal steps from 0 (black) to 4294967295 (white). But as high bit depth GIMP 2.10 does all internal processing at 32-bit floating point precision, the actual number of steps will be no more than the number of tonal steps available in a 32-bit floating point image.
• At floating point precision: the available number of tonal steps in a grayscale image depends on the specified bit depth (8-bit, 16-bit, or 32-bit)

### layers

Color gradients can be named by :

• dimension
• color model: hsv[31]
• number of segments of gradient
• function used to create gradient
• Number of colors
• number type ( precision)

### bit depth of color

Bit depth is the number of bits per pixel, sample, or texel in a bitmap image (holding one or mode image channels, typical values being 4, 8, 16, 24, 32 When referring to a color component, the concept can be defined as:

• bits per component ( bpc)
• bits per channel (bpc)
• bits per color (bpc)
• bits per pixel component (bpp)
• bits per color channel (bpc)
• bits per sample (bps)

Modern standards tend to use bits per component, but historical lower-depth systems used bits per pixel more often.

• 8 bit color = 1 byte
• gray images
• color images with palette
• RGB565 ( 16 bit color = 2 bytes) High color. Here red and blue are encoded in 5 bits and green in 6 bits. [32][33]
• RGB888 ( 24 bit color = 3 bytes ) true color
• RGBA ( 32 bit color = 4 bytes)

Color depth by image file types

• for png color depth can range from 1 to 64 bits per pixel

### number type

• integer
• decimal
• real numbers

Examples by RapidTables:[34]

• White RGB code = (255,255,255) = 255*65536+255*256+255 = #FFFFFF
• Blue RGB code = (0,0,255) = 0*65536+0*256+255 = #0000FF

Precision in GIMP:[35]

• Integer Precision Options
• 8-bit integer
• 16-bit integer
• 32-bit integer
• Floating point precision options
• 16-bit floating point
• 32-bit floating point

### Dimension

#### 1D

Here color of pixel is proportional to 1D variable. For example in 2D space ( complex plane where point z = x+y*i) :

• position with respect to x-axis of Cartesian coordinate system : x
• distance to origin : r=abs(z)
• potential[36]
• complex angle angle=arg(z)

An example of a function to return a color that is linearly between two given colors:


colorA = [0, 0, 255] # blue
colorB = [255, 0, 0] # red
# 'val' must be between 0 and 1
for i in [1,2,3]:
color[i] = colorA[i] + val * (colorB[i] - colorA[i])
return color


Code

#### 2D

Because color can be treated as more than 1D value it is used to represent more than one ( real or 1D) variable. For example :

' panomand/src/dll/fbmandel.bas
' https://www.unilim.fr/pages_perso/jean.debord/panoramic/mandel/panoramic_mandel.htm
' PANOMAND is an open source software for plotting Mandelbrot and Julia sets. It is written in two BASIC dialects: PANORAMIC and FreeBASIC
' by Jean Debord
' a simplified version of R Munafo's algorithm
' Color is defined in HSV space, according to Robert Munafo
' (http://mrob.com/pub/muency/color.html): the value V is
' computed from the distance estimator, while the hue H and
' saturation S are computed from the iteration number.

function MdbCol(byval Iter as integer, _
byval mz   as double, _
byref dz   as Complex) as integer
' Computes the color of a point
' Iter = iteration count
' mz   = modulus of z at iteration Iter
' dz   = derivative at iteration Iter

if Iter = Max_Iter then return &HFFFFFF

dim as double  lmz, mdz, Dist, Dwell, DScale, Angle, Radius, Q, H, S, V
dim as integer R, G, B

lmz = log(mz)
mdz = CAbs(dz)

' Determine Value (luminosity) from Distance Estimator

V = 1

if mdz > 0 then
Dist = pp * mz * lmz / mdz
DScale = log(Dist / ScaleFact) / Lnp + Dist_Fact
if DScale < -8 then
V = 0
elseif DScale < 0 then
V = 1 + DScale / 8
end if
end if

' Determine Hue and Saturation from Continuous Dwell

Dwell = Iter - log(lmz) / Lnp + LLE
Q = log(abs(Dwell)) * AbsColor

if Q < 0.5 then
Q = 1 - 1.5 * Q
Angle = 1 - Q
else
Q = 1.5 * Q - 0.5
Angle = Q
end if

if (Iter mod 2 = 1) and (Color_Fact > 0) then
V = 0.85 * V
end if

H = frac(Angle * 10)

HSVtoRGB H * 360, S, V, R, G, B
return rgb(R, G, B)

end function


#### 3D

• Hans Lundmark page[43]

### Color model

The quality of 16-bit linear RGB is about equal to 12-bit sRGB (= nonlinear RGB), beacause linear color results in disproportionately more samples near white and fewer near black.

Types :

• RGB is for the display
• sRGB ("non-linear")
• RGB ("linear").
• CMYK is for printing
• other ( HSV, HSL, ...) are for choosing color, processing
• HSLuv
• YUV (Luminance and chrominance) it is a way of breaking the brightness and colours in the image down into numbers

#### HSV

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <complex.h> // http://pubs.opengroup.org/onlinepubs/009604499/basedefs/complex.h.html

/*
based on
c++ program from :
http://commons.wikimedia.org/wiki/File:Color_complex_plot.jpg
by  	Claudio Rocchini

gcc d.c -lm -Wall

http://en.wikipedia.org/wiki/Domain_coloring

*/

const double PI = 3.1415926535897932384626433832795;
const double E  = 2.7182818284590452353602874713527;

/*

complex domain coloring
Given a complex number z=re^{ i \theta},

hue represents the argument ( phase, theta ),

sat and value represents the modulus

*/
int GiveHSV( double complex z, double HSVcolor[3] )
{
//The HSV, or HSB, model describes colors in terms of hue, saturation, and value (brightness).

// hue = f(argument(z))
//hue values range from .. to ..
double a = carg(z); //
while(a<0) a += 2*PI; a /= 2*PI;

double m = cabs(z); //
double ranges = 0;
double rangee = 1;
while(m>rangee){
ranges = rangee;
rangee *= E;
}
double k = (m-ranges)/(rangee-ranges);

// saturation = g(abs(z))
double sat = k<0.5 ? k*2: 1 - (k-0.5)*2;
sat = 1 - pow( (1-sat), 3);
sat = 0.4 + sat*0.6;

// value = h(abs(z))
double val = k<0.5 ? k*2: 1 - (k-0.5)*2;
val = 1 - val;
val = 1 - pow( (1-val), 3);
val = 0.6 + val*0.4;

HSVcolor[0]= a;
HSVcolor[1]= sat;
HSVcolor[2]= val;
return 0;
}

int GiveRGBfromHSV( double HSVcolor[3], unsigned char RGBcolor[3] ) {
double r,g,b;
double h; double s; double v;
h=HSVcolor[0]; // hue
s=HSVcolor[1]; //  saturation;
v = HSVcolor[2]; // = value;

if(s==0)
r = g = b = v;
else {
if(h==1) h = 0;
double z = floor(h*6);
int i = (int)z;
double f = (h*6 - z);
double p = v*(1-s);
double q = v*(1-s*f);
double t = v*(1-s*(1-f));
switch(i){
case 0: r=v; g=t; b=p; break;
case 1: r=q; g=v; b=p; break;
case 2: r=p; g=v; b=t; break;
case 3: r=p; g=q; b=v; break;
case 4: r=t; g=p; b=v; break;
case 5: r=v; g=p; b=q; break;
}
}
int c;
c = (int)(256*r); if(c>255) c = 255; RGBcolor[0] = c;
c = (int)(256*g); if(c>255) c = 255; RGBcolor[1] = c;
c = (int)(256*b); if(c>255) c = 255; RGBcolor[2] = c;
return 0;
}

int GiveRGBColor( double complex z, unsigned char RGBcolor[3])
{
static double HSVcolor[3];
GiveHSV( z, HSVcolor );
GiveRGBfromHSV(HSVcolor,RGBcolor);
return 0;
}

//
double complex fun(double complex c ){
return (cpow(c,2)-1)*cpow(c-2.0- I,2)/(cpow(c,2)+2+2*I);} //

int main(){
// screen (integer ) coordinate
const int dimx = 800; const int dimy = 800;
// world ( double) coordinate
const double reMin = -2; const double reMax =  2;
const double imMin = -2; const double imMax =  2;
//
double stepX=(imMax-imMin)/(dimy-1);
double stepY=(reMax-reMin)/(dimx-1);

static unsigned char RGBcolor[3];
FILE * fp;
char *filename ="complex.ppm";
fp = fopen(filename,"wb");
fprintf(fp,"P6\n%d %d\n255\n",dimx,dimy);

int i,j;
for(j=0;j<dimy;++j){
double im = imMax - j*stepX;
for(i=0;i<dimx;++i){
double re = reMax - i*stepY;
double complex z= re + im*I; //
double complex v = fun(z); //
GiveRGBColor( v, RGBcolor);

fwrite(RGBcolor,1,3,fp);
}
}
fclose(fp);
printf("OK - file %s saved\n", filename);

return 0;
}


In Basic :

' /panomand/src/dll/hsvtorgb.bas
' https://www.unilim.fr/pages_perso/jean.debord/panoramic/mandel/panoramic_mandel.htm
' PANOMAND is an open source software for plotting Mandelbrot and Julia sets. It is written in two BASIC dialects: PANORAMIC and FreeBASIC
' by Jean Debord
sub HSVtoRGB(byref H as double,  _
byref S as double,  _
byref V as double,  _
byref R as integer, _
byref G as integer, _
byref B as integer)

' Convert RGB to HSV
' R, G, B values are from 0 to 255
' H = [0..360], S = [0..1], V = [0..1]
' if S = 0, then H = -1 (undefined)

if S = 0 then  ' achromatic (grey)
R = V * 255
G = R
B = R
exit sub
end if

dim as integer I
dim as double  Z, F, P, Q, T
dim as double  RR, GG, BB

Z = H / 60     ' sector 0 to 5
I = int(Z)
F = frac(Z)
P = V * (1 - S)
Q = V * (1 - S * F)
T = V * (1 - S * (1 - F))

select case I
case 0
RR = V
GG = T
BB = P
case 1
RR = Q
GG = V
BB = P
case 2
RR = P
GG = V
BB = T
case 3
RR = P
GG = Q
BB = V
case 4
RR = T
GG = P
BB = V
case 5
RR = V
GG = P
BB = Q
end select

R = RR * 255
G = GG * 255
B = BB * 255
end sub


### Function

One can use any function in each segment of gradient. Output of function is scaled to range of color component.

### Number of colors

Number of color is determined by color depth : from 2 colors to 16 mln of colors.

### Repetition and offset

Direct repetition :

Color is proportional to position <0;1> of color in color gradient. if position > 1 then we have repetition of colors. it maybe useful

Mirror repetition  :

"colorCycleMirror - This will reflect the colour gradient so that it cycles smoothly " [44]

Offset :

# How to use color gradients in computer programs

First find what format of color you need in your program.[45][46]

• A colour look-up table (CLUT)[47] ) color map, palette
• palette [48][49]
• mixed [50]

  "Lookup tables (LUTs) are an excellent technique for optimizing the evaluation of functions that are expensive to compute and inexpensive to cache. ... For data requests that fall between the table's samples, an interpolation algorithm can generate reasonable approximations by averaging nearby samples."[51]


## CLUT image

One can use CLUT image a a source of the gradient[52][53]

  convert input.pgm -level 0,65532 clut.ppm -interpolate integer -clut -depth 8 output.png


## CLUT Array

### python

# http://jtauber.com/blog/2008/05/18/creating_gradients_programmatically_in_python/
# Creating Gradients Programmatically in Python by James Tauber

import sys

def write_png(filename, width, height, rgb_func):

import zlib
import struct
import array

def output_chunk(out, chunk_type, data):
out.write(struct.pack("!I", len(data)))
out.write(chunk_type)
out.write(data)
checksum = zlib.crc32(data, zlib.crc32(chunk_type))
out.write(struct.pack("!I", checksum))

def get_data(width, height, rgb_func):
fw = float(width)
fh = float(height)
compressor = zlib.compressobj()
data = array.array("B")
for y in range(height):
data.append(0)
fy = float(y)
for x in range(width):
fx = float(x)
data.extend([int(v * 255) for v in rgb_func(fx / fw, fy / fh)])
compressed = compressor.compress(data.tostring())
flushed = compressor.flush()
return compressed + flushed

out = open(filename, "w")
out.write(struct.pack("8B", 137, 80, 78, 71, 13, 10, 26, 10))
output_chunk(out, "IHDR", struct.pack("!2I5B", width, height, 8, 2, 0, 0, 0))
output_chunk(out, "IDAT", get_data(width, height, rgb_func))
output_chunk(out, "IEND", "")
out.close()

return lambda offset: (start_value + ((offset - start_offset) / (stop_offset - start_offset) * (stop_value - start_value))) / 255.0

initial_offset = 0.0
for offset, start, end in DATA:
if y < offset:
r = linear_gradient(start[0], end[0], initial_offset, offset)(y)
g = linear_gradient(start[1], end[1], initial_offset, offset)(y)
b = linear_gradient(start[2], end[2], initial_offset, offset)(y)
return r, g, b
initial_offset = offset

## EXAMPLES

# normally you would make these with width=1 but below I've made them 50
# so you can more easily see the result

# body background from jtauber.com and quisition.com
(1.0, (0xA1, 0xA1, 0xA1), (0xDF, 0xDF, 0xDF)),
]))

# header background similar to that on jtauber.com
(0.43, (0xBF, 0x94, 0xC0), (0x4C, 0x26, 0x4C)), # top
(0.85, (0x4C, 0x26, 0x4C), (0x27, 0x13, 0x27)), # bottom
(1.0,  (0x66, 0x66, 0x66), (0xFF, 0xFF, 0xFF)), # shadow
]))

(0.72, (0x00, 0x26, 0x4D), (0x00, 0x40, 0x80)),
(1.0,  (0x00, 0x40, 0x80), (0x00, 0x6C, 0xCF)), # glow
]))

# form input background from pinax
(0.33, (0xDD, 0xDD, 0xDD), (0xF3, 0xF3, 0xF3)), # top-shadow
(1.0,  (0xF3, 0xF3, 0xF3), (0xF3, 0xF3, 0xF3)),
]))


### perl

# Perl code
# http://www.angelfire.com/d20/roll_d3_for_this/mandel-highorder/mandel-high.pl
# from perl High-order Mandelbrot program.
# Written by Christopher Thomas.
# Picture palette info.

my ($palsize); my (@palette); if(0) { # Light/dark colour banded palette. # NOTE: This looks ugly, probably because the dark colours look muddy.$palsize = 16;
@palette =
( "  255   0   0", "    0 112 112", "  255 128   0", "    0   0 128",
"  224 224   0", "   64   0  96", "    0 255   0", "   96   0  64",
"    0 224 224", "  128   0   0", "    0   0 255", "  128  64   0",
"  128   0 192", "  112 112   0", "  192   0 128", "    0 128   0" );
}
else
{
# 8-colour rainbow palette.
$palsize = 8; @palette = ( " 255 0 0", " 255 128 0", " 224 224 0", " 0 255 0", " 0 224 224", " 0 0 255", " 128 0 192", " 192 0 128" ); }  Conversions : • between FractInt and Fractal eXtreme palettes [54] lists: ## Gradient functions Name: • coloring function types Examples : ### glsl // https://www.shadertoy.com/view/lsd3zN // sRGB demo by Tom Forsyth // https://medium.com/@tomforsyth/the-srgb-learning-curve-773b7f68cf7a ////////////////////////////////////////////////////////// // // Illustration of the precision distribution of linear // and sRGB formats. // // A ramp of 64 shades of each colour is shown to // emphasise the distribution of banding in each format. // Real formats of course have 256 shades. // // The leftmost bar of each colour is a linear format // As you can see, although this format is linear in // "photons per second", the difference in shades between // the darker bands is far more obvious to the eye than // the difference between the brighter bands. Thus, // although linear space is a good place to do maths, // when stored in a buffer the distribution of precision // is poorly matched to the eye's preception of brightness. // // The middle bar of each colour is an sRGB format. // While this is a strange non-linear format, and doing // maths in it is not a good idea, it is an excellent // format for storing "picturelike" data. You can see // that the change in perceived brightness between adjacent // bands is very uniform across the entire range of // brightnesses, meaning that it has a distribution of // precision that matches the eye's perception very well. // // The rightmost bar of each colour is a gamma 2.2 bar. // This is not directly supported by hardware, and is there // to illustrate that although it is quite similar to sRGB, // there are significant differences between them, and // care must be taken if trying to approximate one with // the other. In general, it's not worth the very small // performance difference. // ////////////////////////////////////////////////////////// // Taken from D3DX_DXGIFormatConvert.inl float D3DX_FLOAT_to_SRGB ( float val ) { if( val < 0.0031308 ) val *= 12.92; else val = 1.055 * pow(val,1.0/2.4) - 0.055; return val; } // Taken from D3DX_DXGIFormatConvert.inl // Technically this is not bit-exact - that requires a look-up table, // but it's accurate enough for our purposes here. float D3DX_SRGB_to_FLOAT(float val) { if( val < 0.04045 ) val /= 12.92; else val = pow((val + 0.055)/1.055,2.4); return val; } void mainImage( out vec4 fragColor, in vec2 fragCoord ) { vec2 uv = fragCoord.xy / iResolution.xy; float yShade = uv.y; int colCol = int(floor(uv.x*4.0)); float fraction = uv.x*4.0 - float(colCol); int colRamp = int(floor(fraction * 3.1)); // Make the basic colour. vec3 baseCol; if ( colCol == 0 ) { baseCol = vec3(yShade,yShade,yShade); // white } else if ( colCol == 1 ) { baseCol = vec3(yShade*0.6,yShade,0.0); // light green } else if ( colCol == 2 ) { baseCol = vec3(yShade,yShade*0.5,yShade*0.2); // bronzeish } else { baseCol = vec3(yShade*0.5,0.0,yShade); // purple } // Artificially quantise to emphasise precision distribution float shadeSteps = 64.0; baseCol = (1.0/shadeSteps) * floor ( baseCol * shadeSteps ); // Now interpret that value as if it was a value stored in a texture of various formats. vec3 linearCol; if ( colRamp == 0 ) { // Linear texture linearCol = baseCol; } else if ( colRamp == 1 ) { // sRGB texture linearCol.x = D3DX_SRGB_to_FLOAT ( baseCol.x ); linearCol.y = D3DX_SRGB_to_FLOAT ( baseCol.y ); linearCol.z = D3DX_SRGB_to_FLOAT ( baseCol.z ); } else if ( colRamp == 2 ) { // 2.2 gamma for illustration linearCol.x = pow ( baseCol.x, 2.2 ); linearCol.y = pow ( baseCol.y, 2.2 ); linearCol.z = pow ( baseCol.z, 2.2 ); } else { // Separator. linearCol = vec3(0.0,0.0,0.0); } // But then assume the display we're outputting to is gamma 2.2 float displayGamma = 2.2; fragColor.x = pow ( linearCol.x, 1.0/displayGamma ); fragColor.y = pow ( linearCol.y, 1.0/displayGamma ); fragColor.z = pow ( linearCol.z, 1.0/displayGamma ); fragColor.w = 1.0; }  ### HSV gradient • explanation by Robert P. Munafo[66] • Basic code and images by Jean Debord[67] • c programs by Curtis T McMullen [68] ### Linear RGB gradient with 6 segments Rainbow gradient Here gradient consists from 6 segments. In each segment only one RGB component of color is changed using linear function. #### Delphi version // Delphi version by Witold J.Janik with help Andrzeja Wąsika from [pl.comp.lang.delphi] // [i] changes from [iMin] to [iMax] function GiveRainbowColor(iMin, iMax, i: Integer): TColor; var m: Double; r, g, b, mt: Byte; begin m := (i - iMin)/(iMax - iMin + 1) * 6; mt := (round(frac(m)*$FF));
case Trunc(m) of
0: begin
R := $FF; G := mt; B := 0; end; 1: begin R :=$FF - mt;
G := $FF; B := 0; end; 2: begin R := 0; G :=$FF;
B := mt;
end;
3: begin
R := 0;
G := $FF - mt; B :=$FF;
end;
4: begin
R := mt;
G := 0;
B := $FF; end; 5: begin R :=$FF;
G := 0;
B := \$FF - mt;
end;
end; // case

Result := rgb(R,G,B);
end;
/////


#### C version

Input of function are 2 variables :

• position of color in gradient, (a normalized float between 0.0 and 1.0 )
• color as an array of RGB components ( integer without sign from 0 to 255 )

This function does not use direct outoput ( void) but changes input variables color. One can use it this way:

GiveRainbowColor(0.25,color);

/* based on Delphi function by Witold J.Janik */
void GiveRainbowColor(double position,unsigned char c[])
{
/* if position > 1 then we have repetition of colors it maybe useful    */

if (position>1.0){if (position-(int)position==0.0)position=1.0; else position=position-(int)position;}

unsigned char nmax=6; /* number of color segments */
double m=nmax* position;

int n=(int)m; // integer of m

double f=m-n;  // fraction of m
unsigned char t=(int)(f*255);

switch( n){
case 0: {
c[0] = 255;
c[1] = t;
c[2] = 0;
break;
};
case 1: {
c[0] = 255 - t;
c[1] = 255;
c[2] = 0;
break;
};
case 2: {
c[0] = 0;
c[1] = 255;
c[2] = t;
break;
};
case 3: {
c[0] = 0;
c[1] = 255 - t;
c[2] = 255;
break;
};
case 4: {
c[0] = t;
c[1] = 0;
c[2] = 255;
break;
};
case 5: {
c[0] = 255;
c[1] = 0;
c[2] = 255 - t;
break;
};
default: {
c[0] = 255;
c[1] = 0;
c[2] = 0;
break;
};

}; // case
}


#### Cpp version

// C++ version
// here are some my modification but the main code is the same
// as in Witold J.Janik code
//

Uint32 GiveRainbowColor(double position)

// this function gives 1D linear RGB color gradient
// color is proportional to position
// position  <0;1>
// position means position of color in color gradient

{
if (position>1)position=position-int(position);
// if position > 1 then we have repetition of colors
// it maybe useful
Uint8 R, G, B;// byte
int nmax=6;// number of color bars
double m=nmax* position;
int n=int(m); // integer of m
double f=m-n;  // fraction of m
Uint8 t=int(f*255);

switch( n){
case 0: {
R = 255;
G = t;
B = 0;
break;
};
case 1: {
R = 255 - t;
G = 255;
B = 0;
break;
};
case 2: {
R = 0;
G = 255;
B = t;
break;
};
case 3: {
R = 0;
G = 255 - t;
B = 255;
break;
};
case 4: {
R = t;
G = 0;
B = 255;
break;
};
case 5: {
R = 255;
G = 0;
B = 255 - t;
break;
};

}; // case

return (R << 16) | (G << 8) | B;
}


"The idea is to change the color based on a sine wave. This gives a nice smooth gradient effect (although it’s not linear, which is not a requirement anyway). By changing the frequency of the RGB components (we could theoretically work with other color spaces such as HSV) we can get various gradients. Also, we can also play with the phase of each color component, creating a “shifting” effect. The basic implementation of such a gradient can be implemented like so:"

/*

*/
public Color[] GenerateColors(int number) {
var colors = new List<Color>(number);
double step = MaxAngle / number;
for(int i = 0; i < number; ++i) {
var r = (Math.Sin(FreqRed * i * step + PhaseRed) + 1) * .5;
var g = (Math.Sin(FreqGreen * i * step + PhaseGreen) + 1) * .5;
var b = (Math.Sin(FreqBlue * i * step + PhaseBlue) + 1) * .5;
colors.Add(Color.FromRgb((byte)(r * 255), (byte)(g * 255), (byte)(b * 255)));
}
return colors.ToArray();
}


"Where:

• the Freq* are the frequencies of the respective RGB colors
• Phase* are the phase shift values.

Note that all calculations are done with floating point numbers (ranging from 0.0 to 1.0), converting to a WPF Color structure (in this case) at the very end. This is simply convenient, as we’re working with trigonometric functions, which like floating point numbers rather than integers. The result is normalized to the range 0 to 1, as the sine function produces results from –1 to 1, so we add one to get a range of 0 to 2 and finally divide by 2 to get to the desired range."[69]

### cubehelix

/*
GNUPLOT - stdfn.h
Copyright 1986 - 1993, 1998, 2004   Thomas Williams, Colin Kelley
*/
#ifndef clip_to_01
#define clip_to_01(val)	\
((val) < 0 ? 0 : (val) > 1 ? 1 : (val))
#endif

/*
input : position
output : c array ( rgb color)

the colour scheme spirals (as a squashed helix) around the diagonal of the RGB colour cube

https://arxiv.org/abs/1108.5083
A colour scheme for the display of astronomical intensity images by D. A. Green
*/
void GiveCubehelixColor(double position, unsigned char c[]){

/* GNUPLOT - color.h
* Petr Mikulik, December 1998 -- June 1999
* Copyright: open source as much as possible
*/

// t_sm_palette
/* gamma for gray scale and cubehelix palettes only */
double gamma = 1.5;

/* control parameters for the cubehelix palette scheme */
//set palette cubehelix start 0.5 cycles -1.5 saturation 1
//set palette gamma 1.5
double cubehelix_start = 0.5;	/* offset (radians) from colorwheel 0 */
double cubehelix_cycles = -1.5;	/* number of times round the colorwheel */
double cubehelix_saturation = 1.0;	/* color saturation */
double r,g,b;
double gray = position;

/*
Petr Mikulik, December 1998 -- June 1999
* Copyright: open source as much as possible
*/
// /* Map gray in [0,1] to color components according to colorMode */
// function color_components_from_gray
// from gnuplot/src/getcolor.c
double phi, a;

phi = 2. * M_PI * (cubehelix_start/3. +  gray * cubehelix_cycles);

// gamma correction
if (gamma != 1.0)    gray = pow(gray, 1./gamma);

a = cubehelix_saturation * gray * (1.-gray) / 2.;

// compute
r = gray + a * (-0.14861 * cos(phi) + 1.78277 * sin(phi));
g = gray + a * (-0.29227 * cos(phi) - 0.90649 * sin(phi));
b = gray + a * ( 1.97294 * cos(phi));

// normalize to [9,1] range
r = clip_to_01(r);
g = clip_to_01(g);
b = clip_to_01(b);

// change range to [0,255]
c[0] = (unsigned char) 255*r; //R
c[1] = (unsigned char) 255*g; // G
c[2] = (unsigned char) 255*b; // B

}


• Color Look-Up Table (CLUT)

### File types for color gradient

There are special file types for color gradients:[70][71]

• The GIMP uses the files with .ggr extension [72]
• Fractint uses .map files [73]
• UltraFractal uses .ugr - These files can contain multiple gradients
• ual - old Ultra Fractal gradient file
• rgb, pal, gpf - gnuplot files
• The Matplotlib[74] colormap[75] is a lookup table[76]
• csv files
• maps in WHIP format ( Autodesk) by Paul Bourke
• Gnofract4D saves gradients only inside the graphic file, not as separate file.[77]
• MatLab
• Python
• R
• GMT
• QGIS
• Ncview
• Ferret
• Plotly
• Paraview
• VisIt
• Mathematica
• Surfer
• d3
• Petrel
• Fledermaus
• Qimera
• ImageJ
• Fiji
• Inkscape
• XML
• text
• SASS style sheet
• LESS - http://lesscss.org style sheet
• CSS - Cascading Style Sheet

#### csv files

a small table containing 33 values ( stored in a csv file) by Kenneth Moreland[78]

Scalar	R	G	B
0	59	76	192
0.03125	68	90	204
0.0625	77	104	215
0.09375	87	117	225
0.125	98	130	234
0.15625	108	142	241
0.1875	119	154	247
0.21875	130	165	251
0.25	141	176	254
0.28125	152	185	255
0.3125	163	194	255
0.34375	174	201	253
0.375	184	208	249
0.40625	194	213	244
0.4375	204	217	238
0.46875	213	219	230
0.5	221	221	221
0.53125	229	216	209
0.5625	236	211	197
0.59375	241	204	185
0.625	245	196	173
0.65625	247	187	160
0.6875	247	177	148
0.71875	247	166	135
0.75	244	154	123
0.78125	241	141	111
0.8125	236	127	99
0.84375	229	112	88
0.875	222	96	77
0.90625	213	80	66
0.9375	203	62	56
0.96875	192	40	47
1	180	4	38

#### CSS syntax

###### Non-repeating
Code Preview
.gradient1 {
}

.gradient2 {
}

.gradient3 {
}

.gradient4 {
background-image: linear-gradient(130deg, magenta 0%, lime 40%, red 100%);
}

###### Repeating
Code Preview
.gradient5 {
}

.gradient6 {
background-image: repeating-linear-gradient(to right, blue 0%, magenta 10%);
}

.gradient7 {
background-image: repeating-linear-gradient(60deg, cyan 0%, teal 23%, lime 31%);
}


#### Fractint map files

The default filetype extension for color-map files is ".MAP". These are ASCII text files. Consist of a series of RGB triplet values (one triplet per line, encoded as the red, green, and blue [RGB] components of the color). Color map ( or palette) is used as a colour look-up table[79] Default color map is in the Default.map file :

0 0 0            The default VGA color map
0 0 168
0 168 0
0 168 168
168 0 0
168 0 168
168 84 0
168 168 168
84 84 84
84 84 252
84 252 84
84 252 252
252 84 84
252 84 252
252 252 84
252 252 252
0 0 0
20 20 20
32 32 32
44 44 44
56 56 56
68 68 68
80 80 80
96 96 96
112 112 112
128 128 128
144 144 144
160 160 160
180 180 180
200 200 200
224 224 224
252 252 252
0 0 252
64 0 252
124 0 252
188 0 252
252 0 252
252 0 188
252 0 124
252 0 64
252 0 0
252 64 0
252 124 0
252 188 0
252 252 0
188 252 0
124 252 0
64 252 0
0 252 0
0 252 64
0 252 124
0 252 188
0 252 252
0 188 252
0 124 252
0 64 252
124 124 252
156 124 252
188 124 252
220 124 252
252 124 252
252 124 220
252 124 188
252 124 156
252 124 124
252 156 124
252 188 124
252 220 124
252 252 124
220 252 124
188 252 124
156 252 124
124 252 124
124 252 156
124 252 188
124 252 220
124 252 252
124 220 252
124 188 252
124 156 252
180 180 252
196 180 252
216 180 252
232 180 252
252 180 252
252 180 232
252 180 216
252 180 196
252 180 180
252 196 180
252 216 180
252 232 180
252 252 180
232 252 180
216 252 180
196 252 180
180 252 180
180 252 196
180 252 216
180 252 232
180 252 252
180 232 252
180 216 252
180 196 252
0 0 112
28 0 112
56 0 112
84 0 112
112 0 112
112 0 84
112 0 56
112 0 28
112 0 0
112 28 0
112 56 0
112 84 0
112 112 0
84 112 0
56 112 0
28 112 0
0 112 0
0 112 28
0 112 56
0 112 84
0 112 112
0 84 112
0 56 112
0 28 112
56 56 112
68 56 112
84 56 112
96 56 112
112 56 112
112 56 96
112 56 84
112 56 68
112 56 56
112 68 56
112 84 56
112 96 56
112 112 56
96 112 56
84 112 56
68 112 56
56 112 56
56 112 68
56 112 84
56 112 96
56 112 112
56 96 112
56 84 112
56 68 112
80 80 112
88 80 112
96 80 112
104 80 112
112 80 112
112 80 104
112 80 96
112 80 88
112 80 80
112 88 80
112 96 80
112 104 80
112 112 80
104 112 80
96 112 80
88 112 80
80 112 80
80 112 88
80 112 96
80 112 104
80 112 112
80 104 112
80 96 112
80 88 112
0 0 64
16 0 64
32 0 64
48 0 64
64 0 64
64 0 48
64 0 32
64 0 16
64 0 0
64 16 0
64 32 0
64 48 0
64 64 0
48 64 0
32 64 0
16 64 0
0 64 0
0 64 16
0 64 32
0 64 48
0 64 64
0 48 64
0 32 64
0 16 64
32 32 64
40 32 64
48 32 64
56 32 64
64 32 64
64 32 56
64 32 48
64 32 40
64 32 32
64 40 32
64 48 32
64 56 32
64 64 32
56 64 32
48 64 32
40 64 32
32 64 32
32 64 40
32 64 48
32 64 56
32 64 64
32 56 64
32 48 64
32 40 64
44 44 64
48 44 64
52 44 64
60 44 64
64 44 64
64 44 60
64 44 52
64 44 48
64 44 44
64 48 44
64 52 44
64 60 44
64 64 44
60 64 44
52 64 44
48 64 44
44 64 44
44 64 48
44 64 52
44 64 60
44 64 64
44 60 64
44 52 64
44 48 64
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0
0 0 0


#### Gimp/Inscape gpl files

Used by : Gimp, Inscape, Aseprite, Drawpile, Krita, MyPaint[80]

Syntax:

• ASCII files ( text files)[81]
• Comments must start with a #. In non-empty lines that don't, the first three tokens are parsed as numbers
• There is no alpha support
• GIMP Palette - it must be the first line of the file[82]
• Name: <name> - sets the name of the color palette.
• Columns: <number> - is just an indication for displaying the palette inside GIMP.
• 0 0 0 Black - RGB values for the color followed by the color name

Source code of loader function [83]

GIMP palettes are stored using a special file format, in files with the extension .gpl.

Directory:

• ~/.config/GIMP/x.y/palettes/ directory (where x.y is the GIMP version number)
• ~/.config/inkscape/palettes/
GIMP Palette
Name: Material Design
Columns: 14
#
255 248 225		amber 50
255 236 179		amber 100
255 224 130		amber 200
255 213  79		amber 300
255 202  40		amber 400
255 193   7		amber 500
255 179   0		amber 600
255 160   0		amber 700
255 143   0		amber 800
255 111   0		amber 900
255 229 127		amber a100
255 215  64		amber a200
255 196   0		amber a400
255 171   0		amber a700
227 242 253		blue 50
187 222 251		blue 100
144 202 249		blue 200
100 181 246		blue 300
66 165 245		blue 400
33 150 243		blue 500
30 136 229		blue 600
25 118 210		blue 700
21 101 192		blue 800
13  71 161		blue 900
130 177 255		blue a100
68 138 255		blue a200
41 121 255		blue a400
41  98 255		blue a700
224 247 250		cyan 50
178 235 242		cyan 100
128 222 234		cyan 200
77 208 225		cyan 300
38 198 218		cyan 400
0 188 212		cyan 500
0 172 193		cyan 600
0 151 167		cyan 700
0 131 143		cyan 800
0  96 100		cyan 900
132 255 255		cyan a100
24 255 255		cyan a200
0 229 255		cyan a400
0 184 212		cyan a700
251 233 231		deep-orange 50
255 204 188		deep-orange 100
255 171 145		deep-orange 200
255 138 101		deep-orange 300
255 112  67		deep-orange 400
255  87  34		deep-orange 500
244  81  30		deep-orange 600
230  74  25		deep-orange 700
216  67  21		deep-orange 800
191  54  12		deep-orange 900
255 158 128		deep-orange a100
255 110  64		deep-orange a200
255  61   0		deep-orange a400
221  44   0		deep-orange a700
237 231 246		deep-purple 50
209 196 233		deep-purple 100
179 157 219		deep-purple 200
149 117 205		deep-purple 300
126  87 194		deep-purple 400
103  58 183		deep-purple 500
94  53 177		deep-purple 600
81  45 168		deep-purple 700
69  39 160		deep-purple 800
49  27 146		deep-purple 900
179 136 255		deep-purple a100
124  77 255		deep-purple a200
101  31 255		deep-purple a400
98   0 234		deep-purple a700
232 245 233		green 50
200 230 201		green 100
165 214 167		green 200
129 199 132		green 300
102 187 106		green 400
76 175  80		green 500
67 160  71		green 600
56 142  60		green 700
46 125  50		green 800
27  94  32		green 900
185 246 202		green a100
105 240 174		green a200
0 230 118		green a400
0 200  83		green a700
232 234 246		indigo 50
197 202 233		indigo 100
159 168 218		indigo 200
121 134 203		indigo 300
92 107 192		indigo 400
63  81 181		indigo 500
57  73 171		indigo 600
48  63 159		indigo 700
40  53 147		indigo 800
26  35 126		indigo 900
140 158 255		indigo a100
83 109 254		indigo a200
61  90 254		indigo a400
48  79 254		indigo a700
225 245 254		light-blue 50
179 229 252		light-blue 100
129 212 250		light-blue 200
79 195 247		light-blue 300
41 182 246		light-blue 400
3 169 244		light-blue 500
3 155 229		light-blue 600
2 136 209		light-blue 700
2 119 189		light-blue 800
1  87 155		light-blue 900
128 216 255		light-blue a100
64 196 255		light-blue a200
0 176 255		light-blue a400
0 145 234		light-blue a700
241 248 233		light-green 50
220 237 200		light-green 100
197 225 165		light-green 200
174 213 129		light-green 300
156 204 101		light-green 400
139 195  74		light-green 500
124 179  66		light-green 600
104 159  56		light-green 700
85 139  47		light-green 800
51 105  30		light-green 900
204 255 144		light-green a100
178 255  89		light-green a200
118 255   3		light-green a400
100 221  23		light-green a700
249 251 231		lime 50
240 244 195		lime 100
230 238 156		lime 200
220 231 117		lime 300
212 225  87		lime 400
205 220  57		lime 500
192 202  51		lime 600
175 180  43		lime 700
158 157  36		lime 800
130 119  23		lime 900
244 255 129		lime a100
238 255  65		lime a200
198 255   0		lime a400
174 234   0		lime a700
255 243 224		orange 50
255 224 178		orange 100
255 204 128		orange 200
255 183  77		orange 300
255 167  38		orange 400
255 152   0		orange 500
251 140   0		orange 600
245 124   0		orange 700
239 108   0		orange 800
230  81   0		orange 900
255 209 128		orange a100
255 171  64		orange a200
255 145   0		orange a400
255 109   0		orange a700
252 228 236		pink 50
248 187 208		pink 100
244 143 177		pink 200
240  98 146		pink 300
236  64 122		pink 400
233  30  99		pink 500
216  27  96		pink 600
194  24  91		pink 700
173  20  87		pink 800
136  14  79		pink 900
255 128 171		pink a100
255  64 129		pink a200
245   0  87		pink a400
197  17  98		pink a700
243 229 245		purple 50
225 190 231		purple 100
206 147 216		purple 200
186 104 200		purple 300
171  71 188		purple 400
156  39 176		purple 500
142  36 170		purple 600
123  31 162		purple 700
106  27 154		purple 800
74  20 140		purple 900
234 128 252		purple a100
224  64 251		purple a200
213   0 249		purple a400
170   0 255		purple a700
255 235 238		red 50
255 205 210		red 100
239 154 154		red 200
229 115 115		red 300
239  83  80		red 400
244  67  54		red 500
229  57  53		red 600
211  47  47		red 700
198  40  40		red 800
183  28  28		red 900
255 138 128		red a100
255  82  82		red a200
255  23  68		red a400
213   0   0		red a700
224 242 241		teal 50
178 223 219		teal 100
128 203 196		teal 200
77 182 172		teal 300
38 166 154		teal 400
0 150 136		teal 500
0 137 123		teal 600
0 121 107		teal 700
0 105  92		teal 800
0  77  64		teal 900
167 255 235		teal a100
100 255 218		teal a200
29 233 182		teal a400
0 191 165		teal a700
255 253 231		yellow 50
255 249 196		yellow 100
255 245 157		yellow 200
255 241 118		yellow 300
255 238  88		yellow 400
255 235  59		yellow 500
253 216  53		yellow 600
251 192  45		yellow 700
249 168  37		yellow 800
245 127  23		yellow 900
255 255 141		yellow a100
255 255   0		yellow a200
255 234   0		yellow a400
255 214   0		yellow a700
236 239 241		blue-grey 50
207 216 220		blue-grey 100
176 190 197		blue-grey 200
144 164 174		blue-grey 300
120 144 156		blue-grey 400
96 125 139		blue-grey 500
84 110 122		blue-grey 600
69  90 100		blue-grey 700
55  71  79		blue-grey 800
38  50  56		blue-grey 900
239 235 233		brown 50
215 204 200		brown 100
188 170 164		brown 200
161 136 127		brown 300
141 110  99		brown 400
121  85  72		brown 500
109  76  65		brown 600
93  64  55		brown 700
78  52  46		brown 800
62  39  35		brown 900
250 250 250		grey 50
245 245 245		grey 100
238 238 238		grey 200
224 224 224		grey 300
189 189 189		grey 400
158 158 158		grey 500
117 117 117		grey 600
97  97  97		grey 700
66  66  66		grey 800
33  33  33		grey 900
0   0   0	   	black
255 255 255	white


#### Gimp ggr files

"The gradients that are supplied with GIMP are stored in a system gradients folder. By default, gradients that you create are stored in a folder called gradients in your personal GIMP directory. Any gradient files (ending with the extension .ggr) found in one of these folders, will automatically be loaded when you start GIMP" ( from gimp doc ) Default gradients are in /usr/share/gimp/2.0/gradients directory ( check it in a window : Edit/preferences/directories)

Git repo

Gimp gradients can be created thru :

• GUI [84]
• manually in text editor ( use predefined gradients as a base)
• in own programs

Gimp gradient file format is described in:

• GIMP Application Reference Manual [85]
• source files :

typedef struct {
gdouble                  left, middle, right;

GimpRGB                  left_color;
GimpRGB                  right_color;

GimpGradientSegmentType  type;          /*  Segment's blending function  */
GimpGradientSegmentColor color;         /*  Segment's coloring type      */



In GimpConfig style format:[87]

<proposal>

(segment 0.000000 0.286311 0.572621
(left-color (gimp-rgba 0.269543 0.259267 1.000000 1.000000))
(right-color (gimp-rgba 0.215635 0.407414 0.984953 1.000000))
(blending-function linear)
(coloring-type rgb))
(segment ...)
...
(segment ...))
</proposal>

GIMP Gradient
Name: GMT_hot
3
0.000000 0.187500 0.375000 0.000000 0.000000 0.000000 1.000000 1.000000 0.000000 0.000000 1.000000 0 0
0.375000 0.562500 0.750000 1.000000 0.000000 0.000000 1.000000 1.000000 1.000000 0.000000 1.000000 0 0
0.750000 0.875000 1.000000 1.000000 1.000000 0.000000 1.000000 1.000000 1.000000 1.000000 1.000000 0 0


First line says it is a gimp gradient file.

Second line is a gradient's name.

Third line tells the number of segments in the gradient.

Each line following defines the property of each segment in following order :"[89]

• position of left stoppoint
• position of middle point
• position of right stoppoint
• R for left stoppoint
• G for left stoppoint
• B for left stoppoint
• A for left stoppoint
• R for right stoppoint
• G for right stoppoint
• B for right stoppoint
• A for right stoppoint
• Blending function constant
• coloring type constant

There are only two constants at the end of each line:

• the blending function constant of the segment (apparently 0=Linear, 1=Curved, 2=Sinusoidal, 3=Spherical (increasing), 4=Spherical (decreasing))
• the coloring type constant of the segment (probably 0=RGB, 1=HSV (counter-clockwise hue), 2=HSV (clockwise hue)[90]

# programs

## color convert

split your hexadecimal color code into 3 values, that could be treated as RGB vectors (RGB decimals) ( from hextoral)


# tests

Test your :

• monitor ( gamut)
• graphic card
• printer
• own

# Hpw to Calculate the average color of an image ?

Averaging RGB should be correct assuming you do it in linear RGB. If your images are in sRGB, you can remove the gamma correction by doing something like the following for each of the R, G, and B components:

   float sRGBToLinear(UInt8 component)
{
float tempComponent = (float)component / 255.0;
if (tempComponent <= 0.04045)
{
tempComponent = tempComponent / 12.92;
}
else
{
tempComponent = pow((tempComponent + 0.055) / (1.055), 2.4);
}
return tempComponent;
}


You can then average together all of the red values in the image, all of the green values in the image, and all of the blue values in the image after they've been run through the above conversion. You can then do the opposite conversion to get back to sRGB:

   UInt8 linearRGBTosRGB(float component)
{
float tempComponent =  0.0;
if (component <= 0.00318308)
{
tempComponent = 12.92 * component;
}
else
{
tempComponent = 1.055 * pow(component, 1.0 / 2.4) - 0.055;
}
return (UInt8)(tempComponent * 255.0);
}


Note that alpha makes things slightly more complicated. If you're using premultiplied alpha, you can simply apply the above calculations for the average. If you're using straight alpha, you'll want to multiply each of the R, G, and B components by the alpha before doing the averaging.[93]

# How to extract color palette from image ?

• Colores.py—extract color palettes from your favorite images [94]
• Color Scheme Extraction[95]
• using Image Magic [96]
• using Gimp [97]
• "There is this small tool in fractalshades that interactively grabs a colormap from a line you draw on an image, the editor looks like the attached picture. Not perfect, but I found it useful (in the 'tools' section). The cmap can then be used in the program or exported for later use (for the time being, exports only to a txt format specific to this program.)" Geoffroy Billotey (GBillotey)[98]

# How to find lighter and darker colors based on any initial color ?

  // darker by C. Wayne Brown
newR = R + (0-R)*t;  // where t varies between 0 and 1
newG = G + (0-G)*t;  // where t varies between 0 and 1
newB = B + (0-B)*t;  // where t varies between 0 and 1

// lighter C. Wayne Brown
newR = R + (1-R)*t;  // where t varies between 0 and 1
newG = G + (1-G)*t;  // where t varies between 0 and 1
newB = B + (1-B)*t;  // where t varies between 0 and 1


# How to make quality images?

• description by Alan Gibson.[99]

# References

1. Color_space in wikipedia
2. List of color spaces and their uses in wikipedia
3. w3 : sRGB
4. oklab: A perceptual color space for image processing
5. The Informed Illustrator: Digital Spot Color Systems
6. HDR workflows: ITU vs ICC by Luke Wallis
7. Buser, Pierre; Imbert, Michel (1992). Vision. MIT Press. p. 53. ISBN 978-0-262-02336-8. nit luminance.
8. Boyd, RLF, ed. (1992). Astronomical Photometry. Springer. p. 9. ISBN 978-0-7923-1653-4.
9. a b "HPA Tech Retreat 2014 – Day 4". 20 February 2014. Archived from the original on 1 November 2014. Retrieved 25 April 2021.
10. "Color Volume of TVs: DCI-P3 and Rec. 2020". RTINGS.com. Retrieved 2021-04-25.
11. a b "Color Volume: What It Is and Why It Matters for TV". news.samsung.com. Retrieved 31 January 2021.
12. "Color volume of a TV: You should know this about the successor to color space". Homecinema Magazine. 2020-07-18. Retrieved 2021-04-25.
13. "Color Volume: Measuring and Understanding What it Means – ReferenceHT". 2017-04-11. Retrieved 2021-04-25.
14. "BT.2100 : Image parameter values for high dynamic range television for use in production and international programme exchange". www.itu.int. Retrieved 25 April 2021.
15. "BT.1886 : Reference electro-optical transfer function for flat panel displays used in HDTV studio production". www.itu.int. Retrieved 25 April 2021.
16. "BT.2020 : Parameter values for ultra-high definition television systems for production and international programme exchange". www.itu.int. Retrieved 25 April 2021.
17. Objective Color Metrics by Chris Seeger
18. nvidia pugems2 : using-lookup-tables-accelerate-color
19. ImageMagick: resize_gamma
20. A Cheritat wiki: see image showing gamma-correct downscale of dense part of Mandelbrot set
21. Basic Mapping Techniques from Computer Graphics Laboratory Department of Computer Science Zürich Switzerland
22. pyxplot : color objects
23. kitware : using-the-color-map-editor-in-paraview by Utkarsh Ayachit
24. kitware : using-the-color-map-editor-in-paraview by Utkarsh Ayachit
25. Visualization of Scalar Fields from IBBM
26. santesoft : The Transfer Function technique
27. Adaptive Temporal Tone Mapping by Shaun David Ramsey, J. Thomas Johnson III, Charles Hansen
28. learnopengl  : advanced-Lighting/HDR by Joey de Vries
29. imaging module doc: concepts
30. hextoral: what-is-a-hex-color
31. dsp.stackexchange question: why-do-we-use-the-hsv-colour-space-so-often-in-vision-and-image-processing
32. 16BitColorValues by demmel products gmbh.
33. rgb565-color-picker by Thomas Barth
34. rapidtables : RGB Color
35. docs gimp 2.10 : gimp-image-precision
36. fractalforums.org: smooth-1d-coloring
37. R2.1/2.C(1/2) by Robert Munafo
38. Color by Robert Munafo
39. Mandelbrot and Julia sets with PANORAMIC and FreeBASIC By jdebord
40. The Mandelbrot Function by John J. G. Savard
41. The Mandelbrot Function 2 by John J. G. Savard
42. fractalforums.org/: 2d-coloring
43. Visualizing complex analytic functions using domain coloring by Hans Lundmark
44. The Fractal Explorer Pixel Bender filters by Tom Beddard
45. What's Delphi TColor format? at ACASystems
46. Delhi TColor at efg2.com
47. wikipedia :Colour_look-up_table
48. fractalforums : creating-a-good-palette-using-bezier-interpolation
49. FracTest : palettes
50. stefanbion : fraktal-generator and colormapping/
51. nvidia gpu gems2 : using-lookup-tables-accelerate-color
52. Paul Tol's notes
53. gmic : color_presets
54. Fractal Forums > Fractal Software > Fractal Programs > Windows Fractal Software > Fractal eXtreme > Converting between FractInt and Fractal eXtreme palettes
55. stackoverflow question : smooth-spectrum-for-mandelbrot-set-rendering
56. on-rainbows by Charlie Loyd
57. Stefan Bion : color mapping
59. Making annoying rainbows in javascript A tutorial by jim bumgardner
60. mandel.js by Christopher Williams
61. Custom Palettes by Christopher Williams
62. Gradient jQuery plugin Posted by David Wees
63. C++ function by Richel Bilderbeek
64. Multiwave coloring for Mandelbrot
65. histogram colouring is really streching (not true histogram)
66. Color by Robert Munafo
67. Mandelbrot and Julia sets with PANORAMIC and FreeBASIC By Jean Debord
68. c programs by Curtis T McMullen
70. Color gradient file formats explained
71. 29 Colour Map Formats... by Peter Kovesi
72. GIMP add-ons: types, installation, management by Alexandre Prokoudine
73. Fractint Palette Maps and map files
74. matplotlib: colormap-manipulation
75. matplotlib colormaps
76. wikipedia: Lookup table
77. gnofract4d manual
78. kenneth moreland: color-maps
79. w:Colour look-up table
80. About A collection of RGB color palettes for GIMP and Inkscape (but also Aseprite, Drawpile, Krita and MyPaint) by Dezmerean Robert
81. stackoverflow question: gimp-palette-file-gpl-format-syntax
82. Add custom color palettes to GIMP and Inkscape by Dezmerean Robert
83. Source code of gimp load palette function
85. GimpGradient doc at GIMP Application Reference Manual
86. [Gimp-developer] Format of GIMP gradient files
87. [Gimp-developer] Format of GIMP gradient files
88. [Gimp-developer] Format of GIMP gradient files
89. gpr format description by Vinay S Raikar
90. Emulating ggr/GIMP gradient in JavaFx
91. CCC-Tool