GRenderOptPalette Class Reference

A GDraw render region that generates an opimised palette for the output bitmap. More...

#include <grndbmp.h>

Inheritance diagram for GRenderOptPalette:

GRenderBitmap GRenderDIB GRenderRegion RenderRegion ListItem CCObject SimpleCCObject List of all members.

Public Member Functions

 GRenderOptPalette (DocRect ClipRegion, Matrix ConvertMatrix, FIXED16 ViewScale, UINT32 SrcDepth, double dpi, BOOL Use8bpp)
 GRenderOptPalette constructor.
 ~GRenderOptPalette ()
 GRenderOptPalette destructor.
virtual BOOL GetNextBand ()
 Passes this band to Gavin's palette optimisation routine, before we move onto the next band.
LPLOGPALETTE GetOptimisedPalette (UINT32 PaletteSize, UINT32 NumColours, UINT32 ReservedColours=0, BOOL SnapToBrowserPalette=FALSE)
 Generates an optimised palette from the Statistics generated from each band rendered so far.

Static Public Attributes

static BOOL DoTwoColourRoundingToPrimary = TRUE
static BOOL DoGDrawConversion = TRUE
static BOOL UseOldPalette = TRUE

Protected Attributes

void * Stats
BOOL UseSpecial8bpp
BOOL m_bTooManyColours
LPLOGPALETTE m_pExactPalette

Detailed Description

A GDraw render region that generates an opimised palette for the output bitmap.

Author:
Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
Date:
29/5/96

Definition at line 232 of file grndbmp.h.


Constructor & Destructor Documentation

GRenderOptPalette::GRenderOptPalette DocRect  ClipRegion,
Matrix  ConvertMatrix,
FIXED16  ViewScale,
UINT32  Depth,
double  dpi,
BOOL  Use8bpp
 

GRenderOptPalette constructor.

Author:
Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
Date:
29/5/96
Parameters:
- [INPUTS]
- [OUTPUTS]
Returns:
-

Errors: -

See also:
GRenderBitmap::GRenderBitmap

Definition at line 1523 of file grndbmp.cpp.

01524     : GRenderBitmap( ClipRegion, ConvertMatrix, ViewScale, Depth, dpi)
01525 {
01526     ERROR3IF(Depth != 32, "Bad Depth for GRenderOptPalette, must be 32bpp");
01527 
01528     UseSpecial8bpp = Use8bpp;
01529 
01530     m_pExactPalette = NULL;
01531 
01532     if (Depth == 32)
01533     {
01534         if (UseSpecial8bpp)
01535         {
01536             Stats = CCMalloc(DIBUtil::GetOptimal8bppPaletteWorkspaceSize() * 4);
01537             if (Stats)
01538                 DIBUtil::Optimal8bppPaletteInitialise((INT32*)Stats);
01539         }
01540         else
01541         {
01542             Stats = CCMalloc(DIBUtil::GetOptimalPaletteWorkspaceSize());
01543             if (Stats)
01544                 DIBUtil::OptimalPaletteInitialise(Stats);
01545 
01546         }
01547         if( !UseOldPalette )
01548         {
01549             const size_t TotalPal = sizeof(LOGPALETTE) + ( sizeof(PALETTEENTRY) * 256 );
01550             m_pExactPalette = (LPLOGPALETTE)CCMalloc( TotalPal );
01551             if( m_pExactPalette )
01552                 DIBUtil::ExactPaletteInitialise( m_pExactPalette );
01553         }
01554     }
01555 
01556     m_bTooManyColours = FALSE;
01557 
01558     //  Re-initialise
01559     DoGDrawConversion = TRUE;
01560 }

GRenderOptPalette::~GRenderOptPalette  ) 
 

GRenderOptPalette destructor.

Author:
Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
Date:
29/5/96
Parameters:
- [INPUTS]
- [OUTPUTS]
Returns:
-

Errors: -

Definition at line 1576 of file grndbmp.cpp.

