Salome HOME
sources v1.2c
[modules/visu.git] / src / PIPELINE / VISU_LookupTable.cxx
1 //  VISU OBJECT : interactive object for VISU entities implementation
2 //
3 //  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS 
5 // 
6 //  This library is free software; you can redistribute it and/or 
7 //  modify it under the terms of the GNU Lesser General Public 
8 //  License as published by the Free Software Foundation; either 
9 //  version 2.1 of the License. 
10 // 
11 //  This library is distributed in the hope that it will be useful, 
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of 
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
14 //  Lesser General Public License for more details. 
15 // 
16 //  You should have received a copy of the GNU Lesser General Public 
17 //  License along with this library; if not, write to the Free Software 
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA 
19 // 
20 //  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
21 //
22 //
23 //  File   : VISU_LookupTable.cxx
24 //  Author : Vitaliy Smetannikov
25 //  Module : VISU
26
27 #include "VISU_LookupTable.hxx"
28
29 #include <vtkObjectFactory.h>
30 #include <vtkBitArray.h>
31 #include <math.h>
32
33 using namespace std;
34
35 VISU_LookupTable *VISU_LookupTable::New() {
36   vtkObject* ret = vtkObjectFactory::CreateInstance("VISU_LookupTable");
37   if(ret)
38     return (VISU_LookupTable*)ret;
39   return new VISU_LookupTable;
40 }
41
42 VISU_LookupTable::VISU_LookupTable(int sze, int ext)
43   : vtkLookupTable(sze, ext), myScale(1.0) {}
44
45 int VISU_LookupTable::ComputeLogRange(float inRange[2], float outRange[2]){
46   if(inRange[0] >= inRange[1])
47     return -1;
48   if(0.0 <= inRange[0] && 0.0 < inRange[1]){
49     if(inRange[0] != 0.0)
50       outRange[0] = log10((double)inRange[0]);
51     else
52       outRange[0] = log10((double)inRange[1]*1.0E-6);
53     outRange[1] = log10((double)inRange[1]);
54     return 0;
55   }else if(inRange[0] < 0.0 && inRange[1] <= 0.0){
56     outRange[0] = log10((double)-inRange[0]);
57     outRange[1] = log10((double)-inRange[1]);
58     return 1;
59   }else
60     return -1;
61 }
62
63 unsigned char* VISU_LookupTable::MapValue(float v) {
64   if(GetScale() == VTK_SCALE_LOG10) {
65     float aLowBound = log10(this->TableRange[0]);
66     v = pow(10.0f,aLowBound + (v - aLowBound)*myScale);
67     return vtkLookupTable::MapValue(v);
68   }else{
69     v = this->TableRange[0] + (v - this->TableRange[0])*myScale;
70     return vtkLookupTable::MapValue(v);
71   }
72 }
73
74 // Apply log to value, with appropriate constraints.
75 inline float VISU_ApplyLogScale(float v, float range[2], 
76                                 float logRange[2])
77 {
78   // is the range set for negative numbers?
79   if (range[0] < 0)
80     {
81     if (v < 0)
82       {
83       v = log10(-static_cast<double>(v));
84       }
85     else if (range[0] > range[1])
86       {
87       v = logRange[0];
88       }
89     else
90       {
91       v = logRange[1];
92       }
93     }
94   else
95     {
96     if (v > 0)
97       {
98       v = log10(static_cast<double>(v));
99       }
100     else if (range[0] < range[1])
101       {
102       v = logRange[0];
103       }
104     else
105       {
106       v = logRange[1];
107       }
108     }
109   return v;
110 }                 
111
112 // Apply shift/scale to the scalar value v and do table lookup.
113 inline unsigned char *VISU_LinearLookup(float v,   
114                                         unsigned char *table,
115                                         float maxIndex,
116                                         float shift, float scale)
117 {
118   float findx = (v + shift)*scale;
119   if (findx < 0)
120     {
121     findx = 0;
122     }
123   if (findx > maxIndex)
124     {
125     findx = maxIndex;
126     }
127   return &table[4*static_cast<int>(findx)];
128   /* round
129   return &table[4*(int)(findx + 0.5f)];
130   */
131 }
132
133 // accelerate the mapping by copying the data in 32-bit chunks instead
134 // of 8-bit chunks
135 template<class T>
136 void VISU_LookupTableMapData(vtkLookupTable *self, T *input, 
137                            unsigned char *output, int length, 
138                            int inIncr, int outFormat, float theMapScale)
139 {
140   int i = length;
141   float *range = self->GetTableRange();
142   float maxIndex = self->GetNumberOfColors() - 1;
143   float shift, scale;
144   unsigned char *table = self->GetPointer(0);
145   unsigned char *cptr;
146   float alpha;
147
148   if ( (alpha=self->GetAlpha()) >= 1.0 ) //no blending required 
149     {
150     if (self->GetScale() == VTK_SCALE_LOG10)
151       {
152       float val;
153       float logRange[2];
154       VISU_LookupTable::ComputeLogRange(range, logRange);
155       shift = -logRange[0];
156       if (logRange[1] <= logRange[0])
157         {
158         scale = VTK_LARGE_FLOAT;
159         }
160       else
161         {
162         scale = (maxIndex + 1)/(logRange[1] - logRange[0]);
163         }
164       /* correct scale
165       scale = maxIndex/(logRange[1] - logRange[0]);
166       */
167       if (outFormat == VTK_RGBA)
168         {
169         while (--i >= 0) 
170           {
171           val = VISU_ApplyLogScale(*input, range, logRange);
172           cptr = VISU_LinearLookup(val, table, maxIndex, shift, scale*theMapScale); 
173           *output++ = *cptr++;
174           *output++ = *cptr++;
175           *output++ = *cptr++;
176           *output++ = *cptr++;     
177           input += inIncr;
178           }
179         }
180       else if (outFormat == VTK_RGB)
181         {
182         while (--i >= 0) 
183           {
184           val = VISU_ApplyLogScale(*input, range, logRange);
185           cptr = VISU_LinearLookup(val, table, maxIndex, shift, scale*theMapScale); 
186           *output++ = *cptr++;
187           *output++ = *cptr++;
188           *output++ = *cptr++;
189           input += inIncr;
190           }
191         }
192       else if (outFormat == VTK_LUMINANCE_ALPHA)
193         {
194         while (--i >= 0) 
195           {
196           val = VISU_ApplyLogScale(*input, range, logRange);
197           cptr = VISU_LinearLookup(val, table, maxIndex, shift, scale*theMapScale); 
198           *output++ = static_cast<unsigned char>(cptr[0]*0.30 + cptr[1]*0.59 + 
199                                                  cptr[2]*0.11 + 0.5);
200           *output++ = cptr[3];
201           input += inIncr;
202           }
203         }
204       else // outFormat == VTK_LUMINANCE
205         {
206         while (--i >= 0) 
207           {
208           val = VISU_ApplyLogScale(*input, range, logRange);
209           cptr = VISU_LinearLookup(val, table, maxIndex, shift, scale*theMapScale); 
210           *output++ = static_cast<unsigned char>(cptr[0]*0.30 + cptr[1]*0.59 + 
211                                                  cptr[2]*0.11 + 0.5);
212           input += inIncr;
213           }
214         }
215       }//if log scale
216
217     else //not log scale
218       {
219       shift = -range[0];
220       if (range[1] <= range[0])
221         {
222         scale = VTK_LARGE_FLOAT;
223         }
224       else
225         {
226         scale = (maxIndex + 1)/(range[1] - range[0]);
227         }
228       /* correct scale
229       scale = maxIndex/(range[1] - range[0]);
230       */
231
232       if (outFormat == VTK_RGBA)
233         {
234         while (--i >= 0) 
235           {
236           cptr = VISU_LinearLookup(*input, table, maxIndex, shift, scale*theMapScale); 
237           *output++ = *cptr++;
238           *output++ = *cptr++;
239           *output++ = *cptr++;
240           *output++ = *cptr++;     
241           input += inIncr;
242           }
243         }
244       else if (outFormat == VTK_RGB)
245         {
246         while (--i >= 0) 
247           {
248           cptr = VISU_LinearLookup(*input, table, maxIndex, shift, scale*theMapScale); 
249           *output++ = *cptr++;
250           *output++ = *cptr++;
251           *output++ = *cptr++;
252           input += inIncr;
253           }
254         }
255       else if (outFormat == VTK_LUMINANCE_ALPHA)
256         {
257         while (--i >= 0) 
258           {
259           cptr = VISU_LinearLookup(*input, table, maxIndex, shift, scale*theMapScale); 
260           *output++ = static_cast<unsigned char>(cptr[0]*0.30 + cptr[1]*0.59 + 
261                                                  cptr[2]*0.11 + 0.5);
262           *output++ = cptr[3];
263           input += inIncr;
264           }
265         }
266       else // outFormat == VTK_LUMINANCE
267         {
268         while (--i >= 0) 
269           {
270           cptr = VISU_LinearLookup(*input, table, maxIndex, shift, scale*theMapScale); 
271           *output++ = static_cast<unsigned char>(cptr[0]*0.30 + cptr[1]*0.59 + 
272                                                  cptr[2]*0.11 + 0.5);
273           input += inIncr;
274           }
275         }
276       }//if not log lookup
277     }//if blending not needed
278
279   else //blend with the specified alpha
280     {
281     if (self->GetScale() == VTK_SCALE_LOG10)
282       {
283       float val;
284       float logRange[2];
285       VISU_LookupTable::ComputeLogRange(range, logRange);
286       shift = -logRange[0];
287       if (logRange[1] <= logRange[0])
288         {
289         scale = VTK_LARGE_FLOAT;
290         }
291       else
292         {
293         scale = (maxIndex + 1)/(logRange[1] - logRange[0]);
294         }
295       /* correct scale
296       scale = maxIndex/(logRange[1] - logRange[0]);
297       */
298       if (outFormat == VTK_RGBA)
299         {
300         while (--i >= 0) 
301           {
302           val = VISU_ApplyLogScale(*input, range, logRange);
303           cptr = VISU_LinearLookup(val, table, maxIndex, shift, scale*theMapScale); 
304           *output++ = *cptr++;
305           *output++ = *cptr++;
306           *output++ = *cptr++;
307           *output++ = static_cast<unsigned char>((*cptr)*alpha); cptr++;
308           input += inIncr;
309           }
310         }
311       else if (outFormat == VTK_RGB)
312         {
313         while (--i >= 0) 
314           {
315           val = VISU_ApplyLogScale(*input, range, logRange);
316           cptr = VISU_LinearLookup(val, table, maxIndex, shift, scale*theMapScale); 
317           *output++ = *cptr++;
318           *output++ = *cptr++;
319           *output++ = *cptr++;
320           input += inIncr;
321           }
322         }
323       else if (outFormat == VTK_LUMINANCE_ALPHA)
324         {
325         while (--i >= 0) 
326           {
327           val = VISU_ApplyLogScale(*input, range, logRange);
328           cptr = VISU_LinearLookup(val, table, maxIndex, shift, scale*theMapScale); 
329           *output++ = static_cast<unsigned char>(cptr[0]*0.30 + cptr[1]*0.59 + 
330                                                  cptr[2]*0.11 + 0.5);
331           *output++ = static_cast<unsigned char>(alpha*cptr[3]);
332           input += inIncr;
333           }
334         }
335       else // outFormat == VTK_LUMINANCE
336         {
337         while (--i >= 0) 
338           {
339           val = VISU_ApplyLogScale(*input, range, logRange);
340           cptr = VISU_LinearLookup(val, table, maxIndex, shift, scale*theMapScale); 
341           *output++ = static_cast<unsigned char>(cptr[0]*0.30 + cptr[1]*0.59 + 
342                                                  cptr[2]*0.11 + 0.5);
343           input += inIncr;
344           }
345         }
346       }//log scale with blending
347
348     else //no log scale with blending
349       {
350       shift = -range[0];
351       if (range[1] <= range[0])
352         {
353         scale = VTK_LARGE_FLOAT;
354         }
355       else
356         {
357         scale = (maxIndex + 1)/(range[1] - range[0]);
358         }
359       /* correct scale
360       scale = maxIndex/(range[1] - range[0]);
361       */
362
363       if (outFormat == VTK_RGBA)
364         {
365         while (--i >= 0) 
366           {
367           cptr = VISU_LinearLookup(*input, table, maxIndex, shift, scale); 
368           *output++ = *cptr++;
369           *output++ = *cptr++;
370           *output++ = *cptr++;
371           *output++ = static_cast<unsigned char>((*cptr)*alpha); cptr++;
372           input += inIncr;
373           }
374         }
375       else if (outFormat == VTK_RGB)
376         {
377         while (--i >= 0) 
378           {
379           cptr = VISU_LinearLookup(*input, table, maxIndex, shift, scale); 
380           *output++ = *cptr++;
381           *output++ = *cptr++;
382           *output++ = *cptr++;
383           input += inIncr;
384           }
385         }
386       else if (outFormat == VTK_LUMINANCE_ALPHA)
387         {
388         while (--i >= 0) 
389           {
390           cptr = VISU_LinearLookup(*input, table, maxIndex, shift, scale); 
391           *output++ = static_cast<unsigned char>(cptr[0]*0.30 + cptr[1]*0.59 + 
392                                                  cptr[2]*0.11 + 0.5);
393           *output++ = static_cast<unsigned char>(cptr[3]*alpha);
394           input += inIncr;
395           }
396         }
397       else // outFormat == VTK_LUMINANCE
398         {
399         while (--i >= 0) 
400           {
401           cptr = VISU_LinearLookup(*input, table, maxIndex, shift, scale); 
402           *output++ = static_cast<unsigned char>(cptr[0]*0.30 + cptr[1]*0.59 + 
403                                                  cptr[2]*0.11 + 0.5);
404           input += inIncr;
405           }
406         }
407       }//no log scale
408     }//alpha blending
409 }
410
411 // Although this is a relatively expensive calculation,
412 // it is only done on the first render. Colors are cached
413 // for subsequent renders.
414 template<class T>
415 void VISU_LookupTableMapMag(vtkLookupTable *self, T *input, 
416                             unsigned char *output, int length, 
417                             int inIncr, int outFormat, float theMapScale)
418 {
419   double tmp, sum;
420   double *mag;
421   int i, j;
422
423   mag = new double[length];
424   for (i = 0; i < length; ++i)
425     {
426     sum = 0;
427     for (j = 0; j < inIncr; ++j)
428       {
429       tmp = (double)(*input);  
430       sum += (tmp * tmp);
431       ++input;
432       }
433     mag[i] = sqrt(sum);
434     }
435
436   VISU_LookupTableMapData(self, mag, output, length, 1, outFormat, theMapScale);
437
438   delete [] mag;
439 }
440
441
442 void VISU_LookupTable::MapScalarsThroughTable2(void *input, 
443                                                unsigned char *output,
444                                                int inputDataType, 
445                                                int numberOfValues,
446                                                int inputIncrement,
447                                                int outputFormat)
448 {
449   if (this->UseMagnitude && inputIncrement > 1)
450     {
451     switch (inputDataType)
452       {
453       case VTK_BIT:
454         vtkErrorMacro("Cannot comput magnitude of bit array.");
455         break;
456       case VTK_CHAR:
457         VISU_LookupTableMapMag(this,static_cast<char *>(input),output,
458                                numberOfValues,inputIncrement,outputFormat,myScale);
459         return; 
460       case VTK_UNSIGNED_CHAR:
461         VISU_LookupTableMapMag(this,static_cast<unsigned char *>(input),output,
462                              numberOfValues,inputIncrement,outputFormat,myScale);
463         return;
464       case VTK_SHORT:
465         VISU_LookupTableMapMag(this,static_cast<short *>(input),output,
466                              numberOfValues,inputIncrement,outputFormat,myScale);
467         return;
468       case VTK_UNSIGNED_SHORT:
469         VISU_LookupTableMapMag(this,static_cast<unsigned short *>(input),output,
470                              numberOfValues,inputIncrement,outputFormat,myScale);
471         return;
472       case VTK_INT:
473         VISU_LookupTableMapMag(this,static_cast<int *>(input),output,
474                              numberOfValues,inputIncrement,outputFormat,myScale);
475         return;
476       case VTK_UNSIGNED_INT:
477         VISU_LookupTableMapMag(this,static_cast<unsigned int *>(input),output,
478                              numberOfValues,inputIncrement,outputFormat,myScale);
479         return;
480       case VTK_LONG:
481         VISU_LookupTableMapMag(this,static_cast<long *>(input),output,
482                              numberOfValues,inputIncrement,outputFormat,myScale);
483         return;
484       case VTK_UNSIGNED_LONG:
485         VISU_LookupTableMapMag(this,static_cast<unsigned long *>(input),output,
486                              numberOfValues,inputIncrement,outputFormat,myScale);
487         return;
488       case VTK_FLOAT:
489         VISU_LookupTableMapMag(this,static_cast<float *>(input),output,
490                              numberOfValues,inputIncrement,outputFormat,myScale);
491         return;
492       case VTK_DOUBLE:
493         VISU_LookupTableMapMag(this,static_cast<double *>(input),output,
494                              numberOfValues,inputIncrement,outputFormat,myScale);
495         return;
496       default:
497         vtkErrorMacro(<< "MapImageThroughTable: Unknown input ScalarType");
498         return;
499       }
500     }
501
502   switch (inputDataType)
503     {
504     case VTK_BIT:
505       {
506       vtkIdType i, id;
507       vtkBitArray *bitArray = vtkBitArray::New();
508       bitArray->SetVoidArray(input,numberOfValues,1);
509       vtkUnsignedCharArray *newInput = vtkUnsignedCharArray::New();
510       newInput->SetNumberOfValues(numberOfValues);
511       for (id=i=0; i<numberOfValues; i++, id+=inputIncrement)
512         {
513         newInput->SetValue(i, bitArray->GetValue(id));
514         }
515       VISU_LookupTableMapData(this,
516                               static_cast<unsigned char*>(newInput->GetPointer(0)),
517                               output,numberOfValues,
518                               inputIncrement,outputFormat,myScale);
519       newInput->Delete();
520       bitArray->Delete();
521       }
522       break;
523       
524     case VTK_CHAR:
525       VISU_LookupTableMapData(this,static_cast<char *>(input),output,
526                               numberOfValues,inputIncrement,outputFormat,myScale);
527       break;
528       
529     case VTK_UNSIGNED_CHAR:
530       VISU_LookupTableMapData(this,static_cast<unsigned char *>(input),output,
531                               numberOfValues,inputIncrement,outputFormat,myScale);
532       break;
533       
534     case VTK_SHORT:
535       VISU_LookupTableMapData(this,static_cast<short *>(input),output,
536                               numberOfValues,inputIncrement,outputFormat,myScale);
537       break;
538       
539     case VTK_UNSIGNED_SHORT:
540       VISU_LookupTableMapData(this,static_cast<unsigned short *>(input),output,
541                               numberOfValues,inputIncrement,outputFormat,myScale);
542       break;
543       
544     case VTK_INT:
545       VISU_LookupTableMapData(this,static_cast<int *>(input),output,
546                               numberOfValues,inputIncrement,outputFormat,myScale);
547       break;
548       
549     case VTK_UNSIGNED_INT:
550       VISU_LookupTableMapData(this,static_cast<unsigned int *>(input),output,
551                               numberOfValues,inputIncrement,outputFormat,myScale);
552       break;
553       
554     case VTK_LONG:
555       VISU_LookupTableMapData(this,static_cast<long *>(input),output,
556                               numberOfValues,inputIncrement,outputFormat,myScale);
557       break;
558       
559     case VTK_UNSIGNED_LONG:
560       VISU_LookupTableMapData(this,static_cast<unsigned long *>(input),output,
561                               numberOfValues,inputIncrement,outputFormat,myScale);
562       break;
563       
564     case VTK_FLOAT:
565       VISU_LookupTableMapData(this,static_cast<float *>(input),output,
566                               numberOfValues,inputIncrement,outputFormat,myScale);
567       break;
568       
569     case VTK_DOUBLE:
570       VISU_LookupTableMapData(this,static_cast<double *>(input),output,
571                               numberOfValues,inputIncrement,outputFormat,myScale);
572       break;
573       
574     default:
575       vtkErrorMacro(<< "MapImageThroughTable: Unknown input ScalarType");
576       return;
577     }
578 }  
579