00001 #include <stdio.h>
00002 #include <iostream>
00003 #include "vuTFDesign.h"
00004 #include "vuColour31a.h"
00005
00006
00007
00008
00009
00010 vuTFDesign::vuTFDesign(dword ncomp,
00011 dword range) : vuTFIntensity(ncomp,range)
00012 {
00013
00014 m_Opacities.add(OpacityNode(0,0));
00015 m_Opacities.add(OpacityNode(255,0));
00016 m_Colours.add(ColourNode(255, m_NComp, (float)0));
00017
00018
00019 m_OpacitySmoothing = 0;
00020 m_ColourSmoothing = 0;
00021 generateFunction();
00022 }
00023
00024
00025
00026
00027
00028 dword vuTFDesign::addOpacity(byte intensity, float opacity)
00029 {
00030
00031 dword l = m_Opacities.getLength();
00032 dword i = 0;
00033 for (i=0; i < l; i++)
00034 if (m_Opacities[i].intensity >= intensity) break;
00035
00036
00037 if ((i < l) && m_Opacities[i].intensity==intensity)
00038 m_Opacities[i].opacity = opacity;
00039 else
00040 m_Opacities.insert(i,OpacityNode(intensity,opacity));
00041
00042 return i;
00043 }
00044
00045
00046
00047
00048
00049 void vuTFDesign::removeOpacity(dword index)
00050 {
00051
00052 if (index == 0 || index >= m_Opacities.getLength()-1) return;
00053
00054
00055 m_Opacities.remove(index);
00056 }
00057
00058
00059
00060
00061
00062 dword vuTFDesign::getNumOpacities() const
00063 {
00064 return m_Opacities.getLength();
00065 }
00066
00067
00068
00069
00070
00071 const vuTFDesign::OpacityNode& vuTFDesign::getOpacity(dword index) const
00072 {
00073 return m_Opacities[index];
00074 }
00075
00076
00077
00078 void vuTFDesign::clearAllNodes()
00079 {
00080 m_Opacities.removeRange(0,m_Opacities.getLength());
00081 m_Colours.removeRange(0,m_Colours.getLength());
00082
00083
00084 m_Opacities.add(OpacityNode(0,0));
00085 m_Opacities.add(OpacityNode(m_Range-1,0));
00086 m_Colours.add(ColourNode(m_Range-1, m_NComp, (float)0));
00087
00088
00089 m_OpacitySmoothing = 0;
00090 m_ColourSmoothing = 0;
00091 }
00092
00093
00094
00095
00096
00097 float vuTFDesign::getOpacitySmoothing() const
00098 {
00099 return m_OpacitySmoothing;
00100 }
00101
00102
00103
00104
00105
00106 void vuTFDesign::setOpacitySmoothing(float val)
00107 {
00108 if (val > 1) val = 1;
00109 if (val < 0) val = 0;
00110 m_OpacitySmoothing = val;
00111 }
00112
00113
00114
00115
00116
00117 dword vuTFDesign::addColour(dword intensity, const vuColourN& _col)
00118 {
00119
00120 dword l = m_Colours.getLength();
00121 dword i = 0;
00122 for (i = 0; i < l; i++)
00123 if (m_Colours[i].intensity >= intensity) break;
00124
00125
00126 ColourNode cp(intensity,m_NComp,_col);
00127
00128
00129 if ((i < l) && m_Colours[i].intensity==intensity)
00130 m_Colours[i] = cp;
00131 else
00132 m_Colours.insert(i,cp);
00133
00134 return i;
00135 }
00136
00137
00138
00139
00140
00141 dword vuTFDesign::addColour(dword intensity, const float* _col)
00142 {
00143
00144 dword l = m_Colours.getLength();
00145 dword i = 0;
00146 for (i = 0; i < l; i++)
00147 if (m_Colours[i].intensity >= intensity) break;
00148
00149
00150 ColourNode cp(intensity,m_NComp,_col);
00151
00152
00153 if ((i < l) && m_Colours[i].intensity==intensity)
00154 m_Colours[i] = cp;
00155 else
00156 m_Colours.insert(i,cp);
00157
00158 return i;
00159 }
00160
00161
00162
00163
00164
00165 void vuTFDesign::removeColour(dword index)
00166 {
00167
00168 if (index >= m_Colours.getLength() - 1) return;
00169
00170
00171 m_Colours.remove(index);
00172 }
00173
00174
00175
00176
00177
00178 dword vuTFDesign::getNumColours() const
00179 {
00180 return m_Colours.getLength();
00181 }
00182
00183 dword vuTFDesign::getColourNodeIndex(const ColourNode& cnode) const
00184 {
00185 dword i=0;
00186 while(m_Colours[i].intensity<cnode.intensity) i++;
00187 return i;
00188 }
00189
00190
00191
00192
00193
00194 const vuTFDesign::ColourNode& vuTFDesign::getColour(dword index) const
00195 {
00196 return m_Colours[index];
00197 }
00198
00199
00200
00201
00202
00203
00204 float vuTFDesign::getColourSmoothing() const
00205 {
00206 return m_ColourSmoothing;
00207 }
00208
00209
00210
00211
00212
00213
00214 void vuTFDesign::setColourSmoothing(float val)
00215 {
00216 if (val > 1) val = 1;
00217 if (val < 0) val = 0;
00218 m_ColourSmoothing = val;
00219 }
00220
00221
00222
00223
00224
00225 void vuTFDesign::generateFunction()
00226 {
00227 dword index;
00228 dword numColours = m_Colours.getLength();
00229 generateOpacities();
00230
00231
00232
00233 index = 0;
00234 for (dword i = 0; i < numColours; i++)
00235 {
00236 for (; index <= m_Colours[i].intensity; index ++)
00237 {
00238 dword cind = index*m_NComp;
00239 for(dword c=0;c<m_NComp-1;c++) {
00240 m_Table[cind+c] = m_Colours[i].col[c];
00241 }
00242 }
00243 }
00244
00245
00246 smooth(&m_Table[m_NComp-1], m_OpacitySmoothing);
00247 for(dword c=0;c<m_NComp-1;c++) {
00248 smooth(&m_Table[c], m_ColourSmoothing);
00249 }
00250
00251 }
00252
00253
00254 void vuTFDesign::generateOpacities()
00255 {
00256 dword index;
00257 dword numOpacities = m_Opacities.getLength();
00258
00259
00260
00261 index = 0;
00262 for (dword i = 0; i < numOpacities-1; i++)
00263 {
00264 float slope = float(m_Opacities[i+1].opacity - m_Opacities[i].opacity)/
00265 float(m_Opacities[i+1].intensity - m_Opacities[i].intensity);
00266
00267 for (; index <= m_Opacities[i+1].intensity; index ++)
00268 m_Table[index*m_NComp+(m_NComp-1)] = m_Opacities[i].opacity +
00269 slope * (index-m_Opacities[i].intensity);
00270 }
00271 }
00272
00273
00274
00275
00276
00277
00278 void vuTFDesign::smooth(float *data,float percent) const
00279 {
00280 const int num = (int)m_Range;
00281
00282 float *in = new float[num];
00283
00284
00285
00286
00287 for (int i = 0, index = 0; i < num; i++, index+=m_NComp)
00288 in[i] = data[index];
00289
00290
00291 if (percent < 0) percent = 0;
00292 if (percent > 1) percent = 1;
00293 int offset = (int)(num * percent / 2);
00294 for (int i = 0, index = 0; i < num; i++, index+=m_NComp)
00295 {
00296 data[index] = 0;
00297 for (int j = i-offset; j <= i + offset; j++)
00298 {
00299 if (j >= 0)
00300 {
00301 if(j < num)
00302 data[index] += in[j];
00303 else data[index] += in[num-1];
00304 } else data[index] += in[0];
00305 }
00306 data[index] /= (offset*2 + 1);
00307 }
00308 delete [] in;
00309 }
00310
00311
00312 bool vuTFDesign::loadTF(const char* fname)
00313 {
00314 try {
00315 Parse(fname);
00316 } catch(const char *msg) {
00317 cout << msg << endl;
00318 return false;
00319 }
00320 return true;
00321 }
00322
00323
00324 bool vuTFDesign::saveTF(const char* fname) const
00325 {
00326 ofstream ofp;
00327 ofp.open(fname, ios::out);
00328
00329 writeTFunc(ofp);
00330
00331 return true;
00332 }
00333
00334 void vuTFDesign::writeTFunc(ofstream &ofp) const
00335 {
00336 writeNComp(ofp);
00337 writeOpacities(ofp);
00338 writeColours(ofp);
00339 }
00340
00341 bool vuTFDesign::writeNComp(ofstream &ofp) const
00342 {
00343 ofp << "components("<< m_NComp-1 << ")" << endl;
00344 return true;
00345 }
00346
00347 bool vuTFDesign::readNComp()
00348 {
00349 if(readString("components")) {
00350 float ncomp;
00351 if(!readNumber(" ( ", ncomp)) throw "Error reading number of components.";
00352 else readString(" ) ");
00353 if(m_NComp != ncomp+1) {
00354 m_NComp = int(ncomp)+1;
00355 cout<<"Changing transfer function format to "<<m_NComp-1<<"+1 components."<<endl;
00356 init(m_NComp,m_Range);
00357 }
00358 return true;
00359 } else return false;
00360 }
00361
00362 bool vuTFDesign::writeOpacities(ofstream &ofp) const
00363 {
00364
00365 dword nopa = getNumOpacities();
00366 for(dword o=0;o<nopa;o++) {
00367 ofp<<"opacity("<<getOpacity(o).intensity<<", "<<getOpacity(o).opacity<<")"<<endl;
00368 }
00369 ofp<<endl;
00370 return true;
00371 }
00372
00373 bool vuTFDesign::writeColours(ofstream &ofp) const
00374 {
00375
00376 dword ncol = getNumColours();
00377 for(dword o=0;o<ncol;o++) {
00378 ofp<<"colour("<<getColour(o).intensity;
00379 for(dword c=0;c<m_NComp;c++)
00380 ofp<<", "<<getColour(o).col[c];
00381 ofp<<")"<<endl<<endl;
00382 }
00383 ofp<<endl;
00384 return true;
00385 }
00386
00387
00388
00389
00390
00391 vuTFDesign::ColourNode::ColourNode(byte inten, dword ncomp, const vuColourN& _col)
00392 {
00393 intensity = inten;
00394 if((dword)_col.nComponents() == ncomp) {
00395 for(dword c=0;c<ncomp;c++) {
00396 col[c] = _col[c];
00397 }
00398 }
00399 }
00400
00401
00402
00403
00404
00405 vuTFDesign::ColourNode::ColourNode(byte inten, dword ncomp, const float* _col)
00406 {
00407 intensity = inten;
00408 for(dword c=0;c<ncomp;c++) {
00409 col[c] = _col[c];
00410 }
00411 }
00412
00413
00414
00415
00416
00417 vuTFDesign::ColourNode::ColourNode(byte inten, dword ncomp, float val)
00418 {
00419 intensity = inten;
00420
00421 for(dword c=0;c<ncomp;c++)
00422 col[c] = val;
00423 }
00424
00425
00426
00427
00428 void vuTFDesign::Parse(const char* filename) throw (const char *)
00429 {
00430 readBuffer(filename);
00431 FixBuffer();
00432 parseTFunc();
00433 }
00434
00435 void vuTFDesign::parseTFunc()
00436 {
00437 clearAllNodes();
00438
00439 bool read = true;
00440 while (read) {
00441 read = false;
00442 if ( readOpacity() ) { read = true; }
00443 else if ( readColour() ) { read = true; }
00444 else if ( readNComp() ) { read = true; };
00445 }
00446 }
00447
00448 bool vuTFDesign::readColour()
00449 {
00450 if( readString("colour") ) {
00451 float intensity;
00452 float col[32];
00453 if(!readNumber(" ( ",intensity)) throw "Error reading colour.";
00454 bool read = true;
00455 dword c = 0;
00456 while (read && c<32) {
00457 read = false;
00458 if(readNumber(" , ",col[c])) {
00459 read = true;
00460 c++;
00461 } else if(readString(" ) ")) read = false;
00462 }
00463 if(c==32) readString(" ) ");
00464 else if(c==0) throw "Error reading colour components";
00465 while(c<32) col[c++] = 0.0f;
00466 addColour((dword)intensity,col);
00467 return true;
00468 } else return false;
00469 }
00470
00471 bool vuTFDesign::readOpacity()
00472 {
00473 if( readString("opacity") ) {
00474 float intensity;
00475 float opa;
00476 if(readNumber(" ( ",intensity) &&
00477 readNumber(" , ",opa) &&
00478 readString(" ) ")) {
00479 addOpacity((dword)intensity,opa);
00480 return true;
00481 } else throw "Error reading opacity.";
00482 } else return false;
00483 }
00484