--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/graphicstools/gdi_tools/bmconv/PBMCOMP.CPP Tue Feb 02 01:47:50 2010 +0200
@@ -0,0 +1,1271 @@
+// Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+#include "BMCONV.H"
+#include <stdlib.h>
+#include <ctype.h>
+#include <sys/stat.h>
+
+extern TRgb* color256Palette;
+extern char* color256InversePalette;
+
+static inline bool CanCopy16bppData(const char* aDest, const char* aDestEnd, int aDataSize)
+ {
+ const char* aDestNew = aDest + (aDataSize / 128) * (256 + 1) + //(2 * 128) bytes data + 1 leading byte
+ (aDataSize % 128 ? (aDataSize % 128) * 2 + 1 : 0);
+ return aDestNew <= aDestEnd;
+ }
+
+static inline bool CanWrite16bppValue(const char* aDest, const char* aDestEnd, int aDataSize)
+ {
+ const char* aDestNew = aDest + (aDataSize / 128) * (2 + 1) + //2 bytes data + 1 leading byte
+ (aDataSize % 128 ? 2 + 1 : 0);
+ return aDestNew <= aDestEnd;
+ }
+
+static inline bool CanCopy8bppData(const char* aDest, const char* aDestEnd, int aDataSize)
+ {
+ const char* aDestNew = aDest + (aDataSize / 128) * (128 + 1) + //128 bytes data + 1 leading byte
+ (aDataSize % 128 ? (aDataSize % 128) + 1 : 0);
+ return aDestNew <= aDestEnd;
+ }
+
+static inline bool CanWrite8bppValue(const char* aDest, const char* aDestEnd, int aDataSize)
+ {
+ const char* aDestNew = aDest + (aDataSize / 128) * (1 + 1) + //1 byte data + 1 leading byte
+ (aDataSize % 128 ? 1 + 1 : 0);
+ return aDestNew <= aDestEnd;
+ }
+
+static inline bool CanCopy24bppData(const char* aDest, const char* aDestEnd, int aDataSize)
+ {
+ const char* aDestNew = aDest + (aDataSize / 128) * (384 + 1) + //(128 * 3) bytes data + 1 leading byte
+ (aDataSize % 128 ? (aDataSize % 128) * 3 + 1 : 0);
+ return aDestNew <= aDestEnd;
+ }
+
+static inline bool CanWrite24bppValue(const char* aDest, const char* aDestEnd, int aDataSize)
+ {
+ const char* aDestNew = aDest + (aDataSize / 128) * (3 + 1) + //3 bytes data + 1 leading byte
+ (aDataSize % 128 ? 3 + 1 : 0);
+ return aDestNew <= aDestEnd;
+ }
+
+static inline bool CanCopy32bppData(const char* aDest, const char* aDestEnd, int aDataSize)
+ {
+ const char* aDestNew = aDest + (aDataSize / 128) * (512 + 1) + //(128 * 4) bytes data + 1 leading byte
+ (aDataSize % 128 ? (aDataSize % 128) * 4 + 1 : 0);
+ return aDestNew <= aDestEnd;
+ }
+
+static inline bool CanWrite32bppValue(const char* aDest, const char* aDestEnd, int aDataSize)
+ {
+ const char* aDestNew = aDest + (aDataSize / 128) * (4 + 1) + //4 bytes data + 1 leading byte
+ (aDataSize % 128 ? 4 + 1 : 0);
+ return aDestNew <= aDestEnd;
+ }
+
+BitmapCompiler::BitmapCompiler(char* aSourcefilenames[],int aNumSources):
+ iSourcefilenames(aSourcefilenames),
+ iPbmSources(NULL),
+ iNumSources(aNumSources)
+ {}
+
+BitmapCompiler::~BitmapCompiler()
+ {
+ iDestFile.close();
+ if(iPbmSources)
+ for(int count=0;count<iNumSources;count++)
+ delete iPbmSources[count];
+ delete [] iPbmSources;
+ iPbmSources = NULL;
+ }
+
+int BitmapCompiler::Compile(TStoreType aSt,int aCompress,char* aDestfilename,char* aHeaderFilename,char* aPaletteFilename)
+ {
+ int ret = LoadPalette(aPaletteFilename);
+ if (ret)
+ return ret;
+
+ iDestFile.open(aDestfilename, ios::out | ios::binary);
+ if(iDestFile.is_open()==0)
+ return DestFile;
+ if (iNumSources < 1)
+ return SourceFile;
+
+ if (iNumSources==1 && ((iSourcefilenames[0][0]==OPTCHAR || iSourcefilenames[0][0]==ALTERNATE_OPTCHAR)) && iSourcefilenames[0][1]=='m')
+ {
+ // Source is an existing MBM file, presumably because we want to convert
+ // a filestore into a ROM image.
+ if (aHeaderFilename)
+ {
+ cout << "Header file generation is not permitted with /m or -m\n";
+ aHeaderFilename = NULL;
+ }
+ iSourcefilenames[0]+=2;
+ EpocLoader pl;
+ int romFormat;
+ ret = pl.EpocBitmapCount(iSourcefilenames[0], iNumSources, romFormat);
+ if (!ret)
+ ret = LoadPbmFile(iSourcefilenames[0]);
+ }
+ else
+ {
+ // Read the usual list of [OPT]bmp_n source bitmaps.
+ ret = LoadSourcefiles();
+ }
+ if (ret)
+ return ret;
+
+ ret = CreateHeader(aHeaderFilename);
+ if (ret)
+ return ret;
+
+ if (aSt == ERomStore || aSt == ECompressedRomStore)
+ ret = RomImage(aSt == ECompressedRomStore);
+ else
+ ret = FileImage(aCompress);
+ return ret;
+ };
+
+int BitmapCompiler::AllocatePbmSourcesArray()
+ {
+ iPbmSources = new SEpocBitmapHeader*[iNumSources];
+ if(iPbmSources == NULL)
+ return NoMemory;
+
+ memset(iPbmSources,0xff,sizeof(SEpocBitmapHeader*)*iNumSources);
+ int count;
+ for(count=0;count<iNumSources;count++)
+ iPbmSources[count]=NULL;
+ return NoError;
+ }
+
+int BitmapCompiler::LoadSourcefiles()
+ {
+ int ret = AllocatePbmSourcesArray();
+ if (ret)
+ return ret;
+ for(int count=0;count<iNumSources;count++)
+ {
+ bool useAlpha = false;
+ int bpp = 2;
+ TBitmapColor color = EMonochromeBitmap;
+ BitmapLoader bmpload;
+ if(iSourcefilenames[count][0]==OPTCHAR || iSourcefilenames[count][0]==ALTERNATE_OPTCHAR)
+ {
+ iSourcefilenames[count]++;
+ if(iSourcefilenames[count][0]=='c')
+ {
+ color = EColorBitmap;
+ iSourcefilenames[count]++;
+ }
+ bpp=iSourcefilenames[count][0]-'0';
+ iSourcefilenames[count]++;
+ int next=iSourcefilenames[count][0]-'0';
+ if(next==2 || next==6 || next==4)
+ {
+ bpp=bpp*10+next;
+ iSourcefilenames[count]++;
+ }
+ if(iSourcefilenames[count][0]=='a')
+ {
+ useAlpha = true;
+ iSourcefilenames[count]++;
+ if (color!=EColorBitmap || bpp!=32)
+ return Bpp;
+ }
+ if (color == EColorBitmap && bpp!=4 && bpp!=8 && bpp!=12 && bpp!=16 && bpp!=24 && bpp!=32)
+ return Bpp;
+ if (color == EMonochromeBitmap && bpp!=1 && bpp!=2 && bpp!=4 && bpp!=8)
+ return Bpp;
+ }
+ if (color == EColorBitmap && useAlpha)
+ color = EColorBitmapAlpha;
+ ret = bmpload.LoadBitmap(iSourcefilenames[count],bpp,color,iPbmSources[count]);
+ if (ret)
+ return ret;
+ }
+ return NoError;
+ }
+
+int BitmapCompiler::LoadPbmFile(char* aPbmFilename)
+ {
+ int ret = AllocatePbmSourcesArray();
+ if (ret)
+ return ret;
+ for(int count=0;count<iNumSources;count++)
+ {
+ EpocLoader pl;
+ ret = pl.LoadEpocBitmap(aPbmFilename,count);
+ if (!ret)
+ ret = pl.DupBitmap(iPbmSources[count]);
+ if (ret)
+ return ret;
+ }
+ return NoError;
+ }
+
+int BitmapCompiler::RomImage(bool aCompress)
+ {
+ int count=0;
+
+ if (aCompress)
+ {
+ for(; count<iNumSources; count++)
+ {
+ int ret = CompressBitmap(iPbmSources[count]);
+ if (ret)
+ return ret;
+ }
+ }
+
+ int ret = WriteRomheader();
+ if (ret)
+ return ret;
+
+ for(count=0;count<iNumSources;count++)
+ {
+ ret = WriteRombitmap(iPbmSources[count]);
+ if (ret)
+ return ret;
+ }
+ return NoError;
+ }
+
+int BitmapCompiler::FileImage(int aCompress)
+ {
+ int count = 0;
+ if(aCompress)
+ {
+ for(;count<iNumSources;count++)
+ {
+ int ret = CompressBitmap(iPbmSources[count]);
+ if(ret)
+ return ret;
+ }
+ }
+ int ret = WriteFileheader();
+ if (ret)
+ return ret;
+ for (count=0;count<iNumSources;count++)
+ {
+ ret = WriteFilebitmap(iPbmSources[count]);
+ if (ret)
+ return ret;
+ }
+ ret = WriteHeadStream();
+ return ret;
+ }
+
+int BitmapCompiler::WriteRomheader()
+ {
+ iDestFile.write((char*)&KMultiBitmapRomImageUid,4);
+ iDestFile.write((char*)&iNumSources,4);
+ int byteswritten=8+(iNumSources*4);
+ for (int count=0;count<iNumSources;count++)
+ {
+ iDestFile.write((char*)&byteswritten,4);
+ byteswritten+=(((iPbmSources[count]->iBitmapSize)+3)/4*4)-sizeof(SEpocBitmapHeader)+sizeof(Bitmap);
+ }
+ return NoError;
+ }
+
+int BitmapCompiler::WriteRombitmap(SEpocBitmapHeader* aPbm)
+ {
+ if (aPbm->iPaletteEntries != 0)
+ return PaletteSupportNotImplemented;
+
+ int bitmapsize = aPbm->iBitmapSize-sizeof(SEpocBitmapHeader)+sizeof(Bitmap);
+ bitmapsize = ((bitmapsize+3)/4)*4;
+
+ char* buffer = new char[bitmapsize];
+ if (buffer == NULL)
+ return NoMemory;
+ memset(buffer,0xff,bitmapsize);
+
+ Bitmap* bmp = (Bitmap*)buffer;
+ bmp->iUid=KCBitwiseBitmapUid;
+ TBitmapColor color = aPbm->iColor;
+
+ switch(aPbm->iBitsPerPixel)
+ { // for corresponding enums, see TDisplayMode in <gdi.h>
+ case 1:
+ bmp->iDispMode=1;
+ break;
+ case 2:
+ bmp->iDispMode=2;
+ break;
+ case 4:
+ if (color == EMonochromeBitmap)
+ bmp->iDispMode=3;
+ else
+ bmp->iDispMode=5;
+ break;
+ case 8:
+ if (color == EMonochromeBitmap)
+ bmp->iDispMode=4;
+ else
+ bmp->iDispMode=6;
+ break;
+ case 12:
+ bmp->iDispMode=10;
+ break;
+ case 16:
+ bmp->iDispMode=7;
+ break;
+ case 24:
+ bmp->iDispMode=8;
+ break;
+ case 32:
+ if (color == EColorBitmapAlpha)
+ bmp->iDispMode=12; // Color16MA
+ else
+ bmp->iDispMode=11; // Color16MU
+ break;
+ default:
+ delete [] buffer;
+ return SourceFile;
+ }
+
+ bmp->iHeap = NULL;
+ bmp->iPile = NULL;
+ bmp->iHeader = *aPbm;
+ bmp->iByteWidth = BitmapUtils::ByteWidth(bmp->iHeader.iWidthInPixels,bmp->iHeader.iBitsPerPixel);
+ bmp->iDataOffset = sizeof(Bitmap);
+
+ CopyTail(buffer + sizeof(Bitmap), aPbm, aPbm->iBitmapSize, sizeof(SEpocBitmapHeader));
+ iDestFile.write(buffer,bitmapsize);
+
+ delete [] buffer;
+
+ return NoError;
+ }
+
+int BitmapCompiler::WriteFileheader()
+ {
+ int zero=0;
+ iDestFile.write((char*)&KWriteOnceFileStoreUid,4);
+ iDestFile.write((char*)&KMultiBitmapFileImageUid,4);
+ iDestFile.write((char*)&zero,4);
+ iDestFile.write((char*)&KMultiBitmapFileImageChecksum,4);
+ int byteswritten=16;
+ for(int count=0;count<iNumSources;count++)
+ {
+ byteswritten+=iPbmSources[count]->iBitmapSize;
+ }
+ byteswritten+=4;
+ iDestFile.write((char*)&byteswritten,4);
+ return NoError;
+ }
+
+int BitmapCompiler::WriteHeadStream()
+ {
+ iDestFile.write((char*)&iNumSources,4);
+ int byteswritten=20;
+ for(int count=0;count<iNumSources;count++)
+ {
+ iDestFile.write((char*)&byteswritten,4);
+ byteswritten+=iPbmSources[count]->iBitmapSize;
+ }
+ return NoError;
+ }
+
+int BitmapCompiler::WriteFilebitmap(SEpocBitmapHeader* aPbm)
+ {
+ if (aPbm->iPaletteEntries != 0)
+ return PaletteSupportNotImplemented;
+
+ int dataSize = aPbm->iBitmapSize - sizeof(SEpocBitmapHeader);
+
+ iDestFile.write((char*)(aPbm),sizeof(SEpocBitmapHeader));
+ // WritePalette()
+ iDestFile.write(((char*)(aPbm)) + sizeof(SEpocBitmapHeader),dataSize);
+
+ return NoError;
+ }
+
+void BitmapCompiler::WritePalette()
+ {
+ for (int index = 0; index < 256; index++)
+ {
+ iDestFile.write((char*)(&iPalette[index]),3);
+ }
+ }
+
+int BitmapCompiler::LoadPalette(char* aPaletteFilename)
+ {
+ if (!aPaletteFilename)
+ {
+ iDefaultPalette = 1;
+ return NoError;
+ }
+
+ iDefaultPalette = 0;
+ color256Palette = iPalette;
+ color256InversePalette = iInversePalette;
+
+ struct stat fileinfo;
+ if (stat(aPaletteFilename,&fileinfo)==-1)
+ return CommandFile;
+
+ int filesize = fileinfo.st_size;
+ if (filesize == 0)
+ return PaletteFile;
+
+#if defined(__MSVCDOTNET__) || defined(__TOOLS2__)
+ fstream paletteFile(aPaletteFilename, ios::in | ios::binary);
+#else
+ fstream paletteFile(aPaletteFilename, ios::in | ios::binary | ios::nocreate);
+#endif
+
+ if(!paletteFile.is_open())
+ return PaletteFile;
+
+ char* paletteData = new char[filesize];
+ if (!paletteData)
+ return NoMemory;
+
+ memset(paletteData,0,filesize);
+ paletteFile.read(paletteData,filesize);
+ paletteFile.close();
+
+ char* dataPtr = (char*)paletteData;
+ char* dataPtrLimit = dataPtr + filesize;
+
+ for (int index = 0; index < 256; index++)
+ {
+ char hexBuf[10];
+ int ret = ReadHexString(hexBuf,dataPtr,dataPtrLimit);
+ if (ret)
+ {
+ delete paletteData;
+ return ret;
+ }
+
+ int red = HexToInt(hexBuf[8],hexBuf[9]);
+ int green = HexToInt(hexBuf[6],hexBuf[7]);
+ int blue = HexToInt(hexBuf[4],hexBuf[5]);
+
+ iPalette[index] = TRgb(red,green,blue);
+ }
+
+ delete paletteData;
+ CalculateInversePalette();
+ return NoError;
+ }
+
+void BitmapCompiler::CalculateInversePalette()
+ {
+ for (int index = 0; index < 4096; index++)
+ {
+ TRgb color = TRgb((index & 0x00f) * 17,((index & 0x0f0) >> 4) * 17,((index & 0xf00) >> 8) * 17);
+
+ int nearest = 0;
+ int distance = iPalette[0].Difference(color);
+
+ for (int paletteIndex = 0; paletteIndex < 256; paletteIndex++)
+ {
+ TRgb paletteColor = iPalette[paletteIndex];
+
+ if (paletteColor == color)
+ {
+ nearest = paletteIndex;
+ break;
+ }
+
+ int paletteDistance = paletteColor.Difference(color);
+ if (paletteDistance < distance)
+ {
+ nearest = paletteIndex;
+ distance = paletteDistance;
+ }
+ }
+
+ iInversePalette[index] = (char)nearest;
+ TRgb palColor = iPalette[nearest];
+ color = palColor;
+ }
+ }
+
+int BitmapCompiler::CreateHeader(char* aHeaderFilename)
+ {
+ if (!aHeaderFilename)
+ return NoError;
+
+ fstream hf(aHeaderFilename,ios::out);
+ if(!hf.is_open())
+ return DestFile;
+
+ char* basename = strrchr(aHeaderFilename,'\\');
+ if (basename==0)
+ basename = aHeaderFilename;
+ else
+ basename++; // skip directory separator
+
+ char unadornedFile[256];
+ strcpy(unadornedFile, UnadornedName(aHeaderFilename));
+
+ hf << "// " << basename << "\n";
+ hf << "// Generated by BitmapCompiler\n";
+ hf << "// Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).\n";
+ hf << "//\n\n";
+ hf << "enum TMbm" << unadornedFile << "\n";
+ hf << "\t{\n";
+
+ for (int count=0;count<iNumSources;count++)
+ {
+ hf << "\tEMbm" << unadornedFile << UnadornedName(iSourcefilenames[count]);
+ if(count<iNumSources-1)
+ hf << ',';
+ hf << '\n';
+ }
+ hf << "\t};\n";
+ hf.close();
+ return NoError;
+ }
+
+char* BitmapCompiler::UnadornedName(char* aName)
+ {
+ int len = strlen(aName);
+
+ char* foundDir = strrchr(aName,'\\');
+ char* foundUrl = strrchr(aName,'/');
+ char* foundExt = strrchr(aName,'.');
+
+ char* foundPath = (foundDir > foundUrl) ? foundDir : foundUrl;
+ char* firstchar = (foundPath > 0) ? foundPath + 1 : aName;
+ char* lastchar = (foundExt > firstchar) ? foundExt : aName+len;
+
+ static char result[256];
+ if (lastchar-firstchar > 255)
+ {
+ strcpy(result,"NameTooLong");
+ return result;
+ }
+ int i=0;
+ result[0] = (char)toupper(*firstchar);
+ firstchar+=1;
+ for (i=1; firstchar<lastchar; i++,firstchar++)
+ {
+ result[i] = (char)tolower(*firstchar);
+ }
+ result[i] = '\0';
+ return result;
+ }
+
+int BitmapCompiler::CompressBitmap(SEpocBitmapHeader*& aPbm)
+ {
+ int originalsize = aPbm->iBitmapSize-sizeof(SEpocBitmapHeader);
+ char* newbits=new char[originalsize+sizeof(SEpocBitmapHeader)];
+ if(!newbits)
+ return NoMemory;
+
+ memset(newbits,0xff,sizeof(SEpocBitmapHeader)+originalsize);
+ memcpy(newbits,aPbm,sizeof(SEpocBitmapHeader));
+ char* newbitsptr=newbits+sizeof(SEpocBitmapHeader);
+ char* oldbits=((char*)(aPbm))+sizeof(SEpocBitmapHeader);
+
+ TBitmapfileCompression compression = ENoBitmapCompression;
+ int ret = NoCompression;
+
+ if (aPbm->iBitsPerPixel <= 8)
+ {
+ compression = EByteRLECompression;
+ ret = CompressByteData(newbitsptr,oldbits,originalsize);
+ }
+ else if (aPbm->iBitsPerPixel == 12)
+ {
+ compression = ETwelveBitRLECompression;
+ ret = CompressTwelveBitData(newbitsptr,oldbits,originalsize);
+ }
+ else if (aPbm->iBitsPerPixel == 16)
+ {
+ compression = ESixteenBitRLECompression;
+ ret = CompressSixteenBitData(newbitsptr,oldbits,originalsize);
+ }
+ else if (aPbm->iBitsPerPixel == 24)
+ {
+ compression = ETwentyFourBitRLECompression;
+ ret = CompressTwentyFourBitData(newbitsptr,oldbits,originalsize);
+ }
+ else if (aPbm->iBitsPerPixel == 32 && (aPbm->iColor == EColorBitmap))
+ {
+ compression = EThirtyTwoUBitRLECompression;
+ ret = CompressThirtyTwoUBitData(newbitsptr,oldbits,originalsize);
+ }
+ else if (aPbm->iBitsPerPixel == 32 && (aPbm->iColor == EColorBitmapAlpha))
+ {
+ compression = EThirtyTwoABitRLECompression;
+ ret = CompressThirtyTwoABitData(newbitsptr,oldbits,originalsize);
+ }
+
+ if(ret)
+ {
+ delete [] newbits;
+ if(ret>0)
+ return ret;
+ return NoError;
+ }
+
+ delete aPbm;
+ aPbm = (SEpocBitmapHeader*)newbits;
+ aPbm->iBitmapSize = newbitsptr-(newbits+sizeof(SEpocBitmapHeader))+sizeof(SEpocBitmapHeader);
+ aPbm->iCompression = compression;
+ return NoError;
+ }
+
+int BitmapCompiler::CompressByteData(char*& aDest,char* aSrce,int aSize)
+ {
+ const char* destEnd = aDest + aSize;
+ char* bytepointer=aSrce;
+ char* limitpointer=bytepointer+aSize;
+ int margin = (aSize>>6);
+ char* limitmargin = limitpointer - ((margin > 4) ? margin : 4);
+ char* cutoffpointer=aDest+(aSize>>1)+(aSize>>2);
+ int ret=NoError;
+ char* oldbytepointer=NULL;
+ while(bytepointer<limitmargin)
+ {
+ char value=*bytepointer;
+ if(*(bytepointer+1)==value && *(bytepointer+2)==value)
+ {
+ oldbytepointer=bytepointer;
+ bytepointer+=3;
+ while ( ( bytepointer < limitmargin ) && ( *bytepointer == value ) )
+ bytepointer++;
+ ret = WriteCompressedByteValues(aDest,value,bytepointer-oldbytepointer, destEnd);
+ if(ret) return ret;
+ }
+ else
+ {
+ oldbytepointer=bytepointer;
+ while((bytepointer<limitmargin) && (*(bytepointer+1)!=value || *(bytepointer+2)!=value))
+ {
+ bytepointer++;
+ value=*bytepointer;
+ }
+ ret = WriteCompressedByteData(aDest,oldbytepointer,bytepointer-oldbytepointer, destEnd);
+ if(ret) return ret;
+ }
+ if(aDest>cutoffpointer)
+ return NoCompression;
+ }
+
+ int remaining = limitpointer-bytepointer;
+ if(remaining > 0)
+ {
+ if (aDest + remaining > cutoffpointer)
+ return NoCompression;
+ ret=WriteCompressedByteData(aDest,bytepointer,remaining, destEnd);
+ if(ret) return ret;
+ }
+ return NoError;
+ }
+
+int BitmapCompiler::WriteCompressedByteData(char*& aDest,char* aData,int aLength, const char* aDestEnd)
+ {
+ if(!CanCopy8bppData(aDest, aDestEnd, aLength))
+ return NoCompression;
+ while(aLength>128)
+ {
+ *aDest++=-128;
+ for(int count=0;count<128;count++)
+ *aDest++=*aData++;
+ aLength-=128;
+ }
+ if(aLength>128 || aLength<1) return CompressionError;
+ *aDest++=char(-aLength);
+ for(int count=0;count<aLength;count++)
+ *aDest++=*aData++;
+ return NoError;
+ }
+
+int BitmapCompiler::WriteCompressedByteValues(char*& aDest,char aValue,int aLength, const char* aDestEnd)
+ {
+ if (aLength < 1)
+ return CompressionError;
+
+ if(!CanWrite8bppValue(aDest, aDestEnd, aLength))
+ return NoCompression;
+
+ while (aLength > 128)
+ {
+ *aDest++ = 127;
+ *aDest++ = aValue;
+ aLength -= 128;
+ }
+
+ *aDest++ = char(aLength-1);
+ *aDest++ = aValue;
+
+ return NoError;
+ }
+
+int BitmapCompiler::CompressTwelveBitData(char*& aDest,char* aSrce,int aSizeInBytes)
+ {
+ unsigned short* srcePtr = (unsigned short*)aSrce;
+ unsigned short* srceLimitPtr = srcePtr + (aSizeInBytes / 2);
+ unsigned short* dest = (unsigned short*)aDest;
+
+ while (srcePtr < srceLimitPtr)
+ {
+ unsigned short* runStartPtr = srcePtr;
+ unsigned short value = *srcePtr;
+ do
+ srcePtr++;
+ while (srcePtr < srceLimitPtr && *srcePtr == value);
+ WriteCompressedTwelveBitData(dest,*runStartPtr,srcePtr - runStartPtr); // Ignore error return as 12bpp compression never fails
+ }
+
+ aDest = (char*)dest;
+ return NoError;
+ }
+
+int BitmapCompiler::WriteCompressedTwelveBitData(unsigned short*& aDest,unsigned short aData,int aLength)
+ {
+ // The run length l is stored as l-1 in the top 4 bits of each 16-bit word (between 1 and 16)
+ aData &= 0x0fff;
+ unsigned short maxLengthData = (unsigned short)(aData | 0xf000);
+
+ while(aLength>16)
+ {
+ *aDest++ = maxLengthData;
+ aLength -= 16;
+ }
+
+ if (aLength > 0)
+ *aDest++ = (unsigned short)(aData | ((aLength - 1) << 12));
+
+ return NoError;
+ }
+
+int BitmapCompiler::CompressSixteenBitData(char*& aDest,char* aSrce,int aSizeInBytes)
+ {
+ char* destEnd = aDest + aSizeInBytes;
+ unsigned short* srcePtr = (unsigned short*)aSrce;
+ unsigned short* srceLimitPtr = srcePtr + (aSizeInBytes / 2);
+ unsigned short* srceLimitPtrMinusOne = srceLimitPtr - 1;
+ char* destCompressedLimitPtr = aDest + (aSizeInBytes * 7 / 8);
+ int ret = NoError;
+
+ while (srcePtr < srceLimitPtrMinusOne)
+ {
+ unsigned short value = *srcePtr;
+ unsigned short* runStartPtr = srcePtr++;
+
+ if(*srcePtr == value)
+ {
+ do
+ srcePtr++;
+ while ( ( srcePtr < srceLimitPtr ) && ( *srcePtr == value ) );
+
+ ret = WriteCompressedSixteenBitValues(aDest,value,srcePtr-runStartPtr, destEnd);
+ if (ret)
+ return ret;
+ }
+ else
+ {
+ value = *srcePtr;
+ while (srcePtr < srceLimitPtrMinusOne && *(srcePtr + 1) != value)
+ {
+ srcePtr++;
+ value = *srcePtr;
+ }
+
+ ret = WriteCompressedSixteenBitData(aDest,runStartPtr,srcePtr - runStartPtr, destEnd);
+ if (ret)
+ return ret;
+ }
+ if (aDest > destCompressedLimitPtr)
+ return NoCompression;
+ }
+
+ if (srcePtr < srceLimitPtr)
+ {
+ ret = WriteCompressedSixteenBitData(aDest,srcePtr,srceLimitPtr - srcePtr, destEnd);
+ if (ret)
+ return ret;
+ }
+
+ if (aDest > destCompressedLimitPtr)
+ return NoCompression;
+ return NoError;
+ }
+
+int BitmapCompiler::WriteCompressedSixteenBitData(char*& aDest,unsigned short* aData,
+ int aLength, const char* aDestEnd)
+ {
+ if (aLength < 1)
+ return CompressionError;
+
+ if(!CanCopy16bppData(aDest, aDestEnd, aLength))
+ return NoCompression;
+
+ char* srcePtr = (char*)aData;
+
+ while (aLength > 128)
+ {
+ *aDest++ = -128;
+ memcpy(aDest,srcePtr,256);
+ aDest += 256;
+ srcePtr += 256;
+ aLength -= 128;
+ }
+
+ *aDest++ = char(-aLength);
+
+ int remainingBytes = aLength * 2;
+ memcpy(aDest,srcePtr,remainingBytes);
+ aDest += remainingBytes;
+
+ return NoError;
+ }
+
+int BitmapCompiler::WriteCompressedSixteenBitValues(char*& aDest,unsigned short aValue,
+ int aLength, const char* aDestEnd)
+ {
+ if (aLength < 1)
+ return CompressionError;
+
+ if(!CanWrite16bppValue(aDest, aDestEnd, aLength))
+ return NoCompression;
+
+ char lowByte = char(aValue);
+ char highByte = char(aValue >> 8);
+
+ while (aLength > 128)
+ {
+ *aDest++ = 127;
+ *aDest++ = lowByte;
+ *aDest++ = highByte;
+ aLength -= 128;
+ }
+
+ *aDest++ = char(aLength-1);
+ *aDest++ = lowByte;
+ *aDest++ = highByte;
+
+ return NoError;
+ }
+
+int BitmapCompiler::CompressTwentyFourBitData(char*& aDest,char* aSrce,int aSizeInBytes)
+ {
+ const char* destEnd = aDest + aSizeInBytes;
+ char* srceLimitPtr = aSrce + aSizeInBytes;
+ char* srceLimitPtrMinusThree = srceLimitPtr - 3; // three bytes == one pixel
+ char* destCompressedLimitPtr = aDest + (aSizeInBytes * 7 / 8);
+ int ret = NoError;
+
+ while (aSrce < srceLimitPtrMinusThree)
+ {
+ char* runStartPtr = aSrce;
+ char component1 = *aSrce++;
+ char component2 = *aSrce++;
+ char component3 = *aSrce++;
+
+ if (TrueColorPointerCompare(aSrce,component1,component2,component3))
+ {
+ do
+ aSrce += 3;
+ while (aSrce < srceLimitPtr && TrueColorPointerCompare(aSrce,component1,component2,component3));
+
+ ret = WriteCompressedTwentyFourBitValues(aDest,component1,component2,component3,(aSrce - runStartPtr) / 3, destEnd);
+ if (ret)
+ return ret;
+ }
+ else
+ {
+ bool more = true;
+ bool eqRun = false;
+ do
+ {
+ component1 = *aSrce++;
+ component2 = *aSrce++;
+ component3 = *aSrce++;
+ more = (aSrce < srceLimitPtr);
+ eqRun = more && TrueColorPointerCompare(aSrce,component1,component2,component3);
+ }
+ while (more && !eqRun);
+ if (eqRun)
+ aSrce -= 3;
+ int pixelLength = (aSrce - runStartPtr) / 3;
+ ret = WriteCompressedTwentyFourBitData(aDest,runStartPtr,pixelLength,destEnd);
+ if (ret)
+ return ret;
+ }
+ if (aDest > destCompressedLimitPtr)
+ return NoCompression;
+ }
+
+ if (aSrce < srceLimitPtr)
+ {
+ ret = WriteCompressedTwentyFourBitData(aDest,aSrce,(srceLimitPtr - aSrce) / 3, destEnd);
+ if (ret)
+ return ret;
+ }
+
+ if (aDest > destCompressedLimitPtr)
+ return NoCompression;
+ return NoError;
+ }
+
+int BitmapCompiler::WriteCompressedTwentyFourBitData(char*& aDest,char* aData,
+ int aLength, const char* aDestEnd)
+ {
+ if (aLength < 1)
+ return CompressionError;
+
+ if(!CanCopy24bppData(aDest, aDestEnd, aLength))
+ return NoCompression;
+
+ while (aLength > 128)
+ {
+ *aDest++ = -128;
+ memcpy(aDest,aData,384);
+ aDest += 384;
+ aData += 384;
+ aLength -= 128;
+ }
+
+ *aDest++ = char(-aLength);
+
+ int remainingBytes = aLength * 3;
+ memcpy(aDest,aData,remainingBytes);
+ aDest += remainingBytes;
+
+ return NoError;
+ }
+
+int BitmapCompiler::WriteCompressedTwentyFourBitValues(char*& aDest,char aComponent1,
+ char aComponent2,char aComponent3,
+ int aLength, const char* aDestEnd)
+ {
+ if (aLength < 1)
+ return CompressionError;
+
+ if(!CanWrite24bppValue(aDest, aDestEnd, aLength))
+ return NoCompression;
+
+ while (aLength > 128)
+ {
+ *aDest++ = 127;
+ *aDest++ = aComponent1;
+ *aDest++ = aComponent2;
+ *aDest++ = aComponent3;
+ aLength -= 128;
+ }
+
+ *aDest++ = char(aLength-1);
+ *aDest++ = aComponent1;
+ *aDest++ = aComponent2;
+ *aDest++ = aComponent3;
+
+ return NoError;
+ }
+
+/** The function encodes 32-bit buffer into 24-bit stream by using RLE compression algorithm*/
+int BitmapCompiler::CompressThirtyTwoUBitData(char*& aDest,char* aSrce,int aSizeInBytes)
+ {
+ const char* destEnd = aDest + aSizeInBytes;
+ char* srceLimitPtr = aSrce + aSizeInBytes;
+ char* srceLimitPtrMinusFour = srceLimitPtr - 4; // four bytes == one pixel
+ char* destCompressedLimitPtr = aDest + (aSizeInBytes * 7 / 8);
+ int ret = NoError;
+
+ while (aSrce < srceLimitPtrMinusFour)
+ {
+ char* runStartPtr = aSrce;
+ char component1 = *aSrce++;
+ char component2 = *aSrce++;
+ char component3 = *aSrce++;
+ aSrce++;
+
+ if (TrueColorPointerCompare(aSrce,component1,component2,component3))
+ {
+ do
+ aSrce += 4;
+ while (aSrce < srceLimitPtr && TrueColorPointerCompare(aSrce,component1,component2,component3));
+
+ ret = WriteCompressedThirtyTwoUBitValues(aDest,component1,component2,component3,(aSrce - runStartPtr) / 4, destEnd);
+ if (ret)
+ return ret;
+ }
+ else //non repeating pixel buffer
+ {
+ bool more = true;
+ bool eqRun = false;
+ do {
+ component1 = *aSrce++;
+ component2 = *aSrce++;
+ component3 = *aSrce++;
+ aSrce++; //last byte is unused (no alpha component)
+ more = (aSrce < srceLimitPtr);
+ eqRun = more && TrueColorPointerCompare(aSrce,component1,component2,component3);
+ } while (more && !eqRun);
+ if (eqRun)
+ aSrce -= 4;
+ int pixelLength = (aSrce - runStartPtr) / 4;
+ ret = WriteCompressedThirtyTwoUBitData(aDest,runStartPtr,pixelLength,destEnd);
+ if (ret)
+ return ret;
+ }
+ if (aDest > destCompressedLimitPtr)
+ return NoCompression;
+ }
+
+ if (aSrce < srceLimitPtr)
+ {
+ ret = WriteCompressedThirtyTwoUBitData(aDest,aSrce,(srceLimitPtr - aSrce) / 4, destEnd);
+ if (ret)
+ return ret;
+ }
+
+ if (aDest > destCompressedLimitPtr)
+ return NoCompression;
+ return NoError;
+ }
+
+/** The function copies non repeating 32-bit buffer to 24-bit compressed buffer*/
+int BitmapCompiler::WriteCompressedThirtyTwoUBitData(char*& aDest,char* aData,
+ int aLength, const char* aDestEnd)
+ {
+ if (aLength < 1)
+ return CompressionError;
+
+ if(!CanCopy24bppData(aDest, aDestEnd, aLength))
+ return NoCompression;
+
+ while (aLength > 128)
+ {
+ *aDest++ = -128;
+ for(int ii = 0; ii < 128; ii++)
+ {
+ memcpy(aDest,aData, 3);
+ aDest += 3;
+ aData += 4;
+ }
+ aLength -= 128;
+ }
+
+ *aDest++ = char(-aLength);
+
+ while(aLength--)
+ {
+ memcpy(aDest,aData, 3);
+ aDest += 3;
+ aData += 4;
+ }
+
+ return NoError;
+ }
+
+/** The function copies repeating colour to the 24-bit compressed buffer */
+int BitmapCompiler::WriteCompressedThirtyTwoUBitValues(char*& aDest,char aComponent1,
+ char aComponent2,char aComponent3,
+ int aLength, const char* aDestEnd)
+ {
+ if (aLength < 1)
+ return CompressionError;
+
+ if(!CanWrite24bppValue(aDest, aDestEnd, aLength))
+ return NoCompression;
+ while (aLength > 128)
+ {
+ *aDest++ = 127;
+ *aDest++ = aComponent1;
+ *aDest++ = aComponent2;
+ *aDest++ = aComponent3;
+ aLength -= 128;
+ }
+
+ *aDest++ = char(aLength-1);
+ *aDest++ = aComponent1;
+ *aDest++ = aComponent2;
+ *aDest++ = aComponent3;
+
+ return NoError;
+ }
+
+int BitmapCompiler::TrueColorPointerCompare(char* aColorPointer,char aComponent1,char aComponent2,char aComponent3)
+ {
+ return (*aColorPointer == aComponent1 && *(aColorPointer + 1) == aComponent2 && *(aColorPointer + 2) == aComponent3);
+ }
+
+/** The function encodes 32-bit buffer into 32-bit stream by using RLE compression algorithm*/
+int BitmapCompiler::CompressThirtyTwoABitData(char*& aDest,char* aSrce,int aSizeInBytes)
+ {
+ const char* destEnd = aDest + aSizeInBytes;
+ char* srceLimitPtr = aSrce + aSizeInBytes;
+ char* srceLimitPtrMinusFour = srceLimitPtr - 4; // four bytes == one pixel
+ char* destCompressedLimitPtr = aDest + (aSizeInBytes * 7 / 8);
+ int ret = NoError;
+
+ while (aSrce < srceLimitPtrMinusFour)
+ {
+ char* runStartPtr = aSrce;
+ char component1 = *aSrce++;
+ char component2 = *aSrce++;
+ char component3 = *aSrce++;
+ char component4 = *aSrce++;
+
+ if (ColorAlphaPointerCompare(aSrce,component1,component2,component3,component4))
+ {
+ do
+ aSrce += 4;
+ while (aSrce < srceLimitPtr && ColorAlphaPointerCompare(aSrce,component1,component2,component3,component4));
+ int eqPixelLength = (aSrce - runStartPtr) / 4;
+ ret = WriteCompressedThirtyTwoABitValues(aDest,component1,component2,component3,component4,eqPixelLength,destEnd);
+ if (ret)
+ return ret;
+ }
+ else //non repeating pixel buffer
+ {
+ bool more = true;
+ bool eqRun = false;
+ do {
+ component1 = *aSrce++;
+ component2 = *aSrce++;
+ component3 = *aSrce++;
+ component4 = *aSrce++;
+ more = (aSrce < srceLimitPtr);
+ eqRun = more && ColorAlphaPointerCompare(aSrce,component1,component2,component3,component4);
+ } while (more && !eqRun);
+ if (eqRun)
+ aSrce -= 4;
+ int nePixelLength = (aSrce - runStartPtr) / 4;
+ ret = WriteCompressedThirtyTwoABitData(aDest,runStartPtr,nePixelLength,destEnd);
+ if (ret)
+ return ret;
+ }
+ if (aDest > destCompressedLimitPtr)
+ return NoCompression;
+ }
+
+ if (aSrce < srceLimitPtr)
+ {
+ ret = WriteCompressedThirtyTwoABitData(aDest,aSrce,(srceLimitPtr - aSrce) / 4, destEnd);
+ if (ret)
+ return ret;
+ }
+
+ if (aDest > destCompressedLimitPtr)
+ return NoCompression;
+ return NoError;
+ }
+
+/** The function copies non repeating 32-bit buffer to 32-bit compressed buffer*/
+int BitmapCompiler::WriteCompressedThirtyTwoABitData(char*& aDest,char* aData,
+ int aLength, const char* aDestEnd)
+ {
+ if (aLength < 1)
+ return CompressionError;
+
+ if(!CanCopy32bppData(aDest, aDestEnd, aLength))
+ return NoCompression;
+
+ while (aLength > 128)
+ {
+ *aDest++ = -128;
+ memcpy(aDest,aData,512);
+ aDest += 512;
+ aData += 512;
+ aLength -= 128;
+ }
+
+ *aDest++ = char(-aLength);
+ memcpy(aDest,aData, aLength*4);
+ aDest += aLength*4;
+ return NoError;
+ }
+
+/** The function copies repeating pixels including alpha to a 32-bit compressed buffer */
+int BitmapCompiler::WriteCompressedThirtyTwoABitValues(char*& aDest,char aComponent1,
+ char aComponent2,char aComponent3,
+ char aComponent4,int aLength,
+ const char* aDestEnd)
+
+ {
+ if (aLength < 1)
+ return CompressionError;
+
+ if(!CanWrite32bppValue(aDest, aDestEnd, aLength))
+ return NoCompression;
+ while (aLength > 128)
+ {
+ *aDest++ = 127;
+ *aDest++ = aComponent1;
+ *aDest++ = aComponent2;
+ *aDest++ = aComponent3;
+ *aDest++ = aComponent4;
+ aLength -= 128;
+ }
+
+ *aDest++ = char(aLength-1);
+ *aDest++ = aComponent1;
+ *aDest++ = aComponent2;
+ *aDest++ = aComponent3;
+ *aDest++ = aComponent4;
+
+ return NoError;
+ }
+
+int BitmapCompiler::ColorAlphaPointerCompare(char* aColorPointer,char aComponent1,char aComponent2,char aComponent3,char aComponent4)
+ {
+ return (*aColorPointer == aComponent1 && *(aColorPointer + 1) == aComponent2 && *(aColorPointer + 2) == aComponent3 && *(aColorPointer + 3) == aComponent4);
+ }
+
+int BitmapCompiler::ReadHexString(char aHexBuf[10],char*& aDataPtr,char* aDataPtrLimit)
+ {
+ while (aDataPtr < aDataPtrLimit)
+ {
+ if (aDataPtr[0] == '0')
+ {
+ if (aDataPtr[1] == 'x' || aDataPtr[1] == 'X')
+ {
+ memcpy(aHexBuf,aDataPtr,10);
+ aDataPtr += 10;
+ return NoError;
+ }
+ }
+ aDataPtr++;
+ }
+
+ return PaletteFile;
+ }
+
+int BitmapCompiler::HexToInt(char aHighNibble,char aLowNibble)
+ {
+ return (HexToInt(aHighNibble) << 4) + HexToInt(aLowNibble);
+ }
+
+int BitmapCompiler::HexToInt(char aNibble)
+ {
+ int value = 0;
+
+ if (aNibble >= '0' && aNibble <= '9')
+ value = aNibble - '0';
+ else if (aNibble >= 'a' && aNibble <= 'f')
+ value = aNibble - 'a' + 10;
+ else if (aNibble >= 'A' && aNibble <= 'F')
+ value = aNibble - 'A' + 10;
+
+ return value;
+ }
+
+void BitmapCompiler::CopyTail(void* aDst, void* aSrc, int aFullSize, int aSkipped)
+ {
+ memcpy(aDst, ((char*)aSrc)+aSkipped, aFullSize-aSkipped);
+ }