01577 {
01578     if (Stats)
01579         CCFree(Stats);
01580     // GAT
01581     if (m_pExactPalette)
01582         CCFree(m_pExactPalette) ;
01583 }


Member Function Documentation

BOOL GRenderOptPalette::GetNextBand  )  [virtual]
 

Passes this band to Gavin's palette optimisation routine, before we move onto the next band.

Author:
Will_Cowling (Xara Group Ltd) <camelotdev@xara.com>
Date:
29/5/96
Parameters:
- [INPUTS]
- [OUTPUTS]
Returns:
-

Errors: -

Reimplemented from GRenderBitmap.

Definition at line 1600 of file grndbmp.cpp.

01601 {
01602     // Before we move onto the next band, we'll pass the current strip to Gavin's
01603     // palette optimising code
01604     if (Stats)
01605     {
01606         INT32 Width = pBitmapInfo->bmiHeader.biWidth;
01607         INT32 Height = pBitmapInfo->bmiHeader.biHeight;
01608 
01609         INT32 BmpSize = Width * Height;
01610 
01611         //  Calculate the number of colours used by this strip of the bitmap.
01612         //  But only if we have not gone over 256 colours yet
01613         // GAT
01614         if( !m_bTooManyColours && !UseOldPalette )
01615         {
01616             BOOL bResult = DIBUtil::CalculateNumberOfColoursInBitmap( m_pExactPalette, ( RGBQUAD* )pBits, BmpSize );
01617             if( !bResult )
01618             {
01619                 m_bTooManyColours = TRUE;
01620                 DoGDrawConversion = FALSE;
01621             }
01622         }
01623 
01624         BOOL ok;
01625         if (UseSpecial8bpp)
01626             ok = DIBUtil::GenOptimal8bppPaletteStats( (INT32*)Stats, (RGBQUAD*)pBits, BmpSize );
01627         else
01628             ok = DIBUtil::GenOptimalPaletteStats( Stats, (RGBQUAD*)pBits, BmpSize );
01629 
01630         ERROR3IF(!ok, "GenOptimalPaletteStats failed");
01631     }
01632 
01633     return GRenderBitmap::GetNextBand();                                        
01634 }

LPLOGPALETTE GRenderOptPalette::GetOptimisedPalette UINT32  PaletteSize,
UINT32  NumColours,
UINT32  ReservedColours = 0,
BOOL  SnapToBrowserPalette = FALSE
 

Generates an optimised palette from the Statistics generated from each band rendered so far.

Author:
Will_Cowling (Xara Group Ltd) <camelotdev@xara.com> (modified by MarkN)
Date:
29/5/96
Parameters:
PaletteSize = Max number of entries that the palette can hold (should be 2, 16 or 256) [INPUTS] NumColours = Number of colours to put in the palette ReservedColours = , number of colours to reserve (eg. for transparency) SnapToBrowserPalette = TRUE if palette should be snapped to the browser palett
- [OUTPUTS]
Returns:
A pointer to the optimised palette, or NULL if failed
The reserved colours will appear as follows ... 1bpp, at end of the palette, 4bpp, at the start of the palette, 8bpp, at the 11 entry in the palette (10 windows colours are always at the start).

WEBSTER Changes (markn 16/1/97): This function has been modified so that you can specify the number colours you want in the palette

WEBSTER v2 changes (markn 22/7/97)

Returns:
Errors: -

Definition at line 1666 of file grndbmp.cpp.

