Actual source code: cmap.c
petsc-3.7.3 2016-08-01
1: #include <petscsys.h> /*I "petscsys.h" I*/
2: #include <petscdraw.h>
4: /*
5: Set up a color map, using uniform separation in hue space.
6: Map entries are Red, Green, Blue.
7: Values are "gamma" corrected.
8: */
10: /*
11: Gamma is a monitor dependent value. The value here is an
12: approximate that gives somewhat better results than Gamma = 1.
13: */
14: static PetscReal Gamma = 2.0;
18: PetscErrorCode PetscDrawUtilitySetGamma(PetscReal g)
19: {
21: Gamma = g;
22: return(0);
23: }
25: PETSC_STATIC_INLINE double PetscHlsHelper(double m1,double m2,double h)
26: {
27: while (h > 1.0) h -= 1.0;
28: while (h < 0.0) h += 1.0;
29: if (h < 1/6.0) return m1 + (m2-m1)*h*6;
30: if (h < 1/2.0) return m2;
31: if (h < 2/3.0) return m1 + (m2-m1)*(2/3.0-h)*6;
32: return m1;
33: }
35: PETSC_STATIC_INLINE void PetscHlsToRgb(double h,double l,double s,double *r,double *g,double *b)
36: {
37: if (s > 0.0) {
38: double m2 = l <= 0.5 ? l * (1.0+s) : l+s-(l*s);
39: double m1 = 2*l - m2;
40: *r = PetscHlsHelper(m1,m2,h+1/3.);
41: *g = PetscHlsHelper(m1,m2,h);
42: *b = PetscHlsHelper(m1,m2,h-1/3.);
43: } else {
44: /* ignore hue */
45: *r = *g = *b = l;
46: }
47: }
49: PETSC_STATIC_INLINE void PetscGammaCorrect(double *r,double *g,double *b)
50: {
51: PetscReal igamma = 1/Gamma;
52: *r = (double)PetscPowReal((PetscReal)*r,igamma);
53: *g = (double)PetscPowReal((PetscReal)*g,igamma);
54: *b = (double)PetscPowReal((PetscReal)*b,igamma);
55: }
59: static PetscErrorCode PetscDrawCmap_Hue(int mapsize, unsigned char R[],unsigned char G[],unsigned char B[])
60: {
61: int i;
62: double maxhue = 212.0/360,lightness = 0.5,saturation = 1.0;
65: for (i=0; i<mapsize; i++) {
66: double hue = maxhue*(double)i/(mapsize-1),r,g,b;
67: PetscHlsToRgb(hue,lightness,saturation,&r,&g,&b);
68: PetscGammaCorrect(&r,&g,&b);
69: R[i] = (unsigned char)(255*PetscMin(r,1.0));
70: G[i] = (unsigned char)(255*PetscMin(g,1.0));
71: B[i] = (unsigned char)(255*PetscMin(b,1.0));
72: }
73: return(0);
74: }
78: static PetscErrorCode PetscDrawCmap_Gray(int mapsize,unsigned char R[],unsigned char G[],unsigned char B[])
79: {
80: int i;
82: for (i=0; i<mapsize; i++) R[i] = G[i] = B[i] = (unsigned char)((255.0*i)/(mapsize-1));
83: return(0);
84: }
88: static PetscErrorCode PetscDrawCmap_Jet(int mapsize,unsigned char R[],unsigned char G[],unsigned char B[])
89: {
90: int i;
91: const double knots[] = {0, 1/8., 3/8., 5/8., 7/8., 1};
94: for (i=0; i<mapsize; i++) {
95: double u = (double)i/(mapsize-1);
96: double m, r=0, g=0, b=0; int k = 0;
97: while(k < 4 && u > knots[k+1]) k++;
98: m = (u-knots[k])/(knots[k+1]-knots[k]);
99: switch(k) {
100: case 0: r = 0; g = 0; b = (m+1)/2; break;
101: case 1: r = 0; g = m; b = 1; break;
102: case 2: r = m; g = 1; b = 1-m; break;
103: case 3: r = 1; g = 1-m; b = 0; break;
104: case 4: r = 1-m/2; g = 0; b = 0; break;
105: }
106: R[i] = (unsigned char)(255*PetscMin(r,1.0));
107: G[i] = (unsigned char)(255*PetscMin(g,1.0));
108: B[i] = (unsigned char)(255*PetscMin(b,1.0));
109: }
110: return(0);
111: }
115: static PetscErrorCode PetscDrawCmap_Hot(int mapsize,unsigned char R[],unsigned char G[],unsigned char B[])
116: {
117: int i;
118: const double knots[] = {0, 3/8., 3/4., 1};
121: for (i=0; i<mapsize; i++) {
122: double u = (double)i/(mapsize-1);
123: double m, r=0, g=0, b=0; int k = 0;
124: while(k < 2 && u > knots[k+1]) k++;
125: m = (u-knots[k])/(knots[k+1]-knots[k]);
126: switch(k) {
127: case 0: r = m; g = 0; b = 0; break;
128: case 1: r = 1; g = m; b = 0; break;
129: case 2: r = 1; g = 1; b = m; break;
130: }
131: R[i] = (unsigned char)(255*PetscMin(r,1.0));
132: G[i] = (unsigned char)(255*PetscMin(g,1.0));
133: B[i] = (unsigned char)(255*PetscMin(b,1.0));
134: }
135: return(0);
136: }
140: static PetscErrorCode PetscDrawCmap_Bone(int mapsize,unsigned char R[],unsigned char G[],unsigned char B[])
141: {
142: int i;
144: (void)PetscDrawCmap_Hot(mapsize,R,G,B);
145: for (i=0; i<mapsize; i++) {
146: double u = (double)i/(mapsize-1);
147: double r = (7*u + B[i]/255.0)/8;
148: double g = (7*u + G[i]/255.0)/8;
149: double b = (7*u + R[i]/255.0)/8;
150: R[i] = (unsigned char)(255*PetscMin(r,1.0));
151: G[i] = (unsigned char)(255*PetscMin(g,1.0));
152: B[i] = (unsigned char)(255*PetscMin(b,1.0));
153: }
154: return(0);
155: }
157: #include ../src/sys/classes/draw/utils/cmap/coolwarm.h
158: #include ../src/sys/classes/draw/utils/cmap/parula.h
159: #include ../src/sys/classes/draw/utils/cmap/viridis.h
160: #include ../src/sys/classes/draw/utils/cmap/plasma.h
161: #include ../src/sys/classes/draw/utils/cmap/inferno.h
162: #include ../src/sys/classes/draw/utils/cmap/magma.h
164: static struct {
165: const char *name;
166: const unsigned char (*data)[3];
167: PetscErrorCode (*cmap)(int,unsigned char[],unsigned char[],unsigned char[]);
168: } PetscDrawCmapTable[] = {
169: {"hue", NULL, PetscDrawCmap_Hue }, /* varying hue with constant lightness and saturation */
170: {"gray", NULL, PetscDrawCmap_Gray}, /* black to white with shades of gray */
171: {"bone", NULL, PetscDrawCmap_Bone}, /* black to white with gray-blue shades */
172: {"jet", NULL, PetscDrawCmap_Jet }, /* rainbow-like colormap from NCSA, University of Illinois */
173: {"hot", NULL, PetscDrawCmap_Hot }, /* black-body radiation */
174: {"coolwarm", PetscDrawCmap_coolwarm, NULL}, /* ParaView default (Cool To Warm with Diverging interpolation) */
175: {"parula", PetscDrawCmap_parula, NULL}, /* MATLAB (default since R2014b) */
176: {"viridis", PetscDrawCmap_viridis, NULL}, /* matplotlib 1.5 (default since 2.0) */
177: {"plasma", PetscDrawCmap_plasma, NULL}, /* matplotlib 1.5 */
178: {"inferno", PetscDrawCmap_inferno, NULL}, /* matplotlib 1.5 */
179: {"magma", PetscDrawCmap_magma, NULL}, /* matplotlib 1.5 */
180: };
184: PetscErrorCode PetscDrawUtilitySetCmap(const char colormap[],int mapsize,unsigned char R[],unsigned char G[],unsigned char B[])
185: {
186: int i,j;
187: const char *cmap_name_list[sizeof(PetscDrawCmapTable)/sizeof(PetscDrawCmapTable[0])];
188: PetscInt id = 0, count = (PetscInt)(sizeof(cmap_name_list)/sizeof(char*));
189: PetscBool reverse = PETSC_FALSE, brighten = PETSC_FALSE;
190: PetscReal beta = 0;
191: PetscErrorCode ierr;
194: for (i=0; i<count; i++) cmap_name_list[i] = PetscDrawCmapTable[i].name;
195: if (colormap && colormap[0]) {
196: PetscBool match = PETSC_FALSE;
197: for (id=0; !match && id<count; id++) {PetscStrcasecmp(colormap,cmap_name_list[id],&match);}
198: if (!match) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Colormap '%s' not found",colormap);
199: }
200: PetscOptionsGetEList(NULL,NULL,"-draw_cmap",cmap_name_list,count,&id,NULL);
201: PetscOptionsGetBool(NULL,NULL,"-draw_cmap_reverse",&reverse,NULL);
202: PetscOptionsGetReal(NULL,NULL,"-draw_cmap_brighten",&beta,&brighten);
203: if (brighten && (beta <= (PetscReal)-1 || beta >= (PetscReal)+1)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"brighten parameter %g must be in the range (-1,1)",(double)beta);
205: if (PetscDrawCmapTable[id].cmap) {
206: PetscDrawCmapTable[id].cmap(mapsize,R,G,B);
207: } else {
208: const unsigned char (*rgb)[3] = PetscDrawCmapTable[id].data;
209: if (mapsize != 256-PETSC_DRAW_BASIC_COLORS) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Colormap '%s' with size %d not supported",cmap_name_list[id],mapsize);
210: for (i=0; i<mapsize; i++) {R[i] = rgb[i][0]; G[i] = rgb[i][1]; B[i] = rgb[i][2];}
211: }
213: if (reverse) {
214: i = 0; j = mapsize-1;
215: while(i < j) {
216: #define SWAP(a,i,j) do { unsigned char t = a[i]; a[i] = a[j]; a[j] = t; } while (0)
217: SWAP(R,i,j);
218: SWAP(G,i,j);
219: SWAP(B,i,j);
220: #undef SWAP
221: i++; j--;
222: }
223: }
225: if (brighten) {
226: PetscReal gamma = (beta > 0.0) ? (1 - beta) : (1 / (1 + beta));
227: for (i=0; i<mapsize; i++) {
228: PetscReal r = PetscPowReal((PetscReal)R[i]/255,gamma);
229: PetscReal g = PetscPowReal((PetscReal)G[i]/255,gamma);
230: PetscReal b = PetscPowReal((PetscReal)B[i]/255,gamma);
231: R[i] = (unsigned char)(255*PetscMin(r,(PetscReal)1.0));
232: G[i] = (unsigned char)(255*PetscMin(g,(PetscReal)1.0));
233: B[i] = (unsigned char)(255*PetscMin(b,(PetscReal)1.0));
234: }
235: }
236: return(0);
237: }