00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifndef __VCG_TRI_UPDATE_COLOR
00025 #define __VCG_TRI_UPDATE_COLOR
00026
00027 #include <limits>
00028 #include <math.h>
00029 #include <time.h>
00030 #include <vcg/space/color4.h>
00031 #include <vcg/math/histogram.h>
00032 #include <vcg/math/perlin_noise.h>
00033 #include <vcg/math/random_generator.h>
00034 #include <vcg/complex/algorithms/clean.h>
00035 #include <vcg/complex/algorithms/stat.h>
00036
00037 namespace vcg {
00038 namespace tri {
00039
00052 template <class MeshType>
00053 class UpdateColor
00054 {
00055 public:
00056 typedef typename MeshType::VertexType VertexType;
00057 typedef typename MeshType::VertexPointer VertexPointer;
00058 typedef typename MeshType::VertexIterator VertexIterator;
00059 typedef typename MeshType::FaceType FaceType;
00060 typedef typename MeshType::FacePointer FacePointer;
00061 typedef typename MeshType::FaceIterator FaceIterator;
00062 typedef typename MeshType::EdgeIterator EdgeIterator;
00063
00064 typedef typename MeshType::ScalarType ScalarType;
00065 typedef typename MeshType::CoordType CoordType;
00066
00067 class ColorAvgInfo
00068 {
00069 public:
00070 unsigned int r;
00071 unsigned int g;
00072 unsigned int b;
00073 unsigned int a;
00074 int cnt;
00075 };
00076
00079 static int PerVertexConstant(MeshType &m, Color4b vs=Color4b::White,bool selected=false)
00080 {
00081 RequirePerVertexColor(m);
00082
00083 int cnt=0;
00084 for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi)
00085 if(!(*vi).IsD()){
00086 if(!selected || (*vi).IsS())
00087 {
00088 (*vi).C() = vs;
00089 ++cnt;
00090 }
00091 }
00092 return cnt;
00093 }
00094
00097 static int PerFaceConstant(MeshType &m, Color4b vs=Color4b::White,bool selected=false)
00098 {
00099 RequirePerFaceColor(m);
00100 int cnt=0;
00101 for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi)
00102 if(!(*fi).IsD()){
00103 if(!selected || (*fi).IsS())
00104 {
00105 (*fi).C() = vs;
00106 ++cnt;
00107 }
00108 }
00109 return cnt;
00110 }
00111
00117 static void PerVertexFromFace( MeshType &m)
00118 {
00119 RequirePerFaceColor(m);
00120 RequirePerVertexColor(m);
00121
00122 ColorAvgInfo csi;
00123 csi.r=0; csi.g=0; csi.b=0; csi.cnt=0;
00124 SimpleTempData<typename MeshType::VertContainer, ColorAvgInfo> TD(m.vert,csi);
00125
00126 FaceIterator fi;
00127 for(fi=m.face.begin();fi!=m.face.end();++fi)
00128 if(!(*fi).IsD())
00129 for(int j=0;j<3;++j)
00130 {
00131 TD[(*fi).V(j)].r+=(*fi).C()[0];
00132 TD[(*fi).V(j)].g+=(*fi).C()[1];
00133 TD[(*fi).V(j)].b+=(*fi).C()[2];
00134 TD[(*fi).V(j)].a+=(*fi).C()[3];
00135 ++TD[(*fi).V(j)].cnt;
00136 }
00137
00138 VertexIterator vi;
00139 for(vi=m.vert.begin();vi!=m.vert.end();++vi)
00140 if(!(*vi).IsD() && TD[*vi].cnt>0 )
00141 {
00142 (*vi).C()[0] = TD[*vi].r / TD[*vi].cnt;
00143 (*vi).C()[1] = TD[*vi].g / TD[*vi].cnt;
00144 (*vi).C()[2] = TD[*vi].b / TD[*vi].cnt;
00145 (*vi).C()[3] = TD[*vi].a / TD[*vi].cnt;
00146 }
00147 }
00148
00152 static void PerFaceFromVertex( MeshType &m)
00153 {
00154 RequirePerFaceColor(m);
00155 RequirePerVertexColor(m);
00156
00157 FaceIterator fi;
00158 for(fi=m.face.begin();fi!=m.face.end();++fi) if(!(*fi).IsD())
00159 {
00160 Color4f avg = (Color4f::Construct((*fi).V(0)->C()) +
00161 Color4f::Construct((*fi).V(1)->C()) +
00162 Color4f::Construct((*fi).V(2)->C()) )/ 3.0;
00163 (*fi).C().Import(avg);
00164 }
00165 }
00166
00171 static void PerVertexQualityRamp(MeshType &m, float minq=0, float maxq=0)
00172 {
00173 RequirePerVertexQuality(m);
00174 RequirePerVertexColor(m);
00175
00176 if(minq==maxq)
00177 {
00178 std::pair<float,float> minmax = Stat<MeshType>::ComputePerVertexQualityMinMax(m);
00179 minq=minmax.first;
00180 maxq=minmax.second;
00181 }
00182 for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi)
00183 if(!(*vi).IsD())
00184 (*vi).C().SetColorRamp(minq,maxq,(*vi).Q());
00185 }
00186
00187
00192 static void PerVertexQualityRampParula(MeshType &m, float minq=0, float maxq=0)
00193 {
00194 RequirePerVertexQuality(m);
00195 RequirePerVertexColor(m);
00196
00197 if(minq==maxq)
00198 {
00199 std::pair<float,float> minmax = Stat<MeshType>::ComputePerVertexQualityMinMax(m);
00200 minq=minmax.first;
00201 maxq=minmax.second;
00202 }
00203 for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi)
00204 if(!(*vi).IsD())
00205 (*vi).C().SetColorRampParula(minq,maxq,(*vi).Q());
00206 }
00207
00212 static void PerFaceQualityRamp(MeshType &m, float minq=0, float maxq=0, bool selected=false)
00213 {
00214 RequirePerFaceColor(m);
00215 RequirePerFaceQuality(m);
00216
00217 if(minq==maxq)
00218 {
00219 std::pair<float,float> minmax = Stat<MeshType>::ComputePerFaceQualityMinMax(m);
00220 minq=minmax.first;
00221 maxq=minmax.second;
00222 }
00223 for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi) if(!(*fi).IsD())
00224 if(!selected || (*fi).IsS())
00225 (*fi).C().SetColorRamp(minq,maxq,(*fi).Q());
00226 }
00227
00232 static void PerEdgeQualityRamp(MeshType &m, float minq=0, float maxq=0, bool selected=false)
00233 {
00234 RequirePerEdgeColor(m);
00235 RequirePerEdgeQuality(m);
00236
00237 if(minq==maxq)
00238 {
00239 std::pair<float,float> minmax = Stat<MeshType>::ComputePerEdgeQualityMinMax(m);
00240 minq=minmax.first;
00241 maxq=minmax.second;
00242 }
00243 for(EdgeIterator ei=m.edge.begin();ei!=m.edge.end();++ei) if(!(*ei).IsD())
00244 if(!selected || (*ei).IsS())
00245 (*ei).C().SetColorRamp(minq,maxq,(*ei).Q());
00246 }
00247
00252 static void PerVertexQualityGray(MeshType &m, float minq, float maxq)
00253 {
00254 RequirePerVertexColor(m);
00255 RequirePerVertexQuality(m);
00256 if(minq==maxq)
00257 {
00258 std::pair<float,float> minmax = Stat<MeshType>::ComputePerVertexQualityMinMax(m);
00259 minq=minmax.first;
00260 maxq=minmax.second;
00261 }
00262 for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi)
00263 if(!(*vi).IsD())
00264 (*vi).C().SetGrayShade( ((*vi).Q()-minq)/(maxq-minq));
00265 }
00266
00271 static void PerFaceQualityGray(MeshType &m, float minq=0, float maxq=0)
00272 {
00273 RequirePerFaceColor(m);
00274 RequirePerFaceQuality(m);
00275
00276 if(minq==maxq)
00277 {
00278 std::pair<float,float> minmax = Stat<MeshType>::ComputePerFaceQualityMinMax(m);
00279 minq=minmax.first;
00280 maxq=minmax.second;
00281 }
00282 for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi) if(!(*fi).IsD())
00283 (*fi).C().SetGrayShade( ((*fi).Q()-minq)/(maxq-minq));
00284 }
00285
00297 static void PerVertexBorderFlag( MeshType &m, Color4b BorderColor=Color4b::Blue, Color4b InternalColor=Color4b::White, Color4b MixColor=Color4b::Cyan)
00298 {
00299 RequirePerVertexColor(m);
00300
00301 Color4b BaseColor = Color4b::Green;
00302
00303 PerVertexConstant(m,BaseColor);
00304 for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi) if(!(*fi).IsD())
00305 for(int j=0;j<3;++j)
00306 {
00307 if((*fi).IsB(j)){
00308 if( (*fi).V(j)->C() == BaseColor) (*fi).V(j)->C() = BorderColor;
00309 if( (*fi).V(j)->C() == InternalColor) (*fi).V(j)->C() = MixColor;
00310 if( (*fi).V1(j)->C() == BaseColor) (*fi).V1(j)->C() = BorderColor;
00311 if( (*fi).V1(j)->C() == InternalColor) (*fi).V1(j)->C() = MixColor;
00312 } else
00313 {
00314 if( (*fi).V(j)->C() == BaseColor) (*fi).V(j)->C() = InternalColor;
00315 if( (*fi).V(j)->C() == BorderColor) (*fi).V(j)->C() = MixColor;
00316 if( (*fi).V1(j)->C() == BaseColor) (*fi).V1(j)->C() = InternalColor;
00317 if( (*fi).V1(j)->C() == BorderColor) (*fi).V1(j)->C() = MixColor;
00318 }
00319 }
00320
00321 }
00322
00327 static void PerFaceRandomConnectedComponent( MeshType &m)
00328 {
00329 RequirePerFaceColor(m);
00330 RequireFFAdjacency(m);
00331
00332 std::vector< std::pair<int, typename MeshType::FacePointer> > CCV;
00333 int ScatterSize= std::min (100,tri::Clean<MeshType>::ConnectedComponents(m, CCV));
00334
00335 ConnectedComponentIterator<MeshType> ci;
00336 for(unsigned int i=0;i<CCV.size();++i)
00337 {
00338 Color4b BaseColor = Color4b::Scatter(ScatterSize, i%ScatterSize,.4f,.7f);
00339 std::vector<typename MeshType::FacePointer> FPV;
00340 for(ci.start(m,CCV[i].second);!ci.completed();++ci)
00341 (*ci)->C()=BaseColor;
00342 }
00343 }
00344
00349 static void PerFaceRandom(MeshType &m)
00350 {
00351 RequirePerFaceColor(m);
00352 FaceIterator fi;
00353 Color4b BaseColor = Color4b::Black;
00354 PerFaceConstant(m,BaseColor);
00355 int id_num=0;
00356 for(fi=m.face.begin();fi!=m.face.end();++fi)
00357 if(!(*fi).IsD())
00358 {
00359 id_num++;
00360 if((*fi).C() == BaseColor) (*fi).C() = Color4b::Scatter(50, id_num%50,.4f,.7f);
00361 for(int j=0;j<3;++j)
00362 if((*fi).IsF(j))
00363 {
00364 assert(!IsBorder((*fi),j));
00365 (*fi).FFp(j)->C()= (*fi).C();
00366 }
00367 }
00368 }
00369
00377 static void PerVertexPerlinNoise(MeshType& m, CoordType period, CoordType offset = CoordType(0, 0, 0), bool onSelected = false)
00378 {
00379 RequirePerVertexColor(m);
00380
00381 CoordType p[3];
00382
00383 for(VertexIterator vi = m.vert.begin(); vi!=m.vert.end(); ++vi)
00384 if(!(*vi).IsD())
00385 if ((!onSelected) || ((*vi).IsS()))
00386 {
00387
00388 p[0] = (vi->P()/period[0])+offset;
00389 p[1] = (vi->P()/period[1])+offset;
00390 p[2] = (vi->P()/period[2])+offset;
00391 (*vi).C() = Color4b( int(127+128.0*math::Perlin::Noise(p[0][0],p[0][1],p[0][2])),
00392 int(127+128.0*math::Perlin::Noise(p[1][0],p[1][1],p[1][2])),
00393 int(127+128.0*math::Perlin::Noise(p[2][0],p[2][1],p[2][2])),
00394 255 );
00395 }
00396
00397 }
00398
00402 static void PerVertexAddNoise(MeshType& m, int noiseBits, bool onSelected=false)
00403 {
00404 RequirePerVertexColor(m);
00405
00406 if(noiseBits>8) noiseBits = 8;
00407 if(noiseBits<1) return;
00408
00409 math::SubtractiveRingRNG randomGen = math::SubtractiveRingRNG(time(NULL));
00410 for(VertexIterator vi = m.vert.begin(); vi!=m.vert.end(); ++vi)
00411 if(!(*vi).IsD())
00412 if ((!onSelected) || ((*vi).IsS()))
00413 {
00414 (*vi).C()[0] = math::Clamp<int>((*vi).C()[0] + randomGen.generate(int(2*pow(2.0f,noiseBits))) - int(pow(2.0f,noiseBits)),0,255);
00415 (*vi).C()[1] = math::Clamp<int>((*vi).C()[1] + randomGen.generate(int(2*pow(2.0f,noiseBits))) - int(pow(2.0f,noiseBits)),0,255);
00416 (*vi).C()[2] = math::Clamp<int>((*vi).C()[2] + randomGen.generate(int(2*pow(2.0f,noiseBits))) - int(pow(2.0f,noiseBits)),0,255);
00417 }
00418
00419 }
00420
00421
00424 static int PerVertexThresholding(MeshType &m, float threshold, Color4b c1 = Color4<unsigned char>::Black, Color4b c2 = Color4<unsigned char>::White, const bool ProcessSelected=false)
00425 {
00426 RequirePerVertexColor(m);
00427
00428 int counter=0;
00429 VertexIterator vi;
00430 for(vi=m.vert.begin();vi!=m.vert.end();++vi)
00431 {
00432 if(!(*vi).IsD())
00433 {
00434 if(!ProcessSelected || (*vi).IsS())
00435 {
00436 float value = ComputeLightness((*vi).C());
00437
00438 if(value<=threshold) (*vi).C() = c1;
00439 else (*vi).C() = c2;
00440 ++counter;
00441 }
00442 }
00443 }
00444 return counter;
00445 }
00446
00447
00448 static float ComputeLightness(Color4b c)
00449 {
00450 float min_rgb = (float)math::Min(c[0],c[1],c[2]);
00451 float max_rgb = (float)math::Max(c[0],c[1],c[2]);
00452 return (max_rgb + min_rgb)/2;
00453 }
00454
00457 static int PerVertexBrightness(MeshType &m, float amount, const bool ProcessSelected=false)
00458 {
00459 RequirePerVertexColor(m);
00460
00461 int counter=0;
00462 VertexIterator vi;
00463 for(vi=m.vert.begin();vi!=m.vert.end();++vi)
00464 {
00465 if(!(*vi).IsD())
00466 {
00467 if(!ProcessSelected || (*vi).IsS())
00468 {
00469 (*vi).C() = Color4b(
00470 math::Clamp(int((*vi).C()[0]+amount),0,255),
00471 math::Clamp(int((*vi).C()[1]+amount),0,255),
00472 math::Clamp(int((*vi).C()[2]+amount),0,255),
00473 255);
00474 ++counter;
00475 }
00476 }
00477 }
00478 return counter;
00479 }
00480
00483 static int PerVertexContrast(MeshType &m, float factor, const bool ProcessSelected=false)
00484 {
00485 RequirePerVertexColor(m);
00486
00487 int counter=0;
00488 VertexIterator vi;
00489 for(vi=m.vert.begin();vi!=m.vert.end();++vi)
00490 {
00491 if(!(*vi).IsD())
00492 {
00493 if(!ProcessSelected || (*vi).IsS())
00494 {
00495 (*vi).C() = ColorMul((*vi).C(),factor);
00496 ++counter;
00497 }
00498 }
00499 }
00500 return counter;
00501 }
00502
00503
00504
00505 static Color4b ColorMul(Color4b c, float factor)
00506 {
00507 return Color4b( ValueMul(c[0], factor), ValueMul(c[1], factor), ValueMul(c[2], factor), 1);
00508 }
00509
00510 static int ValueMul(int value, float factor)
00511 {
00512 return math::Clamp<int>((int)((value - 128)*factor + 128), 0, 255);
00513 }
00514
00523 static int PerVertexBrightnessContrast(MeshType &m, float brightness, float contrast, const bool ProcessSelected=false)
00524 {
00525 RequirePerVertexColor(m);
00526
00527 int counter=0;
00528 VertexIterator vi;
00529 for(vi=m.vert.begin();vi!=m.vert.end();++vi)
00530 {
00531 if(!(*vi).IsD())
00532 {
00533 if(!ProcessSelected || (*vi).IsS())
00534 {
00535 (*vi).C() = ColorBrightnessContrast((*vi).C(),brightness,contrast);
00536 ++counter;
00537 }
00538 }
00539 }
00540 return counter;
00541 }
00542
00543 static Color4b ColorBrightnessContrast(Color4b c, float brightness, float contrast)
00544 {
00545 return Color4b( ValueBrightnessContrast(c[0], brightness, contrast),
00546 ValueBrightnessContrast(c[1], brightness, contrast),
00547 ValueBrightnessContrast(c[2], brightness, contrast), 1 );
00548 }
00549
00550 static int ValueBrightnessContrast(unsigned char ivalue, float brightness, float contrast)
00551 {
00552 float value = float(ivalue)/255.0f;
00553 if (brightness < 0.0) value = value * ( 1.0 + brightness);
00554 else value = value + ((1.0 - value) * brightness);
00555 value = (value - 0.5) * (tan ((contrast + 1) * M_PI/4) ) + 0.5;
00556 return math::Clamp<int>(255.0*value, 0, 255);
00557 }
00558
00563 static int PerVertexInvert(MeshType &m, const bool ProcessSelected=false)
00564 {
00565 RequirePerVertexColor(m);
00566
00567 int counter=0;
00568 for(VertexIterator vi=m.vert.begin(); vi!=m.vert.end(); ++vi)
00569 {
00570 if(!(*vi).IsD())
00571 {
00572 if(!ProcessSelected || (*vi).IsS())
00573 {
00574 Color4b &c=(*vi).C();
00575 c=Color4b( 255-c[0],255-c[1],255-c[2], 1);
00576 ++counter;
00577 }
00578 }
00579 }
00580 return counter;
00581 }
00582
00586 static int PerVertexGamma(MeshType &m, float gamma, const bool ProcessSelected=false)
00587 {
00588 RequirePerVertexColor(m);
00589
00590 int counter=0;
00591
00592 VertexIterator vi;
00593 for(vi=m.vert.begin();vi!=m.vert.end();++vi)
00594 {
00595 if(!(*vi).IsD())
00596 {
00597 if(!ProcessSelected || (*vi).IsS())
00598 {
00599 (*vi).C() = ColorPow((*vi).C(), 1/gamma);
00600 ++counter;
00601 }
00602 }
00603 }
00604 return counter;
00605 }
00606
00607
00608 static Color4b ColorPow(Color4b c, float exponent)
00609 {
00610 return vcg::Color4b(
00611 math::Clamp((int)( ValuePow(float(c[0])/255, exponent)*255), 0, 255),
00612 math::Clamp((int)( ValuePow(float(c[1])/255, exponent)*255), 0, 255),
00613 math::Clamp((int)( ValuePow(float(c[2])/255, exponent)*255), 0, 255),
00614 255);
00615 }
00616
00617 static float ValuePow(float value, float exponent)
00618 {
00619 return powf(value, exponent);
00620 }
00621
00622
00623 enum rgbChMask {ALL_CHANNELS = 7, RED_CHANNEL = 4, GREEN_CHANNEL = 2, BLUE_CHANNEL = 1, NO_CHANNELS = 0 };
00624
00633 static int PerVertexLevels(MeshType &m, float gamma, float in_min, float in_max, float out_min, float out_max, unsigned char rgbMask, const bool ProcessSelected=false)
00634 {
00635 RequirePerVertexColor(m);
00636
00637 int counter=0;
00638 VertexIterator vi;
00639 for(vi=m.vert.begin();vi!=m.vert.end();++vi)
00640 {
00641 if(!(*vi).IsD())
00642 {
00643 if(!ProcessSelected || (*vi).IsS())
00644 {
00645 (*vi).C() = ColorLevels((*vi).C(), gamma, in_min, in_max, out_min, out_max, rgbMask);
00646 ++counter;
00647 }
00648 }
00649 }
00650 return counter;
00651 }
00652
00653
00654 static Color4b ColorLevels(Color4b c, float gamma, float in_min, float in_max, float out_min, float out_max, unsigned char rgbMask)
00655 {
00656 unsigned char r = c[0], g = c[1], b = c[2];
00657 if(rgbMask & RED_CHANNEL) r = ValueLevels(c[0], gamma, in_min, in_max, out_min, out_max);
00658 if(rgbMask & GREEN_CHANNEL) g = ValueLevels(c[1], gamma, in_min, in_max, out_min, out_max);
00659 if(rgbMask & BLUE_CHANNEL) b = ValueLevels(c[2], gamma, in_min, in_max, out_min, out_max);
00660 return Color4b(r, g, b, 255);
00661 }
00662
00663
00664 static int ValueLevels(int value, float gamma, float in_min, float in_max, float out_min, float out_max)
00665 {
00666 float fvalue = value/255.0f;
00667
00668 fvalue = math::Clamp<float>(fvalue - in_min, 0.0f, 1.0f) / math::Clamp<float>(in_max - in_min, 1.0f/255.0f, 1.0f);
00669
00670 fvalue = powf(fvalue,1/gamma);
00671
00672 fvalue = fvalue * (out_max - out_min) + out_min;
00673
00674 return math::Clamp<int>((int)(fvalue * 255), 0, 255);
00675 }
00676
00682 static int PerVertexColourisation(MeshType &m, Color4b c, float intensity, const bool ProcessSelected=false)
00683 {
00684 RequirePerVertexColor(m);
00685
00686 int counter=0;
00687 VertexIterator vi;
00688 for(vi=m.vert.begin();vi!=m.vert.end();++vi)
00689 {
00690 if(!(*vi).IsD())
00691 {
00692 if(!ProcessSelected || (*vi).IsS())
00693 {
00694 (*vi).C() = ColorApplyDiff((*vi).C(), c, intensity);
00695 ++counter;
00696 }
00697 }
00698 }
00699 return counter;
00700 }
00701
00702
00703
00704
00705 static Color4b ColorApplyDiff(Color4b old_color, Color4b new_color, float intensity)
00706 {
00707 return Color4b( ValueApplyDiff(old_color[0], new_color[0], intensity),
00708 ValueApplyDiff(old_color[1], new_color[1], intensity),
00709 ValueApplyDiff(old_color[2], new_color[2], intensity), 255);
00710 }
00711
00712 static int ValueApplyDiff(int old_value, int new_value, float intensity)
00713 {
00714 return math::Clamp<int>((int)(old_value + intensity * (new_value - old_value)), 0, 255);
00715 }
00716
00717
00718 enum DesaturationMethods {M_LIGHTNESS = 0, M_LUMINOSITY = 1, M_AVERAGE = 2};
00719
00729 static int PerVertexDesaturation(MeshType &m, int method, const bool ProcessSelected=false)
00730 {
00731 RequirePerVertexColor(m);
00732
00733 int counter=0;
00734 VertexIterator vi;
00735 for(vi=m.vert.begin();vi!=m.vert.end();++vi)
00736 {
00737 if(!(*vi).IsD())
00738 {
00739 if(!ProcessSelected || (*vi).IsS())
00740 {
00741 (*vi).C() = ColorDesaturate((*vi).C(), method);
00742 ++counter;
00743 }
00744 }
00745 }
00746 return counter;
00747 }
00748
00749
00750 static Color4b ColorDesaturate(Color4b c, int method)
00751 {
00752 switch(method){
00753 case M_LIGHTNESS:{
00754 int val = (int)ComputeLightness(c);
00755 return Color4b( val, val, val, 255);
00756 }
00757 case M_AVERAGE:{
00758 int val = (int)ComputeAvgLightness(c);
00759 return Color4b( val, val, val, 255);
00760 }
00761 case M_LUMINOSITY:{
00762 int val = (int)ComputeLuminosity(c);
00763 return Color4b( val, val, val, 255);
00764 }
00765 default: assert(0);
00766 }
00767 }
00768
00769
00770 static float ComputeAvgLightness(Color4b c)
00771 {
00772 return float(c[0]+c[1]+c[2])/3.0f;
00773 }
00774
00775
00776 static float ComputeLuminosity(Color4b c)
00777 {
00778 return float(0.2126f*c[0]+0.7152f*c[1]+0.0722f*c[2]);
00779 }
00780
00786 static int PerVertexEqualize(MeshType &m, unsigned int rgbMask, const bool ProcessSelected=false)
00787 {
00788 RequirePerVertexColor(m);
00789
00790
00791 Histogramf Hl, Hr, Hg, Hb;
00792 Hl.Clear(); Hr.Clear(); Hg.Clear(); Hb.Clear();
00793 Hl.SetRange(0, 255, 255); Hr.SetRange(0, 255, 255); Hg.SetRange(0, 255, 255); Hb.SetRange(0, 255, 255);
00794
00795 int counter=0;
00796 VertexIterator vi;
00797
00798
00799 for(vi=m.vert.begin();vi!=m.vert.end();++vi)
00800 {
00801 if(!(*vi).IsD())
00802 {
00803 if(!ProcessSelected || (*vi).IsS())
00804 {
00805 float v = ComputeLightness((*vi).C())+0.5;
00806 Hl.Add(v); Hr.Add((float)(*vi).C()[0]); Hg.Add((float)(*vi).C()[1]); Hb.Add((float)(*vi).C()[2]);
00807 }
00808 }
00809 }
00810
00811
00812 int cdf_l[256], cdf_r[256], cdf_g[256], cdf_b[256];
00813 cdf_l[0] = Hl.BinCount(0); cdf_r[0] = Hr.BinCount(0); cdf_g[0] = Hg.BinCount(0); cdf_b[0] = Hb.BinCount(0);
00814 for(int i=1; i<256; i++){
00815 cdf_l[i] = Hl.BinCount(float(i)) + cdf_l[i-1];
00816 cdf_r[i] = Hr.BinCount(float(i)) + cdf_r[i-1];
00817 cdf_g[i] = Hg.BinCount(float(i)) + cdf_g[i-1];
00818 cdf_b[i] = Hb.BinCount(float(i)) + cdf_b[i-1];
00819 }
00820
00821
00822 for(vi=m.vert.begin();vi!=m.vert.end();++vi)
00823 {
00824 if(!(*vi).IsD())
00825 {
00826 if(!ProcessSelected || (*vi).IsS())
00827 {
00828 (*vi).C()=ColorEqualize((*vi).C(), cdf_l, cdf_r, cdf_g, cdf_b, rgbMask);
00829 ++counter;
00830 }
00831 }
00832 }
00833 return counter;
00834 }
00835
00836
00837 static Color4b ColorEqualize(Color4b c, int cdf_l[256], int cdf_r[256], int cdf_g[256], int cdf_b[256], unsigned int rgbMask)
00838 {
00839 unsigned char r = c[0], g = c[1], b = c[2];
00840 if(rgbMask == NO_CHANNELS)
00841 {
00842 int v = ValueEqualize(cdf_l[(int)(ComputeLightness(c)+0.5f)], cdf_l[0], cdf_l[255]);
00843 return Color4b(v, v, v, 255);
00844 }
00845 if(rgbMask & RED_CHANNEL) r = ValueEqualize(cdf_r[c[0]], cdf_r[0], cdf_r[255]);
00846 if(rgbMask & GREEN_CHANNEL) g = ValueEqualize(cdf_g[c[1]], cdf_g[0], cdf_g[255]);
00847 if(rgbMask & BLUE_CHANNEL) b = ValueEqualize(cdf_b[c[2]], cdf_b[0], cdf_b[255]);
00848 return Color4b(r, g, b, 255);
00849 }
00850
00851
00852 static int ValueEqualize(int cdfValue, int cdfMin, int cdfMax)
00853 {
00854 return int(float((cdfValue - cdfMin)/float(cdfMax - cdfMin)) * 255.0f);
00855 }
00856
00862 static int PerVertexWhiteBalance(MeshType &m, Color4b userColor, const bool ProcessSelected=false)
00863 {
00864 RequirePerVertexColor(m);
00865
00866 Color4b unbalancedWhite= userColor;
00867 int counter=0;
00868 VertexIterator vi;
00869
00870
00871 for(vi=m.vert.begin();vi!=m.vert.end();++vi)
00872 {
00873 if(!(*vi).IsD())
00874 {
00875 if(!ProcessSelected || (*vi).IsS())
00876 {
00877 (*vi).C()=ColorWhiteBalance((*vi).C(),unbalancedWhite);
00878 ++counter;
00879 }
00880 }
00881 }
00882 return counter;
00883 }
00884
00885
00886 static Color4b ColorWhiteBalance(Color4b c, Color4b unbalancedWhite)
00887 {
00888
00889 if(unbalancedWhite[0]==0) unbalancedWhite[0]=1;
00890 if(unbalancedWhite[1]==0) unbalancedWhite[1]=1;
00891 if(unbalancedWhite[2]==0) unbalancedWhite[2]=1;
00892
00893 return Color4b(
00894 math::Clamp<int>((int)(c[0]*(255.0f/unbalancedWhite[0])), 0, 255),
00895 math::Clamp<int>((int)(c[1]*(255.0f/unbalancedWhite[1])), 0, 255),
00896 math::Clamp<int>((int)(c[2]*(255.0f/unbalancedWhite[2])), 0, 255),
00897 255);
00898 }
00899
00900 };
00901
00902 }
00903 }
00904 #endif