01667 {
01668     ERROR3IF(!(PaletteSize==2 || PaletteSize==16 || PaletteSize==256), "Bad palette size passed to GRenderOptPalette::GetOptimisedPalette");
01669     ERROR3IF(ReservedColours > PaletteSize, "Too many colours reserved in GRenderOptPalette::GetOptimisedPalette");
01670 
01671     LPLOGPALETTE pPalette = NULL;
01672 
01673     if (Stats)
01674     {
01675         const size_t TotalPal = sizeof(LOGPALETTE) + ( sizeof(PALETTEENTRY) * PaletteSize );
01676         pPalette = (LPLOGPALETTE)CCMalloc( TotalPal );
01677         if (pPalette)
01678         {
01679             // Initialise the palette with zeros
01680             memset(pPalette, 0, TotalPal);
01681 
01682             pPalette->palVersion    = 0x300;
01683             pPalette->palNumEntries = PaletteSize;
01684 
01685             if (NumColours > PaletteSize)
01686                 NumColours = PaletteSize;
01687 
01688             if (ReservedColours < NumColours)
01689             {
01690                 BOOL ok = TRUE;
01691                 // GAT
01692                 //  If the bitmap has less than 256 colours, then we want to bypass the 
01693                 //  optimisation code, and just use the exact palette.
01694 PORTNOTE("BmpPrevDlg", "Rampant use of BmapPrevDlg removed (please don't re-instate directly - the value should be a param or member of this class)")
01695 #ifndef EXCLUDE_FROM_XARALX
01696                 if( !m_bTooManyColours && m_pExactPalette && !UseOldPalette 
01697                     && m_pExactPalette->palNumEntries < BmapPrevDlg::m_NumOfColoursUserAskedFor ) // and we want this many colours
01698 #else
01699                 if( !m_bTooManyColours && m_pExactPalette && !UseOldPalette ) // and we want this many colours
01700 #endif
01701                 {
01702                     //  Transfer the exact palette into the variable we want, and then clear up the memory.
01703                     INT32 blackEntry = 10;
01704                     pPalette->palNumEntries = m_pExactPalette->palNumEntries;
01705                     INT32 i = 0;
01706                     for( i = 0; i < m_pExactPalette->palNumEntries; i++ )
01707                     {
01708                         pPalette->palPalEntry[i].peRed   = m_pExactPalette->palPalEntry[i].peRed;
01709                         pPalette->palPalEntry[i].peGreen = m_pExactPalette->palPalEntry[i].peGreen;
01710                         pPalette->palPalEntry[i].peBlue  = m_pExactPalette->palPalEntry[i].peBlue;
01711 
01712                         if (pPalette->palPalEntry[i].peRed == 255 &&
01713                             pPalette->palPalEntry[i].peGreen == 255 &&
01714                             pPalette->palPalEntry[i].peBlue == 255 )
01715                             blackEntry = i;
01716                     }
01717                     if (blackEntry != 10 && ReservedColours == 1)
01718                     {
01719                         // swap the black entry for number 10 as this is the transparent entry for some odd reason
01720                         pPalette->palPalEntry[blackEntry].peRed = pPalette->palPalEntry[10].peRed;
01721                         pPalette->palPalEntry[blackEntry].peGreen = pPalette->palPalEntry[10].peGreen;
01722                         pPalette->palPalEntry[blackEntry].peBlue = pPalette->palPalEntry[10].peBlue;
01723 
01724                         pPalette->palPalEntry[10].peRed = 255;
01725                         pPalette->palPalEntry[10].peGreen = 255;
01726                         pPalette->palPalEntry[10].peBlue = 255;
01727                     }
01728                     for( ; i<0x100 ; i++ )
01729                     {
01730                         pPalette->palPalEntry[i].peRed   =
01731                         pPalette->palPalEntry[i].peGreen =
01732                         pPalette->palPalEntry[i].peBlue  = 0 ;
01733                     }
01734 
01735 //                  BmapPrevDlg::m_bNeedPaletteUpdated = TRUE;
01736 PORTNOTE("BmpPrevDlg", "Use of BmapPrevDlg removed")
01737 #ifndef EXCLUDE_FROM_XARALX
01738                     BmapPrevDlg::m_bUseExistingPalette = FALSE;
01739 #endif
01740                 }
01741                 else if (UseSpecial8bpp)
01742                 {
01743                     if (PaletteSize != 256)
01744                     {
01745                         ERROR3("Palette size is wrong for an 8bpp bitmap");
01746                         CCFree( pPalette );
01747                         return NULL;
01748                     }
01749 
01750                     // There has to be at least 20 colours in the palette to accomodate the system colours
01751                     if (NumColours < 20)
01752                         NumColours = 20;
01753 
01754                     // Gavin adds 16 system colours, then later we remove these and add the full set of 20 system colours
01755                     // Therefore, get Gavin to generate 4 fewer colours so we end up with the correct number of
01756                     // colours in the palette.
01757                     NumColours -= 4;
01758 
01759                     // We can only generate a maximum of 252 colours (i.e. (256-20)+16 = 252)
01760                     if (NumColours > 252)
01761                         NumColours = 252;
01762 
01763                     // Leave room for the reserved colours
01764                     NumColours -= ReservedColours;
01765 
01766                     ok = DIBUtil::GenOptimal8bppPalette((INT32*) Stats, pPalette, NumColours);
01767                 }
01768                 else
01769                 {
01770                     // Leave room for the reserved colours
01771                     NumColours -= ReservedColours;
01772 
01773                     ok = DIBUtil::GenOptimalPalette( Stats, pPalette, (NumColours==1) ? 2 : NumColours );
01774                 }
01775                 // GAT
01776                 if( m_pExactPalette )
01777                 {
01778                     //  Get some memory back.
01779                     CCFree( m_pExactPalette );
01780                     m_pExactPalette = NULL;
01781                 }
01782             
01783                 // WEBSTER - markn - 22/7/97
01784                 if (ok && SnapToBrowserPalette)
01785                 {
01786                     PaletteManager::SnapToBrowserPalette(pPalette);
01787                 }
01788 
01789                 if (ok)
01790                 {
01791                     // Now we need to shift the colours about a bit ....
01792                     switch (PaletteSize)
01793                     {
01794                         INT32 index;
01795 
01796                         case 2:
01797                             if (NumColours == 1)
01798                             {
01799                                 // 1 colour needs some special treatment
01800                                 if (pPalette->palPalEntry[1].peRed   == 0xFF &&
01801                                     pPalette->palPalEntry[1].peGreen == 0xFF &&
01802                                     pPalette->palPalEntry[1].peBlue  == 0xFF)
01803                                 {
01804                                     // First entry is white
01805                                     pPalette->palPalEntry[1] = pPalette->palPalEntry[0];
01806                                     pPalette->palPalEntry[1].peFlags = 0;
01807 
01808 
01809                                     pPalette->palPalEntry[0].peRed   = 255;
01810                                     pPalette->palPalEntry[0].peGreen = 255;
01811                                     pPalette->palPalEntry[0].peBlue  = 255;
01812                                     pPalette->palPalEntry[0].peFlags = 255;     // This makes Gavin ignore this
01813                                                                                 // colour when converting the bitmap
01814                                 }
01815                                 else if (pPalette->palPalEntry[0].peRed   == 0xFF &&
01816                                          pPalette->palPalEntry[0].peGreen == 0xFF &&
01817                                          pPalette->palPalEntry[0].peBlue  == 0xFF)
01818                                 {
01819                                     // Second entry is white
01820                                     pPalette->palPalEntry[0].peFlags = 255;     // This makes Gavin ignore this
01821                                                                                 // colour when converting the bitmap
01822                                 }
01823                                 else
01824                                 {
01825                                     // Neither entry is white !
01826                                     pPalette->palPalEntry[0].peRed   = 255;
01827                                     pPalette->palPalEntry[0].peGreen = 255;
01828                                     pPalette->palPalEntry[0].peBlue  = 255;
01829                                     pPalette->palPalEntry[0].peFlags = 255;     // This makes Gavin ignore this
01830                                                                                 // colour when converting the bitmap
01831                                 }
01832                                 
01833                                 pPalette->palNumEntries = 2;
01834                             }
01835                             else
01836                                 pPalette->palNumEntries += ReservedColours;
01837                             break;
01838 
01839                         case 16:
01840                             // Shift the palette entries down, so the reserved colours are at the start
01841                             for (index = NumColours - 1; index >= 0; index--)
01842                             {
01843                                 pPalette->palPalEntry[index + ReservedColours] = pPalette->palPalEntry[index];
01844                             }
01845 
01846                             // Blank the reserved colours to white
01847                             for (index = 0; index < INT32(ReservedColours); index++)
01848                             {
01849                                 pPalette->palPalEntry[index].peRed   = 255;
01850                                 pPalette->palPalEntry[index].peGreen = 255;
01851                                 pPalette->palPalEntry[index].peBlue  = 255;
01852                                 pPalette->palPalEntry[index].peFlags = 255;     // This makes Gavin ignore this
01853                                                                                 // colour when converting the bitmap
01854                             }
01855 
01856                             pPalette->palNumEntries += ReservedColours;
01857                             break;
01858 
01859                         case 256:
01860                             #ifdef _BATCHING
01861                             {
01862                                     for (UINT32 index = 0;index < NumColours;index++)
01863                                     {
01864                                         BYTE R = pPalette->palPalEntry[index].peRed;
01865                                         BYTE G = pPalette->palPalEntry[index].peGreen;
01866                                         BYTE B = pPalette->palPalEntry[index].peBlue;
01867                                         if (R == 254 && G == 254 && B == 254)
01868                                         {
01869                                             pPalette->palPalEntry[index].peRed = 255;
01870                                             pPalette->palPalEntry[index].peGreen = 255;
01871                                             pPalette->palPalEntry[index].peBlue = 255;
01872                                         }                                           
01873                                     }
01874                             }
01875                             #endif
01876                             
01877                             if (UseSpecial8bpp && !( !m_bTooManyColours && !UseOldPalette ) )
01878                             {
01879                                 LPLOGPALETTE pWinPalette;
01880 
01881                                 // Now we move the colours.
01882                                 UINT32 CurStart = 16;
01883                                 UINT32 NewStart = 10 + ReservedColours;
01884 
01885                                 if (CurStart < NumColours)
01886                                 {
01887                                     BOOL ColoursMoved = FALSE;
01888 
01889                                     UINT32 NumColsToMove = NumColours - CurStart;
01890                                     ERROR3IF((NumColsToMove+CurStart) > 256,"No room for system colours");
01891                                     ERROR3IF((NumColsToMove+NewStart) > 256,"No room for system colours");
01892                                     
01893                                     if (NewStart < CurStart)
01894                                     {
01895                                         // Move the non-system colours down
01896                                         for (index = 0; index < INT32(NumColsToMove); index++)
01897                                             pPalette->palPalEntry[index + NewStart] = pPalette->palPalEntry[index + CurStart];
01898 
01899                                         // Blank out unused colours that are not system colours
01900                                         for (index = NumColsToMove+NewStart;index < 246;index++)
01901                                         {
01902                                             pPalette->palPalEntry[index].peRed   = 0;
01903                                             pPalette->palPalEntry[index].peGreen = 0;
01904                                             pPalette->palPalEntry[index].peBlue  = 0;
01905                                         }
01906 
01907                                         ColoursMoved = TRUE;
01908                                     }
01909 
01910                                     ERROR3IF(!ColoursMoved,"Rewrite code to accomodate system colours");
01911                                 }
01912 
01913                                 ERROR3IF(CurStart > NumColours,"Not enough room for system colours");
01914 
01915                                 // Now fill in the rest of the palette with the 20 system colours
01916                                 // (10 at the start, and 10 at the end)
01917                                 pWinPalette = GetErrorDiffPalette();
01918 
01919                                 for (index = 0; index < 10; index++)
01920                                 {
01921                                     pPalette->palPalEntry[index] = pWinPalette->palPalEntry[index];
01922                                 }
01923 
01924                                 for (index = 246; index < 256; index++)
01925                                 {
01926                                     pPalette->palPalEntry[index] = pWinPalette->palPalEntry[index];
01927                                 }
01928                             
01929                                 // Blank the reserved colours to white
01930                                 for (index = 10; index < INT32(10 + ReservedColours); index++)
01931                                 {
01932                                     pPalette->palPalEntry[index].peRed   = 255;
01933                                     pPalette->palPalEntry[index].peGreen = 255;
01934                                     pPalette->palPalEntry[index].peBlue  = 255;
01935                                     pPalette->palPalEntry[index].peFlags = 255;     // This makes Gavin ignore this
01936                                                                                     // colour when converting the bitmap
01937                                 }
01938                             }
01939                             else
01940                             {
01941                                 // WEBSTER - markn 15/2/97
01942                                 // If there's a reserved colour (i.e. creating a transparent bitmap)
01943                                 // make sure Gavin doen't use it
01944                                 // To do this, shift all the colours up one place, and flag the reserved colour
01945                                 // (hard wired to 10 for some reason unknown to myself) so Gavin ignores it
01946                                 if (ReservedColours == 1)
01947                                 {
01948                                     for (index = 255;index > 10;index--)
01949                                         pPalette->palPalEntry[index] = pPalette->palPalEntry[index-1];
01950 
01951                                     pPalette->palPalEntry[10].peRed   = 255;
01952                                     pPalette->palPalEntry[10].peGreen = 255;
01953                                     pPalette->palPalEntry[10].peBlue  = 255;
01954                                     pPalette->palPalEntry[10].peFlags = 255;        // This makes Gavin ignore this
01955                                 }
01956 
01957                                 ERROR3IF(ReservedColours > 1,"This code won't work with more than one reserved colour");
01958 
01959                                 // As this code is assuming that the transparent colour index is 10,
01960                                 // if the user has chosen less than 10 colours, we need to ensure that
01961                                 // the palette actually includes the transparent colour index. Otherwise,
01962                                 // the GIF export code will assume it can output the requested colours using
01963                                 // the minimum bpp. E.g. user request 2 colours, output will be 1 bpp and
01964                                 // so the 10 will cause problems.
01965                                 // This fixing of the number of entries is actually done in ExtractBitmapCopy
01966                             }
01967                             break;
01968                         default:
01969                             ERROR3("Bad palette size in GRenderOptPalette::GetOptimisedPalette");
01970                     }
01971                 }
01972                 else
01973                 {
01974                     ERROR3("Failed to generate optimised palette");
01975                     CCFree( pPalette );
01976                     pPalette = NULL;
01977                 }
01978             }
01979         }
01980 
01981         // Reinitialise the Stats
01982         if (UseSpecial8bpp)
01983             DIBUtil::Optimal8bppPaletteInitialise((INT32*)Stats);
01984         else
01985             DIBUtil::OptimalPaletteInitialise(Stats);
01986     }
01987 
01988     return pPalette;
01989 }


Member Data Documentation

BOOL GRenderOptPalette::DoGDrawConversion = TRUE [static]
 

Definition at line 249 of file grndbmp.h.

BOOL GRenderOptPalette::DoTwoColourRoundingToPrimary = TRUE [static]
 

Definition at line 247 of file grndbmp.h.

BOOL GRenderOptPalette::m_bTooManyColours [protected]
 

Definition at line 257 of file grndbmp.h.

LPLOGPALETTE GRenderOptPalette::m_pExactPalette [protected]
 

Definition at line 258 of file grndbmp.h.

void* GRenderOptPalette::Stats [protected]
 

Definition at line 254 of file grndbmp.h.

BOOL GRenderOptPalette::UseOldPalette = TRUE [static]
 

Definition at line 250 of file grndbmp.h.

BOOL GRenderOptPalette::UseSpecial8bpp [protected]
 

Definition at line 255 of file grndbmp.h.


The documentation for this class was generated from the following files:
Generated on Sat Nov 10 03:54:59 2007 for Camelot by  doxygen 1.4.4