/* * Creates texture array with saturation levels in the y (t) direction * and hue and lightness changes in x (s) direction. * Black band on both hue ends, for plotting data out of range. * [0,black_border-1] and [texture_size-black_border, * texture_size-1] are black. Otherwise, use cindex = * black_border + h*(texture_size-2*black_border-1). * Returns a malloc'ed array of texture_size*texture_size * longs with successive texture_size blocks having * different saturation values; each long has r,g,b,0 * stored as unsigned chars. * * The authors of this software are Eric Grosse and W. M. Coughran, Jr. * Copyright (c) 1991 by AT&T. * Permission to use, copy, modify, and distribute this software for any * purpose without fee is hereby granted, provided that this entire notice * is included in all copies of any software which is or includes a copy * or modification of this software and in all copies of the supporting * documentation for such software. * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR AT&T MAKE ANY * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. * * We thank Cleve Moler for describing the "hot iron" scale to us. */ #include #include #include #include /* color maps */ #define RAINBOW 1 #define GRAY 2 #define TERRAIN 3 #define IRON 4 #define ASTRO 5 #define ZEBRA 6 long * texture_gen(int saturation_lvls,int texture_size,int black_border) { unsigned char r, g, b, *obuf; char *mapstr, *s; int invert = 0, map, ncolors = 7, tx, x, y, ihue; long *texture; double hue, oldhue, sat, oldsat, red, green, blue, h; if (s = getenv("NCOLORS")) ncolors = atoi(s); if (!( mapstr = getenv("MAP"))) mapstr = "rainbow"; else ToLower(mapstr); /* #define ToLower(s) ; if you don't care */ if(!strncmp("inverse ",mapstr,8)){ invert = 1; mapstr += 8; } if(!strcmp("rainbow",mapstr)) map = RAINBOW; else if(!strcmp("gray",mapstr)||!strcmp("grey",mapstr)) map = GRAY; else if(!strcmp("terrain",mapstr)||!strcmp("topo",mapstr)) map = TERRAIN; else if(!strcmp("iron",mapstr)||!strcmp("heated",mapstr)|| !strncmp("hot",mapstr,3)) map = IRON; else if(!strcmp("astro",mapstr)) map = ASTRO; /* the astronomers made me do it */ else if(!strncmp("alt",mapstr,3)||!strcmp("zebra",mapstr)) map = ZEBRA; else exit(2); texture = (long *)malloc(texture_size*saturation_lvls*sizeof(long)); oldhue = -1; oldsat = -1; for (y = 0; y < saturation_lvls; y++) { obuf = (unsigned char *)(texture+y*texture_size); sat = y / (saturation_lvls-1.); if(sat>0.99) sat = 0.99; if( oldsat!=sat ){ for (x = 0, tx = 0; x < texture_size; x++, tx += 4) { hue = (x-black_border) / (texture_size-2*black_border-1.); ihue = floor(ncolors*hue); hue = ((double)ihue)/(ncolors-1); if(hue>1.) hue = 1.; if(invert) hue = 1.-hue; if( x=texture_size-black_border ){ r = 0; g = 0; b = 0; }else if( oldhue!=hue ){ switch(map){ case RAINBOW: rainbow(1.-hue, sat, 1., &red, &green, &blue); break; case GRAY: red = hue; green = hue; blue = hue; break; case TERRAIN: h = 3*hue; if(h<.25){ red = 0; green = 0; blue = 0.25+2*h; }else if(h<2){ red = 0; green = 0.25+(2-h); blue = 0; }else if(h<2.7){ red = .75; green = .15; blue = .0; }else{ red = .9; green = .9; blue = .9; } break; case IRON: red = 3*(hue+.03); green = 3*(hue-.333333); blue = 3*(hue-.666667); break; case ASTRO: red = hue; green = hue; blue = (hue+.2)/1.2; break; case ZEBRA: red = (ihue+invert) % 2; green = red; blue = red; } if(red>1.) red = 1.; if(green>1.) green = 1.; if(blue>1.) blue = 1.; if(red<0.) red = 0.; if(green<0.) green = 0.; if(blue<0.) blue = 0.; r = 255*red; g = 255*green; b = 255*blue; oldhue = hue; if(sat==1.) printf("# %.2g %.2g %.2g\n", r/255.,g/255.,b/255.); } obuf[tx+0] = r; obuf[tx+1] = g; obuf[tx+2] = b; obuf[tx+3] = 0; } } oldsat = sat; } return texture; }