graphicstools/gdi_tools/bmconv/PBMCOMP.CPP
changeset 0 5d03bc08d59c
--- /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);
+	}