## -*- mode:octave -*-
##
## Octave (mathlab) program to generate RGB palettes that are
## indistinguishable for people missing one
## of three (S,M,L), aka (blue,green,red), receptors in the eye.
##
## by Han-Kwang Nienhuys, April 2004
## Copyright: GDFL
##
## tristimuli of computer RGB, from
## http://www.gimlay.org/~andoh/cg/faq/ColorFAQ.html
A1 = [0.64,0.3,0.15] ;
A2 = [0.33,0.60,0.06] ;
A3 = [0.03,0.10,0.79] ;
A = [A1;A2;A3] ;

## XYZ white point D65
whitexyz = [0.3127; 0.3290 ;0.3582] ;

## solve A.a = white
a = A \ whitexyz ;

## true tristimuli matrix for RGB
B = zeros(3,3);
for i = 1:3
  for j = 1:3
    B(i,j) = A(i,j)*a(j) ;
  endfor
endfor

## calculate metameric black for protanopes
black_x = null(B(2:3,1:3))' ;
black_y = null(B(1:2:3,1:3))' ;
black_z = null(B(1:2,1:3))' ;

## normalize to largest component
black_x = black_x/black_x(1) 
black_y = black_y/black_y(2) 
black_z = black_z/black_z(3) 

## construct noisy palettes, neutral, and indistinguishable versions
## for people missing L, M, S receptors, respectively.
palsize = 10;  # number of colors

## requirement: avg+/-noise+/-offset should be between 0..1
avg = 0.5;      # average intensity
noise = 0.15;   # spread (+/-) in intensity
offset = 0.34;  # color offset for the three new palettes

## RGB values within range 0..1
palette_bg = 2*rand(palsize,3)*noise + (avg-noise)*ones(palsize,3) ; 
palette_red =   offset*repmat(black_x,palsize,1) + palette_bg ;
palette_green = offset*repmat(black_y,palsize,1) + palette_bg ;
palette_blue =  offset*repmat(black_z,palsize,1) + palette_bg ;

## Now apply gamma correction and scale to 0..255.
g=2.5 ; # gamma value
for i = 1:palsize
  for j = 1:3
    palette_bg(i,j)    = floor(255*palette_bg(i,j)^(1/g));
    palette_red(i,j)   = floor(255*palette_red(i,j)^(1/g));
    palette_green(i,j) = floor(255*palette_green(i,j)^(1/g));
    palette_blue(i,j)  = floor(255*palette_blue(i,j)^(1/g));
  endfor
endfor

palette_bg
palette_red
palette_green
palette_blue

## sample output in case you don't have octave or mathlab
## these palettes are RGB values to use on computer graphics, with
## an assumed gamma of 2.5.
##
## colors 1-10: background
## colors 11-20: indistinguishable from 1-10 for protanope
## colors 21-30: indistinguishable from 1-10 for deuterope
## colors 31-40: indistinguishable from 1-10 for tritanope
##
## the following can be used as a palette in the GIMP (remove ##)
##
##GIMP Palette
##  204  206  193
##  187  211  207
##  214  191  207
##  182  173  175
##  173  190  173
##  173  197  170
##  177  198  210
##  190  182  207
##  212  191  209
##  204  188  197
##  246  191  193
##  233  196  208
##  253  174  208
##  230  153  176
##  223  173  174
##  223  181  171
##  226  182  211
##  236  163  208
##  252  174  210
##  246  171  198
##  157  248  187
##  130  251  202
##  170  236  202
##  120  223  168
##  102  236  166
##  102  240  163
##  110  241  205
##  135  229  202
##  169  236  204
##  156  234  191
##  179  208  237
##  158  213  248
##  191  193  248
##  151  175  224
##  139  192  223
##  139  199  221
##  144  200  250
##  162  184  248
##  189  193  250
##  179  190  240
