00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "OSDLPalette.h"
00028
00029 #include "OSDLSurface.h"
00030 #include "OSDLFileTags.h"
00031
00032 #include "Ceylan.h"
00033
00034
00035
00036 #include <list>
00037
00038
00039 using std::string ;
00040
00041
00042 using namespace Ceylan::Log ;
00043 using namespace Ceylan::System ;
00044
00045
00046 using namespace OSDL::Video ;
00047 using namespace OSDL::Video::Pixels ;
00048
00049
00050
00051 #ifdef OSDL_USES_CONFIG_H
00052 #include <OSDLConfig.h>
00053 #endif // OSDL_USES_CONFIG_H
00054
00055
00056 #if OSDL_ARCH_NINTENDO_DS
00057 #include "OSDLConfigForNintendoDS.h"
00058 #endif // OSDL_ARCH_NINTENDO_DS
00059
00060
00061
00062
00063 #if OSDL_USES_SDL
00064
00065 #include "SDL.h"
00066
00067 const Ceylan::Flags Palette::Logical = SDL_LOGPAL ;
00068 const Ceylan::Flags Palette::Physical = SDL_PHYSPAL ;
00069
00070 #else // OSDL_USES_SDL
00071
00072
00073 const Ceylan::Flags Palette::Logical = 0x01 ;
00074 const Ceylan::Flags Palette::Physical = 0x02 ;
00075
00076 #endif // OSDL_USES_SDL
00077
00078
00079
00080
00081 PaletteException::PaletteException( const string & message ) :
00082 VideoException( "Palette exception: " + message )
00083 {
00084
00085 }
00086
00087
00088
00089 PaletteException::~PaletteException() throw()
00090 {
00091
00092 }
00093
00094
00095
00096
00097 Palette::Palette( ColorCount numberOfColors, ColorDefinition * colors,
00098 PixelFormat * format ) :
00099 _numberOfColors( 0 ),
00100 _colorDefs( 0 ),
00101 _pixelColors( 0 ),
00102 _converted( false ),
00103 _ownsColorDefinition( true ),
00104 _hasColorkey( false ),
00105 _colorKeyIndex( 0 )
00106 {
00107
00108 #if OSDL_USES_SDL
00109
00110
00111
00112 load( numberOfColors, colors ) ;
00113
00114 if ( format != 0 )
00115 updatePixelColorsFrom( * format ) ;
00116
00117 #else // OSDL_USES_SDL
00118
00119 throw PaletteException( "Palette constructor failed:"
00120 "no SDL support available" ) ;
00121
00122 #endif // OSDL_USES_SDL
00123
00124 }
00125
00126
00127
00128 Palette::Palette( const LowLevelPalette & palette ) :
00129 _numberOfColors( 0 ),
00130 _colorDefs( 0 ),
00131 _pixelColors( 0 ),
00132 _converted( false ),
00133 _ownsColorDefinition( false ),
00134 _hasColorkey( false ),
00135 _colorKeyIndex( 0 )
00136 {
00137
00138 #if OSDL_USES_SDL
00139
00140
00141
00142 load( palette.ncolors, palette.colors ) ;
00143
00144 #else // OSDL_USES_SDL
00145
00146 throw PaletteException( "Palette constructor failed:"
00147 "no SDL support available" ) ;
00148
00149 #endif // OSDL_USES_SDL
00150
00151 }
00152
00153
00154
00155 Palette::Palette( const string & paletteFilename ) :
00156 _numberOfColors( 0 ),
00157 _colorDefs( 0 ),
00158 _pixelColors( 0 ),
00159 _converted( false ),
00160 _ownsColorDefinition( true ),
00161 _hasColorkey( false ),
00162 _colorKeyIndex( 0 )
00163 {
00164
00165 try
00166 {
00167
00168 Size fileSize = File::GetSize( paletteFilename ) ;
00169
00170 Ceylan::Holder<File> paletteHolder( File::Open( paletteFilename ) ) ;
00171
00172
00173
00174 FileTag readTag = paletteHolder->readUint16() ;
00175 fileSize -= sizeof( PaletteTag ) ;
00176
00177 if ( readTag != PaletteTag )
00178 throw PaletteException(
00179 "Palette constructor: expected palette tag not found ("
00180 + Ceylan::toString( PaletteTag ) + "), read instead "
00181 + Ceylan::toString( readTag ) + ", which corresponds to: "
00182 + DescribeFileTag( readTag ) ) ;
00183
00184
00185 bool hasColorkey = ( paletteHolder->readUint8() != 0 ) ;
00186 fileSize-- ;
00187
00188 if ( hasColorkey )
00189 {
00190 setColorKeyIndex( paletteHolder->readUint16() ) ;
00191 fileSize -= 2 ;
00192 }
00193
00194
00195
00196 if ( fileSize % 3 != 0 )
00197 throw PaletteException( "Palette constructor from file failed: "
00198 "size of palette file '" + paletteFilename + "' is "
00199 + Ceylan::toString( fileSize )
00200 + " bytes, which is not a multiple of 3 bytes "
00201 "(24 bits per color)" ) ;
00202
00203
00204
00205 ColorCount colorCount = fileSize / 3 ;
00206
00207
00208
00209
00210
00211
00212
00213
00214 ColorDefinition * colorDefs = new ColorDefinition[ colorCount ] ;
00215
00216
00217 for ( ColorCount i = 0; i < colorCount; i++ )
00218 {
00219
00220 colorDefs[i].r = static_cast<ColorElement>(
00221 paletteHolder->readUint8() ) ;
00222
00223 colorDefs[i].g = static_cast<ColorElement>(
00224 paletteHolder->readUint8() ) ;
00225
00226 colorDefs[i].b = static_cast<ColorElement>(
00227 paletteHolder->readUint8() ) ;
00228
00229 colorDefs[i].unused = Pixels::AlphaOpaque ;
00230
00231 }
00232
00233 load( colorCount, colorDefs ) ;
00234
00235
00236 }
00237 catch( const Ceylan::Exception & e )
00238 {
00239
00240 throw PaletteException( "Palette constructor from file failed: "
00241 + e.toString() ) ;
00242
00243 }
00244
00245 }
00246
00247
00248
00249 Palette::~Palette() throw()
00250 {
00251
00252 if ( _ownsColorDefinition && _colorDefs != 0 )
00253 {
00254 delete [] _colorDefs ;
00255 }
00256
00257 invalidatePixelColors() ;
00258
00259 }
00260
00261
00262
00263 void Palette::load( ColorCount numberOfColors, ColorDefinition * colors )
00264 {
00265
00266
00267
00268
00269 _converted = false ;
00270
00271 if ( _colorDefs != 0 )
00272 delete [] _colorDefs ;
00273
00274
00275 if ( colors == 0 )
00276 {
00277
00278
00279 _colorDefs = new ColorDefinition[ numberOfColors ] ;
00280
00281 for ( ColorCount i=0; i < numberOfColors; i++ )
00282 {
00283
00284
00285 _colorDefs[i].r = 0 ;
00286 _colorDefs[i].g = 0 ;
00287 _colorDefs[i].b = 0 ;
00288 _colorDefs[i].unused = AlphaOpaque ;
00289
00290 }
00291
00292 }
00293 else
00294 {
00295
00296 _colorDefs = colors ;
00297
00298 }
00299
00300
00301 if ( numberOfColors != _numberOfColors )
00302 {
00303
00304 _numberOfColors = numberOfColors ;
00305
00306 invalidatePixelColors() ;
00307
00308 }
00309
00310 }
00311
00312
00313
00314 ColorCount Palette::getNumberOfColors() const
00315 {
00316
00317 return _numberOfColors ;
00318
00319 }
00320
00321
00322
00323 const Pixels::PixelColor & Palette::getPixelColorAt( ColorCount index ) const
00324 {
00325
00326 if ( index >= _numberOfColors )
00327 throw PaletteException(
00328 "Palette::getPixelColorAt: out of bounds: specified index ("
00329 + Ceylan::toString( index ) + ") greater or equal to upper index ("
00330 + Ceylan::toString( _numberOfColors ) + ")." ) ;
00331
00332 return _pixelColors[ index ] ;
00333
00334 }
00335
00336
00337
00338 Pixels::PixelColor * Palette::getPixelColors() const
00339 {
00340
00341 return _pixelColors ;
00342
00343 }
00344
00345
00346
00347 const Pixels::ColorDefinition & Palette::getColorDefinitionAt(
00348 ColorCount index ) const
00349 {
00350
00351 if ( index >= _numberOfColors )
00352 throw PaletteException(
00353 "Palette::getColorDefinitionAt: out of bounds: "
00354 "specified index ("
00355 + Ceylan::toString( index ) + ") greater or equal to upper index ("
00356 + Ceylan::toString( _numberOfColors ) + ")." ) ;
00357
00358 return _colorDefs[ index ] ;
00359
00360 }
00361
00362
00363
00364 void Palette::setColorDefinitionAt( ColorCount targetIndex,
00365 const ColorDefinition & newColorDefinition )
00366 {
00367
00368 if ( targetIndex >= _numberOfColors )
00369 throw PaletteException(
00370 "Palette::setColorDefinitionAt: out of bounds: "
00371 "specified index ("
00372 + Ceylan::toString( targetIndex )
00373 + ") greater or equal to upper index ("
00374 + Ceylan::toString( _numberOfColors ) + ")." ) ;
00375
00376 _colorDefs[ targetIndex ] = newColorDefinition ;
00377
00378 }
00379
00380
00381
00382 void Palette::setColorDefinitionAt( ColorCount targetIndex,
00383 ColorElement red, ColorElement green, ColorElement blue,
00384 ColorElement alpha )
00385 {
00386
00387 if ( targetIndex >= _numberOfColors )
00388 throw PaletteException(
00389 "Palette::setColorDefinitionAt: out of bounds: "
00390 "specified index ("
00391 + Ceylan::toString( targetIndex )
00392 + ") greater or equal to upper index ("
00393 + Ceylan::toString( _numberOfColors ) + ")." ) ;
00394
00395 _colorDefs[ targetIndex ].r = red ;
00396 _colorDefs[ targetIndex ].g = green ;
00397 _colorDefs[ targetIndex ].b = blue ;
00398 _colorDefs[ targetIndex ].unused = alpha ;
00399
00400 }
00401
00402
00403
00404 Pixels::ColorDefinition * Palette::getColorDefinitions() const
00405 {
00406
00407 return _colorDefs ;
00408
00409 }
00410
00411
00412
00413 bool Palette::hasColorKey() const
00414 {
00415
00416 return _hasColorkey ;
00417
00418 }
00419
00420
00421
00422 ColorCount Palette::getColorKeyIndex() const
00423 {
00424
00425 if ( ! _hasColorkey )
00426 throw PaletteException( "Palette::getColorKeyIndex failed: "
00427 "no available colorkey" ) ;
00428
00429 return _colorKeyIndex ;
00430
00431 }
00432
00433
00434
00435 void Palette::setColorKeyIndex( ColorCount colorkeyIndex )
00436 {
00437
00438
00439
00440 _hasColorkey = true ;
00441
00442 _colorKeyIndex = colorkeyIndex ;
00443
00444 }
00445
00446
00447
00448 void Palette::updatePixelColorsFrom( const PixelFormat & format )
00449 {
00450
00451 if ( _numberOfColors == 0 )
00452 {
00453
00454 LogPlug::warning(
00455 "Palette::updatePixelColorsFrom: no color available." ) ;
00456
00457 _converted = true ;
00458 return ;
00459
00460 }
00461
00462 if ( _pixelColors == 0 )
00463 {
00464 _pixelColors = new PixelColor[ _numberOfColors ] ;
00465 }
00466
00467
00468 for ( ColorCount c = 0; c < _numberOfColors; c++ )
00469 {
00470 _pixelColors[c] = convertColorDefinitionToPixelColor(
00471 * const_cast<PixelFormat*>( &format ), _colorDefs[c] ) ;
00472 }
00473
00474 _converted = true ;
00475
00476 }
00477
00478
00479
00480 void Palette::quantize( Pixels::ColorElement quantizeMaxCoordinate,
00481 bool scaleUp )
00482 {
00483
00484 for ( ColorCount index = 0; index < _numberOfColors; index++ )
00485 {
00486
00487 _colorDefs[index].r = QuantizeComponent( _colorDefs[index].r,
00488 quantizeMaxCoordinate ) ;
00489
00490 _colorDefs[index].g = QuantizeComponent( _colorDefs[index].g,
00491 quantizeMaxCoordinate ) ;
00492
00493 _colorDefs[index].b = QuantizeComponent( _colorDefs[index].b,
00494 quantizeMaxCoordinate ) ;
00495
00496
00497
00498
00499 if ( scaleUp )
00500 {
00501
00502 _colorDefs[index].r = static_cast<ColorElement>(
00503 Ceylan::Maths::Round(
00504 _colorDefs[index].r * 255.0f / quantizeMaxCoordinate ) ) ;
00505
00506 _colorDefs[index].g = static_cast<ColorElement>(
00507 Ceylan::Maths::Round(
00508 _colorDefs[index].g * 255.0f / quantizeMaxCoordinate ) ) ;
00509
00510 _colorDefs[index].b = static_cast<ColorElement>(
00511 Ceylan::Maths::Round(
00512 _colorDefs[index].b * 255.0f / quantizeMaxCoordinate ) ) ;
00513
00514
00515
00516 }
00517
00518 }
00519
00520 invalidatePixelColors() ;
00521
00522 }
00523
00524
00525
00526 void Palette::correctGamma( GammaFactor gamma )
00527 {
00528
00529 for ( ColorCount index = 0; index < _numberOfColors; index++ )
00530 {
00531
00532 if ( _hasColorkey && ( index == _colorKeyIndex ) )
00533 continue ;
00534
00535 _colorDefs[index].r = CorrectGammaComponent( _colorDefs[index].r,
00536 gamma ) ;
00537
00538 _colorDefs[index].g = CorrectGammaComponent( _colorDefs[index].g,
00539 gamma ) ;
00540
00541 _colorDefs[index].b = CorrectGammaComponent( _colorDefs[index].b,
00542 gamma ) ;
00543
00544
00545
00546 }
00547
00548 invalidatePixelColors() ;
00549
00550 }
00551
00552
00553
00554 ColorCount Palette::getClosestColorIndexTo( const ColorDefinition & color )
00555 const
00556 {
00557
00558 if ( _numberOfColors == 0 )
00559 throw PaletteException( "Palette::getClosestColorIndexTo failed: "
00560 "no color in palette." ) ;
00561
00562 bool initialized = false ;
00563
00564 ColorCount bestIndex ;
00565 ColorDistance smallestDistance, currentDistance ;
00566
00567 for ( ColorCount i=0; i < _numberOfColors; i++ )
00568 {
00569
00570 if ( _hasColorkey && ( i == _colorKeyIndex ) )
00571 continue ;
00572
00573 currentDistance = GetDistance( color, _colorDefs[i] ) ;
00574
00575 if ( initialized )
00576 {
00577
00578 if ( currentDistance < smallestDistance )
00579 {
00580
00581 smallestDistance = currentDistance ;
00582 bestIndex = i ;
00583
00584 }
00585
00586 }
00587 else
00588 {
00589
00590 smallestDistance = currentDistance ;
00591 bestIndex = i ;
00592 initialized = true ;
00593
00594 }
00595
00596
00597 }
00598
00599 return bestIndex ;
00600
00601 }
00602
00603
00604
00605 bool Palette::draw( Surface & targetSurface,
00606 const ColorDefinition & backgroundColor )
00607 {
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617 updatePixelColorsFrom( targetSurface.getPixelFormat() ) ;
00618
00619 targetSurface.lock() ;
00620
00621 targetSurface.fill( backgroundColor ) ;
00622
00623 for ( Length i = 0;
00624 i < targetSurface.getHeight() && i < _numberOfColors; i++ )
00625 {
00626 targetSurface.drawHorizontalLine( 0, targetSurface.getWidth(),
00627 i, getPixelColorAt( i ) ) ;
00628 }
00629
00630 targetSurface.unlock() ;
00631
00632 return ( targetSurface.getHeight() >= _numberOfColors ) ;
00633
00634 }
00635
00636
00637
00638 bool Palette::hasDuplicates( bool useAlpha ) const
00639 {
00640
00641 if ( _numberOfColors == 0 )
00642 return false ;
00643
00644 for ( ColorCount index = 0; index < _numberOfColors-1; index++ )
00645 {
00646
00647 if ( _hasColorkey && ( index == _colorKeyIndex ) )
00648 continue ;
00649
00650 for ( ColorCount checkIndex = index+1; checkIndex < _numberOfColors;
00651 checkIndex++ )
00652 if ( Pixels::areEqual( _colorDefs[index], _colorDefs[checkIndex],
00653 useAlpha ) )
00654 {
00655
00656 if ( _hasColorkey && ( checkIndex == _colorKeyIndex ) )
00657 continue ;
00658
00659 LogPlug::debug( "Palette::hasDuplicates: "
00660 "duplicate detected at index #" + Ceylan::toString( index )
00661 + " and index #" + Ceylan::toString( checkIndex )
00662 + " for color definition "
00663 + Pixels::toString( _colorDefs[index] ) + "." ) ;
00664
00665 return true ;
00666
00667 }
00668
00669 }
00670
00671 return false ;
00672
00673 }
00674
00675
00676
00677 void Palette::save( const std::string & filename, bool encoded ) const
00678 {
00679
00680
00681
00682 try
00683 {
00684
00685 Ceylan::Holder<File> paletteHolder( File::Create( filename ) ) ;
00686
00687 if ( ! encoded )
00688 {
00689
00690
00691 paletteHolder->writeUint16( PaletteTag ) ;
00692
00693 if ( hasColorKey() )
00694 {
00695
00696 paletteHolder->writeUint8( 1 ) ;
00697 paletteHolder->writeUint16( getColorKeyIndex() ) ;
00698
00699 }
00700 else
00701 {
00702
00703 paletteHolder->writeUint8( 0 ) ;
00704
00705 }
00706
00707
00708
00709 }
00710
00711
00712 for ( ColorCount index = 0; index < _numberOfColors; index++ )
00713 {
00714
00715 if ( encoded )
00716 {
00717
00718
00719
00720
00721
00722
00723 Ceylan::Uint16 colorDefinition = 32768
00724 | QuantizeComponent( _colorDefs[index].r )
00725 | ( ( QuantizeComponent( _colorDefs[index].g ) ) << 5 )
00726 | ( ( QuantizeComponent( _colorDefs[index].b ) ) << 10 ) ;
00727
00728
00729 paletteHolder->writeUint8( ( colorDefinition & 0xff00 ) >> 8 ) ;
00730 paletteHolder->writeUint8( colorDefinition & 0x00ff ) ;
00731
00732 }
00733 else
00734 {
00735
00736
00737 paletteHolder->writeUint8( _colorDefs[index].r ) ;
00738 paletteHolder->writeUint8( _colorDefs[index].g ) ;
00739 paletteHolder->writeUint8( _colorDefs[index].b ) ;
00740
00741
00742 }
00743 }
00744
00745
00746
00747 }
00748 catch( const Ceylan::Exception & e )
00749 {
00750
00751 throw PaletteException( "Palette::save failed: " + e.toString() ) ;
00752
00753 }
00754
00755 }
00756
00757
00758
00759 const string Palette::toString( Ceylan::VerbosityLevels level ) const
00760 {
00761
00762 if ( _numberOfColors == 0 )
00763 return "Palette has no color defined" ;
00764
00765 if ( _colorDefs == 0 )
00766 {
00767
00768 LogPlug::error( "Palette::toString: palette should have "
00769 + Ceylan::toString( _numberOfColors ) + " color definitions, "
00770 "but no definition is registered (null pointer)." ) ;
00771
00772 return "Palette has no color defined and is in inconsistent state" ;
00773
00774 }
00775
00776 string result = "Palette has " + Ceylan::toString( _numberOfColors )
00777 + " color definitions, " ;
00778
00779 if ( _pixelColors == 0 )
00780 result += "they are not converted to actual pixel colors" ;
00781 else
00782 result += "they are already converted to actual pixel colors" ;
00783
00784 if ( _hasColorkey )
00785 result += ". Palette has a colorkey, corresponding to color index #"
00786 + Ceylan::toString( _colorKeyIndex ) ;
00787 else
00788 result += ". Palette has no colorkey" ;
00789
00790 if ( level == Ceylan::low )
00791 return result ;
00792
00793
00794 result += ". Listing registered color definitions:" ;
00795
00796 std::list<string> l ;
00797
00798 for ( ColorCount index = 0; index < _numberOfColors; index++ )
00799 l.push_back( "Color #" + Ceylan::toString( index ) + ": "
00800 + Pixels::toString( _colorDefs[index] ) ) ;
00801
00802
00803 return result + Ceylan::formatStringList( l ) ;
00804
00805 }
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816 Palette & Palette::CreateGreyScalePalette( ColorCount numberOfColors )
00817 {
00818
00819 return CreateGradationPalette( Pixels::Black, Pixels::White,
00820 numberOfColors ) ;
00821
00822 }
00823
00824
00825
00826 Palette & Palette::CreateGradationPalette( const ColorDefinition & colorStart,
00827 const ColorDefinition & colorEnd, ColorCount numberOfColors )
00828 {
00829
00830 ColorDefinition * colorBuffer = new ColorDefinition[ numberOfColors ] ;
00831
00832 if ( colorBuffer == 0 )
00833 Ceylan::emergencyShutdown(
00834 "Palette::CreateGradationPalette: not enough memory." ) ;
00835
00836 #if OSDL_DEBUG_PALETTE
00837 LogPlug::debug( "Gradation ranging from "
00838 + Pixels::toString( colorStart ) + " to "
00839 + Pixels::toString( colorEnd ) + "." ) ;
00840 #endif // OSDL_DEBUG_PALETTE
00841
00842 Ceylan::Float32 redIncrement = (
00843 static_cast<Ceylan::Float32>( colorEnd.r ) - colorStart.r )
00844 / numberOfColors ;
00845
00846 Ceylan::Float32 greenIncrement = (
00847 static_cast<Ceylan::Float32>( colorEnd.g ) - colorStart.g )
00848 / numberOfColors ;
00849
00850 Ceylan::Float32 blueIncrement = (
00851 static_cast<Ceylan::Float32>( colorEnd.b ) - colorStart.b )
00852 / numberOfColors ;
00853
00854 Ceylan::Float32 alphaIncrement = (
00855 static_cast<Ceylan::Float32>( colorEnd.unused ) - colorStart.unused )
00856 / numberOfColors ;
00857
00858 for ( ColorCount c = 0; c < numberOfColors; c++ )
00859 {
00860
00861
00862
00863
00864
00865
00866
00867 colorBuffer[ c ].r = static_cast<ColorElement>(
00868 Ceylan::Maths::Ceil( colorStart.r + redIncrement * c ) ) ;
00869
00870 colorBuffer[ c ].g = static_cast<ColorElement>(
00871 Ceylan::Maths::Ceil( colorStart.g + greenIncrement * c ) ) ;
00872
00873 colorBuffer[ c ].b = static_cast<ColorElement>(
00874 Ceylan::Maths::Ceil( colorStart.b + blueIncrement * c ) ) ;
00875
00876 colorBuffer[ c ].unused = static_cast<ColorElement>(
00877 Ceylan::Maths::Ceil( colorStart.unused + alphaIncrement * c ) ) ;
00878
00879 }
00880
00881 return * new Palette( numberOfColors, colorBuffer ) ;
00882
00883 }
00884
00885
00886
00887 Palette & Palette::CreateMasterPalette( bool addColorkey )
00888 {
00889
00890 ColorCount colorCount = 255 ;
00891
00892 if ( addColorkey )
00893 colorCount++ ;
00894
00895 Palette & palette = * new Palette( colorCount ) ;
00896
00897
00898 colorCount = 0 ;
00899
00900 if ( addColorkey )
00901 {
00902
00903
00904 const ColorCount colorKeyIndex = 0 ;
00905
00906 palette.setColorDefinitionAt( colorKeyIndex, Pixels::DefaultColorkey ) ;
00907 palette.setColorKeyIndex( colorKeyIndex ) ;
00908 colorCount++ ;
00909
00910 }
00911
00912
00913
00914
00915
00916
00917
00918
00919 const Ceylan::Uint8 redRange = 6 ;
00920 const Ceylan::Uint8 greenRange = 8 ;
00921 const Ceylan::Uint8 blueRange = 5 ;
00922
00923
00924 ColorDefinition currentDef ;
00925
00926 currentDef.unused = Pixels::AlphaOpaque ;
00927
00928 for ( ColorCount redIndex = 0; redIndex < redRange; redIndex++ )
00929 for ( ColorCount greenIndex = 0; greenIndex < greenRange;
00930 greenIndex++ )
00931 for ( ColorCount blueIndex = 0; blueIndex < blueRange;
00932 blueIndex++ )
00933 {
00934
00935 currentDef.r = static_cast<ColorElement>(
00936 Ceylan::Maths::Round(
00937 255.0f * redIndex / (redRange-1) ) ) ;
00938
00939 currentDef.g = static_cast<ColorElement>(
00940 Ceylan::Maths::Round(
00941 255.0f * greenIndex / (greenRange-1) ) ) ;
00942
00943 currentDef.b = static_cast<ColorElement>(
00944 Ceylan::Maths::Round(
00945 255.0f * blueIndex / (blueRange-1) ) ) ;
00946
00947 palette.setColorDefinitionAt( colorCount, currentDef ) ;
00948
00949 colorCount++ ;
00950
00951 }
00952
00953
00954
00955 const ColorCount greyRange = 8 ;
00956
00957 for ( ColorCount greyIndex = 0; greyIndex < greyRange; greyIndex++ )
00958 {
00959
00960
00961 ColorElement greyComponent = static_cast<ColorElement>(
00962 Ceylan::Maths::Round( 255.0f *(greyIndex+1) / (greyRange+1) ) ) ;
00963
00964 currentDef.r = greyComponent ;
00965 currentDef.g = greyComponent ;
00966 currentDef.b = greyComponent ;
00967
00968 palette.setColorDefinitionAt( colorCount, currentDef ) ;
00969
00970 colorCount++ ;
00971
00972 }
00973
00974
00975
00976
00977
00978
00979 palette.setColorDefinitionAt( colorCount++, 6, 177, 220 ) ;
00980 palette.setColorDefinitionAt( colorCount++, 4, 147, 183 ) ;
00981 palette.setColorDefinitionAt( colorCount++, 28, 95, 139 ) ;
00982
00983
00984 palette.setColorDefinitionAt( colorCount++, 70, 59, 42 ) ;
00985
00986
00987 palette.setColorDefinitionAt( colorCount++, 238, 190, 141 ) ;
00988 palette.setColorDefinitionAt( colorCount++, 250, 205, 155 ) ;
00989
00990
00991 palette.setColorDefinitionAt( colorCount++, 255, 255, 111 ) ;
00992
00993
00994
00995 return palette ;
00996
00997 }
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007 void Palette::invalidatePixelColors()
01008 {
01009
01010 if ( _pixelColors != 0 )
01011 {
01012
01013 delete [] _pixelColors ;
01014 _pixelColors = 0 ;
01015
01016 }
01017
01018
01019
01020 }
01021
01022
01023
01024
01025
01026
01027
01028
01029
01030 Pixels::ColorElement Palette::QuantizeComponent( ColorElement component,
01031 Pixels::ColorElement newMaxCoordinate )
01032 {
01033
01034 return static_cast<ColorElement>( Ceylan::Maths::Round(
01035 component / 255.0f * newMaxCoordinate ) ) ;
01036
01037 }
01038
01039
01040
01041 Pixels::ColorElement Palette::CorrectGammaComponent(
01042 ColorElement component, GammaFactor gamma )
01043 {
01044
01045
01046 return static_cast<ColorElement>( Ceylan::Maths::Round(
01047 Ceylan::Maths::Pow( component/255.0f, 1/gamma ) * 255.0f ) ) ;
01048
01049 }
01050
01051
01052
01053 ColorDistance Palette::GetDistance(
01054 const Pixels::ColorDefinition & firstColor,
01055 const Pixels::ColorDefinition & secondColor )
01056 {
01057
01058
01059
01060
01061 ColorDistance rmean = ( firstColor.r + secondColor.r ) / 2 ;
01062
01063 ColorDistance rs = ( firstColor.r - secondColor.r ) *
01064 ( firstColor.r - secondColor.r ) ;
01065
01066 ColorDistance gs = ( firstColor.g - secondColor.g ) *
01067 ( firstColor.g - secondColor.g ) ;
01068
01069 ColorDistance bs = ( firstColor.b - secondColor.b ) *
01070 ( firstColor.b - secondColor.b ) ;
01071
01072 return ( ((512+rmean)*rs)>>8 ) + 4*gs + ( ((767-rmean)*bs)>>8 ) ;
01073
01074 }
01075