1 /***********************************************************************/
2 /* Open Visualization Data Explorer                                    */
3 /* (C) Copyright IBM Corp. 1989,1999                                   */
4 /* ALL RIGHTS RESERVED                                                 */
5 /* This code licensed under the                                        */
6 /*    "IBM PUBLIC LICENSE - Open Visualization Data Explorer"          */
7 /***********************************************************************/
8 /*
9  */
10 
11 #include <dxconfig.h>
12 
13 
14 /***
15 MODULE:
16     AutoGrayScale
17 SHORTDESCRIPTION:
18     Adds color and opacity information to data, to prepare it for rendering.
19 CATEGORY:
20  Data Transformation
21 INPUTS:
22    data;   scalar field;  NULL; field to color
23    opacity;   scalar;     data dependent;            opacity
24    hue; scalar;     data dependent;            color
25    start;     scalar;     0.6666;          starting color (default blue)
26    range;     scalar;     0.6666;          range of color (default blue -> red)
27    saturation; scalar;    1.00;          saturation
28    min;       scalar or scalar field; data dependent; minimum of data to map
29    max;       scalar or scalar field; data dependent; maximum of data to map
30    delayed;   flag; 0; delay application of color and opacity maps
31 OUTPUTS:
32    mapped;     color field;        NULL; color mapped input field
33    colormap; field;       NULL; rgb color map used
34 FLAGS:
35 BUGS:
36 AUTHOR:
37     dl gresh
38 END:
39 ***/
40 
41 #include <string.h>
42 #include <ctype.h>
43 #include <dx/dx.h>
44 #include "_autogray.h"
45 #include "_autocolor.h"
46 #include "_glyph.h"
47 
48 int
m_AutoGrayScale(Object * in,Object * out)49 m_AutoGrayScale(Object *in, Object *out)
50 {
51     Group g_in;
52     Array onearray=NULL;
53     float opacity, hue, phase, range, saturation;
54     float  inputmin,   inputmax, r, g, b;
55     float *inputminp=(&inputmin), *inputmaxp=(&inputmax);
56     int    used_object, delayed, i, count, one=1;
57     Object colormap;
58     char *colorstr, newstring[21];
59     RGBColor colorvecmin, colorvecmax;
60     RGBColor cv[2];
61 
62 
63 /* at this point it is assumed that the input group g_in is a composite
64    field (i.e. that all of the subfields are of a uniform type). */
65 
66     if(!(g_in = (Group)in[0])) {
67 	out[0] = NULL;
68         /* missing first parameter */
69 	DXSetError(ERROR_MISSING_DATA, "#10000", "data");
70 	return ERROR;
71     }
72 
73     if (!(_dxfFieldWithInformation((Object)in[0]))) {
74 	out[0] = in[0];
75         out[1] = (Object)DXNewField();
76 	return OK;
77     }
78 
79     if (!in[1])
80 	opacity = -1.0;
81     else if (!DXExtractFloat((Object)in[1],&opacity)) {
82         /* bad opacity input; must be a float between 0 and 1 */
83 	DXSetError(ERROR_BAD_PARAMETER,"#10110", "opacity", 0, 1);
84 	return ERROR;
85     }
86     else if ((opacity < 0.0)||(opacity > 1.0)) {
87         /* bad opacity input; must be a float between 0 and 1 */
88         DXSetError(ERROR_BAD_PARAMETER,"#10110", "opacity", 0, 1);
89         return ERROR;
90     }
91     if (!in[2])
92 	hue = 0.66666;
93     else if (!DXExtractFloat((Object)in[2],&hue)) {
94         /* bad hue input; must be a scalar value*/
95 	DXSetError(ERROR_BAD_PARAMETER,"#10080","hue");
96 	return ERROR;
97     }
98 
99     if (!in[3])
100 	phase = 0.0;
101     else if (!DXExtractFloat((Object)in[3],&phase)) {
102         /* bad phase, must be a float */
103 	DXSetError(ERROR_BAD_PARAMETER,"#10090", "start");
104 	return ERROR;
105     }
106     if (phase < 0.0) {
107 	DXSetError(ERROR_BAD_PARAMETER,"#10090", "start");
108 	return ERROR;
109     }
110 
111     if (!in[4])
112 	range =  1.0;
113     else if (!DXExtractFloat((Object)in[4],&range)) {
114         /* bad range, must be a float */
115 	DXSetError(ERROR_BAD_PARAMETER,"#10080","range");
116 	return ERROR;
117     }
118 
119     if (phase+range < 0.0) {
120         DXSetError(ERROR_BAD_PARAMETER,"#10090", "start+range");
121         return ERROR;
122     }
123 
124     if (!in[5])
125 	saturation = 0.0;
126     else if (!DXExtractFloat((Object)in[5],&saturation)) {
127         /* bad saturation, must be a float between 0 and 1 */
128 	DXSetError(ERROR_BAD_PARAMETER,"#10110","saturation", 0, 1);
129 	return ERROR;
130     }
131     else if ((saturation < 0.0)||(saturation > 1.0)) {
132         /* bad saturation input; must be a float between 0 and 1 */
133         DXSetError(ERROR_BAD_PARAMETER,"#10110", "saturation", 0, 1);
134         return ERROR;
135     }
136 
137     /* if in[6] is an object, and in[7] is null, then we want to
138        make inputmax be the max of the object, rather than the normal
139        default */
140 
141     used_object = 0;
142 
143 
144     if (!in[6])
145 	inputminp = NULL;
146     else if (!DXExtractFloat((Object)in[6],inputminp)) {
147 	if (_dxfIsFieldorGroup((Object)in[6])) {
148 	    /* get max and min */
149 	    if (!DXStatistics((Object)in[6],"data",inputminp,inputmaxp,
150 			    NULL,NULL))
151 	    {
152                 /* min must be a field or a scalar value */
153 		DXAddMessage("min parameter");
154 		return ERROR;
155 	    }
156 	    else
157 		used_object++;
158 	}
159 	else {
160             /* min must be a field or a scalar value */
161 	    DXSetError(ERROR_BAD_PARAMETER,"#10520","min");
162 	    return ERROR;
163 	}
164     }
165 
166     if (!in[7]) {
167 	if (!used_object)
168 	    inputmaxp = NULL;
169 /*         implicit else, max was set above  */
170        }
171     else if (!DXExtractFloat((Object)in[7],inputmaxp)) {
172 	if (_dxfIsFieldorGroup((Object)in[7])) {
173 	    if (!DXStatistics((Object)in[7],"data",NULL,inputmaxp,NULL,
174 			    NULL)) {
175                 /* max must be a field or a scalar value */
176 		DXAddMessage("max parameter");
177 		return ERROR;
178 	    }
179 	}
180 	else {
181             /* max must be a field or a scalar value */
182 	    DXSetError(ERROR_BAD_PARAMETER,"#10520", "max");
183 	    return ERROR;
184 	}
185     }
186 
187     if (!in[8])
188 	delayed = 0;
189     else {
190         if (!(DXExtractInteger(in[8],&delayed))) {
191 	    DXSetError(ERROR_BAD_PARAMETER, "#10070", "delayed");
192             return ERROR;
193         }
194         if ((delayed != 0)&&(delayed != 1)) {
195 	    DXSetError(ERROR_BAD_PARAMETER, "#10070", "delayed");
196             return ERROR;
197         }
198       }
199 
200 
201     if (!in[9]) {
202       /* the default */
203       _dxfHSVtoRGB(hue, saturation, phase, &r, &g, &b);
204       colorvecmin = DXRGB(r, g, b);
205       _dxfHSVtoRGB(hue, saturation, phase+range, &r, &g, &b);
206       colorvecmax = DXRGB(r, g, b);
207     }
208     /* first try a string */
209     else if (DXExtractNthString(in[9], 0, &colorstr)) {
210       /* is it a valid color name? */
211       if (!(DXColorNameToRGB(colorstr, &colorvecmin))) {
212         /* if it's not a valid colorname, is it "min" or "max"? */
213         count = 0;
214         i=0;
215         while (i<20 && colorstr[i] != '\0') {
216           for (i=0; i< 20; i++) {
217             if (isalpha(colorstr[i])) {
218               newstring[count]=tolower(colorstr[i]);
219               count++;
220             }
221             else {
222               if (colorstr[i] != ' ') {
223                 newstring[count] = colorstr[i];
224                 count++;
225               }
226             }
227           }
228         }
229         if (!strcmp(newstring, "colorofmin")) {
230           DXResetError();
231           _dxfHSVtoRGB(hue, saturation, phase, &r, &g, &b);
232           colorvecmin = DXRGB(r,g,b);
233         }
234         else if (!strcmp(newstring,"colorofmax")) {
235           DXResetError();
236           _dxfHSVtoRGB(hue, saturation, phase+range, &r, &g, &b);
237           colorvecmin = DXRGB(r,g,b);
238         }
239         else goto error;
240       }
241       /* start by setting max = min */
242       colorvecmax=colorvecmin;
243       /* now look and see if there's a second string hanging around */
244       if (DXExtractNthString(in[9], 1, &colorstr)) {
245         /* is it a valid color name? */
246         if (!(DXColorNameToRGB(colorstr, &colorvecmax))) {
247           /* if it's not a valid colorname, is it "min" or "max"? */
248           count = 0;
249           i=0;
250           while (i<20 && colorstr[i] != '\0') {
251             for (i=0; i< 20; i++) {
252               if (isalpha(colorstr[i])) {
253                 newstring[count]=tolower(colorstr[i]);
254                 count++;
255               }
256               else {
257                 if (colorstr[i] != ' ') {
258                   newstring[count] = colorstr[i];
259                   count++;
260                 }
261               }
262             }
263           }
264           if (!strcmp(newstring, "colorofmin")) {
265             DXResetError();
266             _dxfHSVtoRGB(hue, saturation, phase, &r, &g, &b);
267             colorvecmax = DXRGB(r,g,b);
268           }
269           else if (!strcmp(newstring,"colorofmax")) {
270             DXResetError();
271             _dxfHSVtoRGB(hue, saturation, phase+range, &r, &g, &b);
272             colorvecmax = DXRGB(r,g,b);
273           }
274           else goto error;
275         }
276       }
277     }
278     else if ((DXExtractParameter(in[9], TYPE_FLOAT, 3, 1,
279                                  (Pointer)&colorvecmin))) {
280       colorvecmax = colorvecmin;
281     }
282     else if ((DXExtractParameter(in[9], TYPE_FLOAT, 3, 2, (Pointer)&cv))) {
283       colorvecmin = cv[0];
284       colorvecmax = cv[1];
285     }
286     else {
287       DXSetError(ERROR_BAD_PARAMETER,
288                  "outofrange must be a color string or pair of color strings, \"color of min\" or \"color of max\", or a 3-vector or pair of 3 vectors");
289       goto error;
290     }
291 
292 
293     out[0] = (Object)_dxfAutoGrayScale((Object)g_in, opacity,
294 				       hue, phase, range, saturation,
295 				       inputminp, inputmaxp,
296 				       &colormap, delayed,
297 				       colorvecmin, colorvecmax);
298     if (out[0]) out[1] = (Object)colormap;
299 
300     /* for delayed colors, add the direct color map attribute */
301     if (delayed) {
302        onearray = DXNewArray(TYPE_INT,CATEGORY_REAL, 0);
303        if (!DXAddArrayData(onearray, 0, 1, &one))
304            goto error;
305        if (!DXSetAttribute(out[0], "direct color map", (Object) onearray))
306            goto error;
307        onearray = NULL;
308     }
309 
310 
311 
312 
313     if ((!out[0])||(!(out[1])))
314       return ERROR;
315     else
316       return OK;
317 
318   error:
319     DXDelete((Object)onearray);
320     return ERROR;
321   }
322 
323 
324 
325 
326