Forked from
gmsh / gmsh
18703 commits behind the upstream repository.
-
Christophe Geuzaine authored
power law for the alpha channel
Christophe Geuzaine authoredpower law for the alpha channel
ColorTable.cpp 11.97 KiB
// $Id: ColorTable.cpp,v 1.27 2004-12-24 20:25:11 geuzaine Exp $
//
// Copyright (C) 1997-2004 C. Geuzaine, J.-F. Remacle
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
// USA.
//
// Please report all bugs and problems to <gmsh@geuz.org>.
//
// Contributor(s):
// David Colignon
//
// These colortable routines were inspired by those provided in Vis5d,
// a program for visualizing five dimensional gridded data sets
// Copyright (C) 1990 - 1995 Bill Hibbard, Brian Paul, Dave Santek,
// and Andre Battaiola.
#include "Gmsh.h"
#include "ColorTable.h"
#include "Context.h"
#include "Numeric.h"
extern Context_T CTX;
void ColorTable_InitParam(int number, GmshColorTable * ct)
{
ct->size = 255;
for(int i = 0; i < COLORTABLE_NBMAX_PARAM; i++){
ct->ipar[i] = 0;
ct->dpar[i] = 0.;
}
ct->ipar[COLORTABLE_MODE] = COLORTABLE_RGB;
ct->ipar[COLORTABLE_NUMBER] = number;
ct->dpar[COLORTABLE_ALPHA] = 1.0;
}
static double gray(double s)
{
return s < 0. ? 0. : (s < 1. ? s : 1.);
}
static double hot_r(double s)
{
return s < 0. ? 0. : (s < 3./8. ? 8./3. * s : 1.);
}
static double hot_g(double s)
{
return s < 3./8. ? 0. : (s < 6./8. ? 8./3. * (s - 3./8.) : 1.);
}
static double hot_b(double s)
{
return s < 6./8. ? 0. : (s < 1. ? 8./2. * (s - 6./8.) : 1.);
}
static double cubic(double a, double b, double c, double d, double x)
{
return a + b * x + c * x * x + d * x * x * x;
}
void ColorTable_Recompute(GmshColorTable * ct)
{
double s, t, gamma;
int r, g, b, a;
double bias = ct->dpar[COLORTABLE_BIAS];
double curvature = ct->dpar[COLORTABLE_CURVATURE];
int rotation = ct->ipar[COLORTABLE_ROTATION];
for(int i = 0; i < ct->size; i++) {
if(ct->size > 1) {
if(i + rotation < 0)
s = (double)(i + rotation + ct->size) / (double)(ct->size - 1);
else if(i + rotation > ct->size - 1)
s = (double)(i + rotation - ct->size) / (double)(ct->size - 1);
else
s = (double)(i + rotation) / (double)(ct->size - 1);
}
else
s = 0.;
if(ct->ipar[COLORTABLE_SWAP])
s = 1.0 - s;
switch (ct->ipar[COLORTABLE_NUMBER]) {
case 0: // all black
r = g = b = 0;
break;
case 1: // vis5d
t = (curvature + 1.4) * (s - (1. + bias) / 2.);
r = (int)(128.0 + 127.0 * atan(7.0 * t) / 1.57);
g = (int)(128.0 + 127.0 * (2 * exp(-7 * t * t) - 1));
b = (int)(128.0 + 127.0 * atan(-7.0 * t) / 1.57);
break;
case 2: // matlab "jet"
{
double ii = (double)(s-bias)*128.;
if(ii < 0) ii = 0;
if(ii > 128) ii = 128;
double rr =
ii <= 46 ? 0. :
ii >= 111 ? -0.03125*(ii - 111) + 1. :
ii >= 78 ? 1. :
0.03125*(ii - 46);
double gg =
ii <= 14 || ii >= 111 ? 0. :
ii >= 79 ? -0.03125*(ii - 111) :
ii <= 46 ? 0.03125*(ii - 14) :
1.;
double bb =
ii >= 79 ? 0. :
ii >= 47 ? -0.03125*(ii - 79) :
ii <= 14 ? 0.03125*(ii - 14) + 1.:
1.;
r = (int)(rr*255.);
g = (int)(gg*255.);
b = (int)(bb*255.);
}
break;
case 3: // lucie, samcef (?)
if(s - bias <= 0.) {
r = 0;
g = 0;
b = 255;
}
else if(s - bias <= 0.40) {
r = 0;
g = (int)((s - bias) * 637.5);
b = (int)(255. - (s - bias) * 637.5);
}
else if(s - bias <= 0.60) {
r = (int)(1275. * (s - bias - 0.4));
g = 255;
b = 0;
}
else if(s - bias <= 1.) {
r = 255;
g = (int)(255. - 637.5 * (s - bias - 0.6));
b = 0;
}
else {
r = 255;
g = 0;
b = 0;
}
break;
case 4: // rainbow
if(s - bias <= 0.) {
r = 0;
g = 0;
b = 255;
}
else if(s - bias <= 0.25 + curvature) {
curvature = (curvature == -0.25) ? -0.26 : curvature;
r = 0;
g = (int)((s - bias) * (255. / (0.25 + curvature)));
b = 255;
}
else if(s - bias <= 0.50) {
curvature = (curvature == 0.25) ? 0.26 : curvature;
r = 0;
g = 255;
b = (int)(255. - (255. / (0.25 - curvature)) * (s - bias - 0.25 - curvature));
}
else if(s - bias <= 0.75 - curvature) {
curvature = (curvature == 0.25) ? 0.26 : curvature;
r = (int)((s - bias - 0.5) * (255. / (0.25 - curvature)));
g = 255;
b = 0;
}
else if(s - bias <= 1.) {
curvature = (curvature == -0.25) ? -0.26 : curvature;
r = 255;
g = (int)(255. - (255. / (0.25 + curvature)) * (s - bias - 0.75 + curvature));
b = 0;
}
else {
r = 255;
g = 0;
b = 0;
}
break;
case 5: // emc2000 (rainbow with black and white)
if(s - bias <= 0.) {
r = 0;
g = 0;
b = 0;
}
else if(s - bias <= 0.2) {
r = (int)(57 * (1 - 100 * ((s - bias) - 0.1) * ((s - bias) - 0.1)));
g = 0;
b = (int)((s - bias) * (255. / 0.2));
}
else if(s - bias <= 0.3624) {
r = 0;
g = (int)((s - bias - 0.2) * (255. / 0.1624));
b = 255;
}
else if(s - bias <= 0.50) {
r = 0;
g = 255;
b = (int)(255. - (255. / 0.1376) * (s - bias - 0.3624));
}
else if(s - bias <= 0.6376) {
r = (int)((s - bias - 0.5) * (255. / 0.1376));
g = 255;
b = 0;
}
else if(s - bias <= 0.8) {
r = 255;
g = (int)(255. - (255. / 0.1624) * (s - bias - 0.6376));
b = 0;
}
else if(s - bias <= 1.0) {
r = 255;
g = (int)((255. / 0.2) * (s - bias - 0.8));
b = (int)(-3187.66 * (s - bias) * (s - bias) + 7012.76 * (s - bias) - 3570.61);
}
else {
r = 255;
g = 255;
b = 255;
}
break;
case 6: // darkblue->red->yellow->white
r = (int)(255. * cubic(-0.0506169, 2.81633, -1.87033, 0.0524573, s-bias));
g = (int)(255. * cubic(0.0485868, -1.26109, 6.3074, -4.12498, s-bias));
b = (int)(255. * cubic(0.364662, 1.50814, -7.36756, 6.51847, s-bias));
break;
case 7: // matlab "hot"
r = (int)(255. * hot_r(s-bias));
g = (int)(255. * hot_g(s-bias));
b = (int)(255. * hot_b(s-bias));
break;
case 8: // matlab "pink"
r = (int)(255. * sqrt((2.*gray(s-bias) + hot_r(s-bias))/3.));
g = (int)(255. * sqrt((2.*gray(s-bias) + hot_g(s-bias))/3.));
b = (int)(255. * sqrt((2.*gray(s-bias) + hot_b(s-bias))/3.));
break;
case 9: // grayscale
if(s - bias <= 0.) {
r = g = b = 0;
}
else if(s - bias <= 1.) {
r = g = b = (int)(255 * (1. - curvature) * (s - bias));
}
else {
r = g = b = (int)(255 * (1. - curvature));
}
break;
case 10: // all white
r = g = b = 255;
break;
case 11: // matlab "hsv"
{
double H = 6. * s + 1.e-10, R, G, B;
HSV_to_RGB(H, 1., 1., &R, &G, &B);
r = (int)(255 * R);
g = (int)(255 * G);
b = (int)(255 * B);
}
break;
case 12: // matlab "bone"
r = (int)(255. * (7.*gray(s-bias) + hot_b(s-bias))/8.);
g = (int)(255. * (7.*gray(s-bias) + hot_g(s-bias))/8.);
b = (int)(255. * (7.*gray(s-bias) + hot_r(s-bias))/8.);
break;
case 13: // matlab "spring"
r = (int)(255. * 1.);
g = (int)(255. * gray(s-bias));
b = (int)(255. * (1. - gray(s-bias)));
break;
case 14: // matlab "summer"
r = (int)(255. * gray(s-bias));
g = (int)(255. * (0.5+gray(s-bias)/2.));
b = (int)(255. * 0.4);
break;
case 15: // matlab "autumn"
r = (int)(255. * 1.);
g = (int)(255. * gray(s-bias));
b = (int)(255. * 0.);
break;
case 16: // matlab "winter"
r = (int)(255. * 0.);
g = (int)(255. * gray(s-bias));
b = (int)(255. * (0.5+(1.-gray(s-bias))/2.));
break;
case 17: // matlab "cool"
r = (int)(255. * gray(s-bias));
g = (int)(255. * (1.-gray(s-bias)));
b = (int)(255. * 1.);
break;
case 18: // matlab "copper"
r = (int)(255. * DMIN(1., gray(s-bias) * 1.25));
g = (int)(255. * DMIN(1., gray(s-bias) * 0.7812));
b = (int)(255. * DMIN(1., gray(s-bias) * 0.4975));
break;
default:
r = g = b = 0;
break;
}
double aa = 1.0;
if(ct->dpar[COLORTABLE_ALPHAPOW])
aa = pow(s ? s : 1.e-10, ct->dpar[COLORTABLE_ALPHAPOW]);
a = (int)(255. * aa * ct->dpar[COLORTABLE_ALPHA]);
if(ct->dpar[COLORTABLE_BETA]) {
if(ct->dpar[COLORTABLE_BETA] > 0.0)
gamma = 1. - ct->dpar[COLORTABLE_BETA];
else
gamma = 1. / (1.001 + ct->dpar[COLORTABLE_BETA]); // beta is thresholded to [-1,1]
r = (int)(255. * pow((double)r / 255., gamma));
g = (int)(255. * pow((double)g / 255., gamma));
b = (int)(255. * pow((double)b / 255., gamma));
}
if(ct->ipar[COLORTABLE_INVERT]) {
r = 255 - r;
g = 255 - g;
b = 255 - b;
}
// clamp to [0,255]
r = r < 0 ? 0 : (r > 255 ? 255 : r);
g = g < 0 ? 0 : (g > 255 ? 255 : g);
b = b < 0 ? 0 : (b > 255 ? 255 : b);
a = a < 0 ? 0 : (a > 255 ? 255 : a);
ct->table[i] = PACK_COLOR(r, g, b, a);
}
}
static GmshColorTable clip;
void ColorTable_Copy(GmshColorTable * ct)
{
clip.size = ct->size;
memcpy(clip.table, ct->table, ct->size * sizeof(unsigned int));
memcpy(clip.ipar, ct->ipar, COLORTABLE_NBMAX_PARAM * sizeof(int));
memcpy(clip.dpar, ct->dpar, COLORTABLE_NBMAX_PARAM * sizeof(double));
}
void ColorTable_Paste(GmshColorTable * ct)
{
ct->size = clip.size;
memcpy(ct->table, clip.table, clip.size * sizeof(unsigned int));
memcpy(ct->ipar, clip.ipar, COLORTABLE_NBMAX_PARAM * sizeof(int));
memcpy(ct->dpar, clip.dpar, COLORTABLE_NBMAX_PARAM * sizeof(double));
}
int ColorTable_Diff(GmshColorTable * ct1, GmshColorTable * ct2)
{
if(ct1->size != ct2->size) return 1;
for(int i = 0; i < ct1->size; i++)
if(ct1->table[i] != ct2->table[i]) return 1;
return 0;
}
void ColorTable_Print(GmshColorTable * ct, FILE * fp)
{
int i, r, g, b, a;
char tmp1[1024], tmp2[1024];
strcpy(tmp1, "");
for(i = 0; i < ct->size; i++) {
r = UNPACK_RED(ct->table[i]);
g = UNPACK_GREEN(ct->table[i]);
b = UNPACK_BLUE(ct->table[i]);
a = UNPACK_ALPHA(ct->table[i]);
if(i && !(i % 4)) {
if(fp)
fprintf(fp, "%s\n", tmp1);
else
Msg(DIRECT, tmp1);
strcpy(tmp1, "");
}
sprintf(tmp2, "{%d, %d, %d, %d}", r, g, b, a);
strcat(tmp1, tmp2);
if(i != ct->size - 1)
strcat(tmp1, ", ");
}
if(fp)
fprintf(fp, "%s\n", tmp1);
else
Msg(DIRECT, tmp1);
}
int ColorTable_IsAlpha(GmshColorTable * ct)
{
int i, a;
for(i = 0; i < ct->size; i++) {
a = UNPACK_ALPHA(ct->table[i]);
if(a < 255)
return 1;
}
return 0;
}
// HSV/RBG conversion routines
#define UNDEFINED 0
// rgb on [0, 1], sv returned on [0, 1] and h on [0, 6].
// Exception: h is returned UNDEFINED if S==0.
#define RETURN_HSV(h,s,v) {*H=h; *S=s; *V=v; return;}
void RGB_to_HSV(double R, double G, double B,
double *H, double *S, double *V)
{
double v, x, f;
int i;
x = DMIN(DMIN(R, G), B);
v = DMAX(DMAX(R, G), B);
if(v == x)
RETURN_HSV(UNDEFINED, 0, v);
f = (R == x) ? G - B : ((G == x) ? B - R : R - G);
i = (R == x) ? 3 : ((G == x) ? 5 : 1);
RETURN_HSV(i - f / (v - x), (v - x) / v, v);
}
// h given on [0, 6] or UNDEFINED. s and v given on [0, 1].
// rgb each returned on [0, 1].
#define RETURN_RGB(r,g,b) {*R=r; *G=g; *B=b; return;}
void HSV_to_RGB(double H, double S, double V,
double *R, double *G, double *B)
{
double m, n, f;
int i;
if(H == UNDEFINED)
RETURN_RGB(V, V, V);
i = (int)floor(H);
f = H - i;
if(!(i & 1))
f = 1 - f; // if i is even
m = V * (1 - S);
n = V * (1 - S * f);
switch (i) {
case 6:
case 0:
RETURN_RGB(V, n, m);
case 1:
RETURN_RGB(n, V, m);
case 2:
RETURN_RGB(m, V, n);
case 3:
RETURN_RGB(m, n, V);
case 4:
RETURN_RGB(n, m, V);
case 5:
RETURN_RGB(V, m, n);
}
}