|
1 /* |
|
2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 |
|
18 #include "BMCONV.H" |
|
19 #include <stdlib.h> |
|
20 #include <ctype.h> |
|
21 #include <sys/stat.h> |
|
22 |
|
23 extern TRgb* color256Palette; |
|
24 extern char* color256InversePalette; |
|
25 |
|
26 static inline bool CanCopy16bppData(const char* aDest, const char* aDestEnd, int aDataSize) |
|
27 { |
|
28 const char* aDestNew = aDest + (aDataSize / 128) * (256 + 1) + //(2 * 128) bytes data + 1 leading byte |
|
29 (aDataSize % 128 ? (aDataSize % 128) * 2 + 1 : 0); |
|
30 return aDestNew <= aDestEnd; |
|
31 } |
|
32 |
|
33 static inline bool CanWrite16bppValue(const char* aDest, const char* aDestEnd, int aDataSize) |
|
34 { |
|
35 const char* aDestNew = aDest + (aDataSize / 128) * (2 + 1) + //2 bytes data + 1 leading byte |
|
36 (aDataSize % 128 ? 2 + 1 : 0); |
|
37 return aDestNew <= aDestEnd; |
|
38 } |
|
39 |
|
40 static inline bool CanCopy8bppData(const char* aDest, const char* aDestEnd, int aDataSize) |
|
41 { |
|
42 const char* aDestNew = aDest + (aDataSize / 128) * (128 + 1) + //128 bytes data + 1 leading byte |
|
43 (aDataSize % 128 ? (aDataSize % 128) + 1 : 0); |
|
44 return aDestNew <= aDestEnd; |
|
45 } |
|
46 |
|
47 static inline bool CanWrite8bppValue(const char* aDest, const char* aDestEnd, int aDataSize) |
|
48 { |
|
49 const char* aDestNew = aDest + (aDataSize / 128) * (1 + 1) + //1 byte data + 1 leading byte |
|
50 (aDataSize % 128 ? 1 + 1 : 0); |
|
51 return aDestNew <= aDestEnd; |
|
52 } |
|
53 |
|
54 static inline bool CanCopy24bppData(const char* aDest, const char* aDestEnd, int aDataSize) |
|
55 { |
|
56 const char* aDestNew = aDest + (aDataSize / 128) * (384 + 1) + //(128 * 3) bytes data + 1 leading byte |
|
57 (aDataSize % 128 ? (aDataSize % 128) * 3 + 1 : 0); |
|
58 return aDestNew <= aDestEnd; |
|
59 } |
|
60 |
|
61 static inline bool CanWrite24bppValue(const char* aDest, const char* aDestEnd, int aDataSize) |
|
62 { |
|
63 const char* aDestNew = aDest + (aDataSize / 128) * (3 + 1) + //3 bytes data + 1 leading byte |
|
64 (aDataSize % 128 ? 3 + 1 : 0); |
|
65 return aDestNew <= aDestEnd; |
|
66 } |
|
67 |
|
68 static inline bool CanCopy32bppData(const char* aDest, const char* aDestEnd, int aDataSize) |
|
69 { |
|
70 const char* aDestNew = aDest + (aDataSize / 128) * (512 + 1) + //(128 * 4) bytes data + 1 leading byte |
|
71 (aDataSize % 128 ? (aDataSize % 128) * 4 + 1 : 0); |
|
72 return aDestNew <= aDestEnd; |
|
73 } |
|
74 |
|
75 static inline bool CanWrite32bppValue(const char* aDest, const char* aDestEnd, int aDataSize) |
|
76 { |
|
77 const char* aDestNew = aDest + (aDataSize / 128) * (4 + 1) + //4 bytes data + 1 leading byte |
|
78 (aDataSize % 128 ? 4 + 1 : 0); |
|
79 return aDestNew <= aDestEnd; |
|
80 } |
|
81 BitmapCompiler::BitmapCompiler(TSourceFile* aSourcefilenames,int aNumSources): |
|
82 iSourcefilenames(aSourcefilenames), |
|
83 iPbmSources(NULL), |
|
84 iNumSources(aNumSources) |
|
85 {} |
|
86 |
|
87 BitmapCompiler::~BitmapCompiler() |
|
88 { |
|
89 iDestFile.close(); |
|
90 if(iPbmSources) |
|
91 for(int count=0;count<iNumSources;count++) |
|
92 delete iPbmSources[count]; |
|
93 delete [] iPbmSources; |
|
94 iPbmSources = NULL; |
|
95 } |
|
96 |
|
97 int BitmapCompiler::Compile(TStoreType aSt,int aCompress,char* aDestfilename,char* aHeaderFilename,char* aPaletteFilename) |
|
98 { |
|
99 int ret = LoadPalette(aPaletteFilename); |
|
100 if (ret) |
|
101 return ret; |
|
102 |
|
103 iDestFile.open(aDestfilename, ios::out | ios::binary); |
|
104 if(iDestFile.is_open()==0) |
|
105 return DestFile; |
|
106 if (iNumSources < 1) |
|
107 return SourceFile; |
|
108 |
|
109 if (iNumSources==1 && (iSourcefilenames[0].FileName()[0]==OPTCHAR || iSourcefilenames[0].FileName()[0]==ALTERNATE_OPTCHAR) && iSourcefilenames[0].FileName()[1]=='m') |
|
110 { |
|
111 // Source is an existing MBM file, presumably because we want to convert |
|
112 // a filestore into a ROM image. |
|
113 if (aHeaderFilename) |
|
114 { |
|
115 cout << "Header file generation is not permitted with /m or -m\n"; |
|
116 aHeaderFilename = NULL; |
|
117 } |
|
118 iSourcefilenames[0].FileName()+=2; |
|
119 EpocLoader pl; |
|
120 int romFormat; |
|
121 ret = pl.EpocBitmapCount(iSourcefilenames[0].FileName(), iNumSources, romFormat); |
|
122 if (!ret) |
|
123 ret = LoadPbmFile(iSourcefilenames[0].FileName()); |
|
124 } |
|
125 else |
|
126 { |
|
127 // Read the usual list of [OPT]bmp_n source bitmaps. |
|
128 ret = LoadSourcefiles(); |
|
129 } |
|
130 if (ret) |
|
131 return ret; |
|
132 |
|
133 ret = CreateHeader(aHeaderFilename); |
|
134 if (ret) |
|
135 return ret; |
|
136 |
|
137 if (aSt == ERomStore || aSt == ECompressedRomStore) |
|
138 ret = RomImage(aSt == ECompressedRomStore); |
|
139 else |
|
140 ret = FileImage(aCompress); |
|
141 return ret; |
|
142 }; |
|
143 |
|
144 int BitmapCompiler::AllocatePbmSourcesArray() |
|
145 { |
|
146 iPbmSources = new SEpocBitmapHeader*[iNumSources]; |
|
147 if(iPbmSources == NULL) |
|
148 return NoMemory; |
|
149 |
|
150 memset(iPbmSources,0xff,sizeof(SEpocBitmapHeader*)*iNumSources); |
|
151 int count; |
|
152 for(count=0;count<iNumSources;count++) |
|
153 iPbmSources[count]=NULL; |
|
154 return NoError; |
|
155 } |
|
156 |
|
157 int BitmapCompiler::LoadSourcefiles() |
|
158 { |
|
159 int ret = AllocatePbmSourcesArray(); |
|
160 if (ret) |
|
161 return ret; |
|
162 for(int count=0;count<iNumSources;count++) |
|
163 { |
|
164 bool useAlpha = false; |
|
165 int bpp = 2; |
|
166 TBitmapColor color = EMonochromeBitmap; |
|
167 BitmapLoader bmpload; |
|
168 if(iSourcefilenames[count].FileName()[0]==OPTCHAR || iSourcefilenames[count].FileName()[0]==ALTERNATE_OPTCHAR) |
|
169 { |
|
170 iSourcefilenames[count].FileName()++; |
|
171 if(iSourcefilenames[count].FileName()[0]=='c') |
|
172 { |
|
173 color = EColorBitmap; |
|
174 iSourcefilenames[count].FileName()++; |
|
175 } |
|
176 bpp=iSourcefilenames[count].FileName()[0]-'0'; |
|
177 iSourcefilenames[count].FileName()++; |
|
178 int next=iSourcefilenames[count].FileName()[0]-'0'; |
|
179 if(next==2 || next==6 || next==4) |
|
180 { |
|
181 bpp=bpp*10+next; |
|
182 iSourcefilenames[count].FileName()++; |
|
183 } |
|
184 if(iSourcefilenames[count].FileName()[0]=='a') |
|
185 { |
|
186 useAlpha = true; |
|
187 iSourcefilenames[count].FileName()++; |
|
188 if (color!=EColorBitmap || bpp!=32) |
|
189 return Bpp; |
|
190 } |
|
191 if (color == EColorBitmap && bpp!=4 && bpp!=8 && bpp!=12 && bpp!=16 && bpp!=24 && bpp!=32) |
|
192 return Bpp; |
|
193 if (color == EMonochromeBitmap && bpp!=1 && bpp!=2 && bpp!=4 && bpp!=8) |
|
194 return Bpp; |
|
195 } |
|
196 if (color == EColorBitmap && useAlpha) |
|
197 color = EColorBitmapAlpha; |
|
198 ret = bmpload.LoadBitmap(iSourcefilenames[count],bpp,color,iPbmSources[count]); |
|
199 if (ret) |
|
200 return ret; |
|
201 } |
|
202 return NoError; |
|
203 } |
|
204 |
|
205 int BitmapCompiler::LoadPbmFile(char* aPbmFilename) |
|
206 { |
|
207 int ret = AllocatePbmSourcesArray(); |
|
208 if (ret) |
|
209 return ret; |
|
210 for(int count=0;count<iNumSources;count++) |
|
211 { |
|
212 EpocLoader pl; |
|
213 ret = pl.LoadEpocBitmap(aPbmFilename,count); |
|
214 if (!ret) |
|
215 ret = pl.DupBitmap(iPbmSources[count]); |
|
216 if (ret) |
|
217 return ret; |
|
218 } |
|
219 return NoError; |
|
220 } |
|
221 |
|
222 int BitmapCompiler::RomImage(bool aCompress) |
|
223 { |
|
224 int count=0; |
|
225 |
|
226 if (aCompress) |
|
227 { |
|
228 for(; count<iNumSources; count++) |
|
229 { |
|
230 int ret = CompressBitmap(iPbmSources[count]); |
|
231 if (ret) |
|
232 return ret; |
|
233 } |
|
234 } |
|
235 |
|
236 int ret = WriteRomheader(); |
|
237 if (ret) |
|
238 return ret; |
|
239 |
|
240 for(count=0;count<iNumSources;count++) |
|
241 { |
|
242 ret = WriteRombitmap(iPbmSources[count]); |
|
243 if (ret) |
|
244 return ret; |
|
245 } |
|
246 return NoError; |
|
247 } |
|
248 |
|
249 int BitmapCompiler::FileImage(int aCompress) |
|
250 { |
|
251 int count = 0; |
|
252 if(aCompress) |
|
253 { |
|
254 for(;count<iNumSources;count++) |
|
255 { |
|
256 int ret = CompressBitmap(iPbmSources[count]); |
|
257 if(ret) |
|
258 return ret; |
|
259 } |
|
260 } |
|
261 int ret = WriteFileheader(); |
|
262 if (ret) |
|
263 return ret; |
|
264 for (count=0;count<iNumSources;count++) |
|
265 { |
|
266 ret = WriteFilebitmap(iPbmSources[count]); |
|
267 if (ret) |
|
268 return ret; |
|
269 } |
|
270 ret = WriteHeadStream(); |
|
271 return ret; |
|
272 } |
|
273 |
|
274 int BitmapCompiler::WriteRomheader() |
|
275 { |
|
276 iDestFile.write((char*)&KMultiBitmapRomImageUid,4); |
|
277 iDestFile.write((char*)&iNumSources,4); |
|
278 int byteswritten=8+(iNumSources*4); |
|
279 for (int count=0;count<iNumSources;count++) |
|
280 { |
|
281 iDestFile.write((char*)&byteswritten,4); |
|
282 byteswritten+=(((iPbmSources[count]->iBitmapSize)+3)/4*4)-sizeof(SEpocBitmapHeader)+sizeof(Bitmap); |
|
283 } |
|
284 return NoError; |
|
285 } |
|
286 |
|
287 int BitmapCompiler::WriteRombitmap(SEpocBitmapHeader* aPbm) |
|
288 { |
|
289 if (aPbm->iPaletteEntries != 0) |
|
290 return PaletteSupportNotImplemented; |
|
291 |
|
292 int bitmapsize = aPbm->iBitmapSize-sizeof(SEpocBitmapHeader)+sizeof(Bitmap); |
|
293 bitmapsize = ((bitmapsize+3)/4)*4; |
|
294 |
|
295 char* buffer = new char[bitmapsize]; |
|
296 if (buffer == NULL) |
|
297 return NoMemory; |
|
298 memset(buffer,0xff,bitmapsize); |
|
299 |
|
300 Bitmap* bmp = (Bitmap*)buffer; |
|
301 bmp->iUid=KCBitwiseBitmapUid; |
|
302 TBitmapColor color = aPbm->iColor; |
|
303 |
|
304 switch(aPbm->iBitsPerPixel) |
|
305 { // for corresponding enums, see TDisplayMode in <gdi.h> |
|
306 case 1: |
|
307 bmp->iDispMode=1; |
|
308 break; |
|
309 case 2: |
|
310 bmp->iDispMode=2; |
|
311 break; |
|
312 case 4: |
|
313 if (color == EMonochromeBitmap) |
|
314 bmp->iDispMode=3; |
|
315 else |
|
316 bmp->iDispMode=5; |
|
317 break; |
|
318 case 8: |
|
319 if (color == EMonochromeBitmap) |
|
320 bmp->iDispMode=4; |
|
321 else |
|
322 bmp->iDispMode=6; |
|
323 break; |
|
324 case 12: |
|
325 bmp->iDispMode=10; |
|
326 break; |
|
327 case 16: |
|
328 bmp->iDispMode=7; |
|
329 break; |
|
330 case 24: |
|
331 bmp->iDispMode=8; |
|
332 break; |
|
333 case 32: |
|
334 if (color == EColorBitmapAlpha) |
|
335 bmp->iDispMode=12; // Color16MA |
|
336 else |
|
337 bmp->iDispMode=11; // Color16MU |
|
338 break; |
|
339 default: |
|
340 delete [] buffer; |
|
341 return SourceFile; |
|
342 } |
|
343 |
|
344 bmp->iHeap = NULL; |
|
345 bmp->iPile = NULL; |
|
346 bmp->iHeader = *aPbm; |
|
347 bmp->iByteWidth = BitmapUtils::ByteWidth(bmp->iHeader.iWidthInPixels,bmp->iHeader.iBitsPerPixel); |
|
348 bmp->iDataOffset = sizeof(Bitmap); |
|
349 |
|
350 CopyTail(buffer + sizeof(Bitmap), aPbm, aPbm->iBitmapSize, sizeof(SEpocBitmapHeader)); |
|
351 iDestFile.write(buffer,bitmapsize); |
|
352 |
|
353 delete [] buffer; |
|
354 |
|
355 return NoError; |
|
356 } |
|
357 |
|
358 int BitmapCompiler::WriteFileheader() |
|
359 { |
|
360 int zero=0; |
|
361 iDestFile.write((char*)&KWriteOnceFileStoreUid,4); |
|
362 iDestFile.write((char*)&KMultiBitmapFileImageUid,4); |
|
363 iDestFile.write((char*)&zero,4); |
|
364 iDestFile.write((char*)&KMultiBitmapFileImageChecksum,4); |
|
365 int byteswritten=16; |
|
366 for(int count=0;count<iNumSources;count++) |
|
367 { |
|
368 byteswritten+=iPbmSources[count]->iBitmapSize; |
|
369 } |
|
370 byteswritten+=4; |
|
371 iDestFile.write((char*)&byteswritten,4); |
|
372 return NoError; |
|
373 } |
|
374 |
|
375 int BitmapCompiler::WriteHeadStream() |
|
376 { |
|
377 iDestFile.write((char*)&iNumSources,4); |
|
378 int byteswritten=20; |
|
379 for(int count=0;count<iNumSources;count++) |
|
380 { |
|
381 iDestFile.write((char*)&byteswritten,4); |
|
382 byteswritten+=iPbmSources[count]->iBitmapSize; |
|
383 } |
|
384 return NoError; |
|
385 } |
|
386 |
|
387 int BitmapCompiler::WriteFilebitmap(SEpocBitmapHeader* aPbm) |
|
388 { |
|
389 if (aPbm->iPaletteEntries != 0) |
|
390 return PaletteSupportNotImplemented; |
|
391 |
|
392 int dataSize = aPbm->iBitmapSize - sizeof(SEpocBitmapHeader); |
|
393 |
|
394 iDestFile.write((char*)(aPbm),sizeof(SEpocBitmapHeader)); |
|
395 // WritePalette() |
|
396 iDestFile.write(((char*)(aPbm)) + sizeof(SEpocBitmapHeader),dataSize); |
|
397 |
|
398 return NoError; |
|
399 } |
|
400 |
|
401 void BitmapCompiler::WritePalette() |
|
402 { |
|
403 for (int index = 0; index < 256; index++) |
|
404 { |
|
405 iDestFile.write((char*)(&iPalette[index]),3); |
|
406 } |
|
407 } |
|
408 |
|
409 int BitmapCompiler::LoadPalette(char* aPaletteFilename) |
|
410 { |
|
411 if (!aPaletteFilename) |
|
412 { |
|
413 iDefaultPalette = 1; |
|
414 return NoError; |
|
415 } |
|
416 |
|
417 iDefaultPalette = 0; |
|
418 color256Palette = iPalette; |
|
419 color256InversePalette = iInversePalette; |
|
420 |
|
421 struct stat fileinfo; |
|
422 if (stat(aPaletteFilename,&fileinfo)==-1) |
|
423 return CommandFile; |
|
424 |
|
425 int filesize = fileinfo.st_size; |
|
426 if (filesize == 0) |
|
427 return PaletteFile; |
|
428 |
|
429 #if defined(__MSVCDOTNET__) || defined(__TOOLS2__) || defined(__CW32__) |
|
430 fstream paletteFile(aPaletteFilename, ios::in | ios::binary); |
|
431 #else |
|
432 fstream paletteFile(aPaletteFilename, ios::in | ios::binary | ios::nocreate); |
|
433 #endif |
|
434 |
|
435 if(!paletteFile.is_open()) |
|
436 return PaletteFile; |
|
437 |
|
438 char* paletteData = new char[filesize]; |
|
439 if (!paletteData) |
|
440 return NoMemory; |
|
441 |
|
442 memset(paletteData,0,filesize); |
|
443 paletteFile.read(paletteData,filesize); |
|
444 paletteFile.close(); |
|
445 |
|
446 char* dataPtr = (char*)paletteData; |
|
447 char* dataPtrLimit = dataPtr + filesize; |
|
448 |
|
449 for (int index = 0; index < 256; index++) |
|
450 { |
|
451 char hexBuf[10]; |
|
452 int ret = ReadHexString(hexBuf,dataPtr,dataPtrLimit); |
|
453 if (ret) |
|
454 { |
|
455 delete paletteData; |
|
456 return ret; |
|
457 } |
|
458 |
|
459 int red = HexToInt(hexBuf[8],hexBuf[9]); |
|
460 int green = HexToInt(hexBuf[6],hexBuf[7]); |
|
461 int blue = HexToInt(hexBuf[4],hexBuf[5]); |
|
462 |
|
463 iPalette[index] = TRgb(red,green,blue); |
|
464 } |
|
465 |
|
466 delete paletteData; |
|
467 CalculateInversePalette(); |
|
468 return NoError; |
|
469 } |
|
470 |
|
471 void BitmapCompiler::CalculateInversePalette() |
|
472 { |
|
473 for (int index = 0; index < 4096; index++) |
|
474 { |
|
475 TRgb color = TRgb((index & 0x00f) * 17,((index & 0x0f0) >> 4) * 17,((index & 0xf00) >> 8) * 17); |
|
476 |
|
477 int nearest = 0; |
|
478 int distance = iPalette[0].Difference(color); |
|
479 |
|
480 for (int paletteIndex = 0; paletteIndex < 256; paletteIndex++) |
|
481 { |
|
482 TRgb paletteColor = iPalette[paletteIndex]; |
|
483 |
|
484 if (paletteColor == color) |
|
485 { |
|
486 nearest = paletteIndex; |
|
487 break; |
|
488 } |
|
489 |
|
490 int paletteDistance = paletteColor.Difference(color); |
|
491 if (paletteDistance < distance) |
|
492 { |
|
493 nearest = paletteIndex; |
|
494 distance = paletteDistance; |
|
495 } |
|
496 } |
|
497 |
|
498 iInversePalette[index] = (char)nearest; |
|
499 TRgb palColor = iPalette[nearest]; |
|
500 color = palColor; |
|
501 } |
|
502 } |
|
503 |
|
504 int BitmapCompiler::CreateHeader(char* aHeaderFilename) |
|
505 { |
|
506 if (!aHeaderFilename) |
|
507 return NoError; |
|
508 |
|
509 fstream hf(aHeaderFilename,ios::out); |
|
510 if(!hf.is_open()) |
|
511 return DestFile; |
|
512 |
|
513 char* basename = strrchr(aHeaderFilename,'\\'); |
|
514 if (basename==0) |
|
515 basename = aHeaderFilename; |
|
516 else |
|
517 basename++; // skip directory separator |
|
518 |
|
519 char unadornedFile[256]; |
|
520 strcpy(unadornedFile, UnadornedName(aHeaderFilename)); |
|
521 |
|
522 hf << "// " << basename << "\n"; |
|
523 hf << "// Generated by BitmapCompiler\n"; |
|
524 hf << "// Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.\n"; |
|
525 hf << "//\n\n"; |
|
526 hf << "enum TMbm" << unadornedFile << "\n"; |
|
527 hf << "\t{\n"; |
|
528 |
|
529 for (int count=0;count<iNumSources;count++) |
|
530 { |
|
531 char* unadornedSourceFileName = UnadornedName(iSourcefilenames[count].FileName()); |
|
532 // Strip "_mask_soft" suffix to plain "_mask" |
|
533 if( (strlen(unadornedSourceFileName)>10) && |
|
534 (strcmp( unadornedSourceFileName + strlen(unadornedSourceFileName) - 10, |
|
535 "_mask_soft" ) == 0) ) |
|
536 { |
|
537 unadornedSourceFileName[ strlen(unadornedSourceFileName) - 5 ] = '\0'; |
|
538 } |
|
539 hf << "\tEMbm" << unadornedFile << unadornedSourceFileName; |
|
540 if(count<iNumSources-1) |
|
541 hf << ','; |
|
542 hf << '\n'; |
|
543 } |
|
544 hf << "\t};\n"; |
|
545 hf.close(); |
|
546 return NoError; |
|
547 } |
|
548 |
|
549 char* BitmapCompiler::UnadornedName(char* aName) |
|
550 { |
|
551 int len = strlen(aName); |
|
552 |
|
553 char* foundDir = strrchr(aName,'\\'); |
|
554 char* foundUrl = strrchr(aName,'/'); |
|
555 char* foundExt = strrchr(aName,'.'); |
|
556 |
|
557 char* foundPath = (foundDir > foundUrl) ? foundDir : foundUrl; |
|
558 char* firstchar = (foundPath > (char*)0) ? (char*)(foundPath + 1) : aName; |
|
559 char* lastchar = (foundExt > firstchar) ? foundExt : aName+len; |
|
560 |
|
561 static char result[256]; |
|
562 if (lastchar-firstchar > 255) |
|
563 { |
|
564 strcpy(result,"NameTooLong"); |
|
565 return result; |
|
566 } |
|
567 int i=0; |
|
568 result[0] = (char)toupper(*firstchar); |
|
569 firstchar+=1; |
|
570 for (i=1; firstchar<lastchar; i++,firstchar++) |
|
571 { |
|
572 result[i] = (char)tolower(*firstchar); |
|
573 } |
|
574 result[i] = '\0'; |
|
575 return result; |
|
576 } |
|
577 |
|
578 int BitmapCompiler::CompressBitmap(SEpocBitmapHeader*& aPbm) |
|
579 { |
|
580 int originalsize = aPbm->iBitmapSize-sizeof(SEpocBitmapHeader); |
|
581 char* newbits=new char[originalsize+sizeof(SEpocBitmapHeader)]; |
|
582 if(!newbits) |
|
583 return NoMemory; |
|
584 |
|
585 memset(newbits,0xff,sizeof(SEpocBitmapHeader)+originalsize); |
|
586 memcpy(newbits,aPbm,sizeof(SEpocBitmapHeader)); |
|
587 char* newbitsptr=newbits+sizeof(SEpocBitmapHeader); |
|
588 char* oldbits=((char*)(aPbm))+sizeof(SEpocBitmapHeader); |
|
589 |
|
590 TBitmapfileCompression compression = ENoBitmapCompression; |
|
591 int ret = NoCompression; |
|
592 |
|
593 if (aPbm->iBitsPerPixel <= 8) |
|
594 { |
|
595 compression = EByteRLECompression; |
|
596 ret = CompressByteData(newbitsptr,oldbits,originalsize); |
|
597 } |
|
598 else if (aPbm->iBitsPerPixel == 12) |
|
599 { |
|
600 compression = ETwelveBitRLECompression; |
|
601 ret = CompressTwelveBitData(newbitsptr,oldbits,originalsize); |
|
602 } |
|
603 else if (aPbm->iBitsPerPixel == 16) |
|
604 { |
|
605 compression = ESixteenBitRLECompression; |
|
606 ret = CompressSixteenBitData(newbitsptr,oldbits,originalsize); |
|
607 } |
|
608 else if (aPbm->iBitsPerPixel == 24) |
|
609 { |
|
610 compression = ETwentyFourBitRLECompression; |
|
611 ret = CompressTwentyFourBitData(newbitsptr,oldbits,originalsize); |
|
612 } |
|
613 else if (aPbm->iBitsPerPixel == 32 && (aPbm->iColor == EColorBitmap)) |
|
614 { |
|
615 compression = EThirtyTwoUBitRLECompression; |
|
616 ret = CompressThirtyTwoUBitData(newbitsptr,oldbits,originalsize); |
|
617 } |
|
618 else if (aPbm->iBitsPerPixel == 32 && (aPbm->iColor == EColorBitmapAlpha)) |
|
619 { |
|
620 compression = EThirtyTwoABitRLECompression; |
|
621 ret = CompressThirtyTwoABitData(newbitsptr,oldbits,originalsize); |
|
622 } |
|
623 |
|
624 if(ret) |
|
625 { |
|
626 delete [] newbits; |
|
627 if(ret>0) |
|
628 return ret; |
|
629 return NoError; |
|
630 } |
|
631 |
|
632 delete aPbm; |
|
633 aPbm = (SEpocBitmapHeader*)newbits; |
|
634 aPbm->iBitmapSize = newbitsptr-(newbits+sizeof(SEpocBitmapHeader))+sizeof(SEpocBitmapHeader); |
|
635 aPbm->iCompression = compression; |
|
636 return NoError; |
|
637 } |
|
638 |
|
639 int BitmapCompiler::CompressByteData(char*& aDest,char* aSrce,int aSize) |
|
640 { |
|
641 const char* destEnd = aDest + aSize; |
|
642 char* bytepointer=aSrce; |
|
643 char* limitpointer=bytepointer+aSize; |
|
644 int margin = (aSize>>6); |
|
645 char* limitmargin = limitpointer - ((margin > 4) ? margin : 4); |
|
646 char* cutoffpointer=aDest+(aSize>>1)+(aSize>>2); |
|
647 int ret=NoError; |
|
648 char* oldbytepointer=NULL; |
|
649 while(bytepointer<limitmargin) |
|
650 { |
|
651 char value=*bytepointer; |
|
652 if(*(bytepointer+1)==value && *(bytepointer+2)==value) |
|
653 { |
|
654 oldbytepointer=bytepointer; |
|
655 bytepointer+=3; |
|
656 while ( ( bytepointer < limitmargin ) && ( *bytepointer == value ) ) |
|
657 bytepointer++; |
|
658 ret = WriteCompressedByteValues(aDest,value,bytepointer-oldbytepointer, destEnd); |
|
659 if(ret) return ret; |
|
660 } |
|
661 else |
|
662 { |
|
663 oldbytepointer=bytepointer; |
|
664 while((bytepointer<limitmargin) && (*(bytepointer+1)!=value || *(bytepointer+2)!=value)) |
|
665 { |
|
666 bytepointer++; |
|
667 value=*bytepointer; |
|
668 } |
|
669 ret = WriteCompressedByteData(aDest,oldbytepointer,bytepointer-oldbytepointer, destEnd); |
|
670 if(ret) return ret; |
|
671 } |
|
672 if(aDest>cutoffpointer) |
|
673 return NoCompression; |
|
674 } |
|
675 |
|
676 int remaining = limitpointer-bytepointer; |
|
677 if(remaining > 0) |
|
678 { |
|
679 if (aDest + remaining > cutoffpointer) |
|
680 return NoCompression; |
|
681 ret=WriteCompressedByteData(aDest,bytepointer,remaining, destEnd); |
|
682 if(ret) return ret; |
|
683 } |
|
684 return NoError; |
|
685 } |
|
686 |
|
687 int BitmapCompiler::WriteCompressedByteData(char*& aDest,char* aData,int aLength, const char* aDestEnd) |
|
688 { |
|
689 if(!CanCopy8bppData(aDest, aDestEnd, aLength)) |
|
690 return NoCompression; |
|
691 while(aLength>128) |
|
692 { |
|
693 *aDest++=-128; |
|
694 for(int count=0;count<128;count++) |
|
695 *aDest++=*aData++; |
|
696 aLength-=128; |
|
697 } |
|
698 if(aLength>128 || aLength<1) return CompressionError; |
|
699 *aDest++=char(-aLength); |
|
700 for(int count=0;count<aLength;count++) |
|
701 *aDest++=*aData++; |
|
702 return NoError; |
|
703 } |
|
704 |
|
705 int BitmapCompiler::WriteCompressedByteValues(char*& aDest,char aValue,int aLength, const char* aDestEnd) |
|
706 { |
|
707 if (aLength < 1) |
|
708 return CompressionError; |
|
709 |
|
710 if(!CanWrite8bppValue(aDest, aDestEnd, aLength)) |
|
711 return NoCompression; |
|
712 |
|
713 while (aLength > 128) |
|
714 { |
|
715 *aDest++ = 127; |
|
716 *aDest++ = aValue; |
|
717 aLength -= 128; |
|
718 } |
|
719 |
|
720 *aDest++ = char(aLength-1); |
|
721 *aDest++ = aValue; |
|
722 |
|
723 return NoError; |
|
724 } |
|
725 |
|
726 int BitmapCompiler::CompressTwelveBitData(char*& aDest,char* aSrce,int aSizeInBytes) |
|
727 { |
|
728 unsigned short* srcePtr = (unsigned short*)aSrce; |
|
729 unsigned short* srceLimitPtr = srcePtr + (aSizeInBytes / 2); |
|
730 unsigned short* dest = (unsigned short*)aDest; |
|
731 |
|
732 while (srcePtr < srceLimitPtr) |
|
733 { |
|
734 unsigned short* runStartPtr = srcePtr; |
|
735 unsigned short value = *srcePtr; |
|
736 do |
|
737 srcePtr++; |
|
738 while (srcePtr < srceLimitPtr && *srcePtr == value); |
|
739 WriteCompressedTwelveBitData(dest,*runStartPtr,srcePtr - runStartPtr); // Ignore error return as 12bpp compression never fails |
|
740 } |
|
741 |
|
742 aDest = (char*)dest; |
|
743 return NoError; |
|
744 } |
|
745 |
|
746 int BitmapCompiler::WriteCompressedTwelveBitData(unsigned short*& aDest,unsigned short aData,int aLength) |
|
747 { |
|
748 // The run length l is stored as l-1 in the top 4 bits of each 16-bit word (between 1 and 16) |
|
749 aData &= 0x0fff; |
|
750 unsigned short maxLengthData = (unsigned short)(aData | 0xf000); |
|
751 |
|
752 while(aLength>16) |
|
753 { |
|
754 *aDest++ = maxLengthData; |
|
755 aLength -= 16; |
|
756 } |
|
757 |
|
758 if (aLength > 0) |
|
759 *aDest++ = (unsigned short)(aData | ((aLength - 1) << 12)); |
|
760 |
|
761 return NoError; |
|
762 } |
|
763 |
|
764 int BitmapCompiler::CompressSixteenBitData(char*& aDest,char* aSrce,int aSizeInBytes) |
|
765 { |
|
766 char* destEnd = aDest + aSizeInBytes; |
|
767 unsigned short* srcePtr = (unsigned short*)aSrce; |
|
768 unsigned short* srceLimitPtr = srcePtr + (aSizeInBytes / 2); |
|
769 unsigned short* srceLimitPtrMinusOne = srceLimitPtr - 1; |
|
770 char* destCompressedLimitPtr = aDest + (aSizeInBytes * 7 / 8); |
|
771 int ret = NoError; |
|
772 |
|
773 while (srcePtr < srceLimitPtrMinusOne) |
|
774 { |
|
775 unsigned short value = *srcePtr; |
|
776 unsigned short* runStartPtr = srcePtr++; |
|
777 |
|
778 if(*srcePtr == value) |
|
779 { |
|
780 do |
|
781 srcePtr++; |
|
782 while ( ( srcePtr < srceLimitPtr ) && ( *srcePtr == value ) ); |
|
783 |
|
784 ret = WriteCompressedSixteenBitValues(aDest,value,srcePtr-runStartPtr, destEnd); |
|
785 if (ret) |
|
786 return ret; |
|
787 } |
|
788 else |
|
789 { |
|
790 value = *srcePtr; |
|
791 while (srcePtr < srceLimitPtrMinusOne && *(srcePtr + 1) != value) |
|
792 { |
|
793 srcePtr++; |
|
794 value = *srcePtr; |
|
795 } |
|
796 |
|
797 ret = WriteCompressedSixteenBitData(aDest,runStartPtr,srcePtr - runStartPtr, destEnd); |
|
798 if (ret) |
|
799 return ret; |
|
800 } |
|
801 if (aDest > destCompressedLimitPtr) |
|
802 return NoCompression; |
|
803 } |
|
804 |
|
805 if (srcePtr < srceLimitPtr) |
|
806 { |
|
807 ret = WriteCompressedSixteenBitData(aDest,srcePtr,srceLimitPtr - srcePtr, destEnd); |
|
808 if (ret) |
|
809 return ret; |
|
810 } |
|
811 |
|
812 if (aDest > destCompressedLimitPtr) |
|
813 return NoCompression; |
|
814 return NoError; |
|
815 } |
|
816 |
|
817 int BitmapCompiler::WriteCompressedSixteenBitData(char*& aDest,unsigned short* aData, |
|
818 int aLength, const char* aDestEnd) |
|
819 { |
|
820 if (aLength < 1) |
|
821 return CompressionError; |
|
822 |
|
823 if(!CanCopy16bppData(aDest, aDestEnd, aLength)) |
|
824 return NoCompression; |
|
825 |
|
826 char* srcePtr = (char*)aData; |
|
827 |
|
828 while (aLength > 128) |
|
829 { |
|
830 *aDest++ = -128; |
|
831 memcpy(aDest,srcePtr,256); |
|
832 aDest += 256; |
|
833 srcePtr += 256; |
|
834 aLength -= 128; |
|
835 } |
|
836 |
|
837 *aDest++ = char(-aLength); |
|
838 |
|
839 int remainingBytes = aLength * 2; |
|
840 memcpy(aDest,srcePtr,remainingBytes); |
|
841 aDest += remainingBytes; |
|
842 |
|
843 return NoError; |
|
844 } |
|
845 |
|
846 int BitmapCompiler::WriteCompressedSixteenBitValues(char*& aDest,unsigned short aValue, |
|
847 int aLength, const char* aDestEnd) |
|
848 { |
|
849 if (aLength < 1) |
|
850 return CompressionError; |
|
851 |
|
852 if(!CanWrite16bppValue(aDest, aDestEnd, aLength)) |
|
853 return NoCompression; |
|
854 |
|
855 char lowByte = char(aValue); |
|
856 char highByte = char(aValue >> 8); |
|
857 |
|
858 while (aLength > 128) |
|
859 { |
|
860 *aDest++ = 127; |
|
861 *aDest++ = lowByte; |
|
862 *aDest++ = highByte; |
|
863 aLength -= 128; |
|
864 } |
|
865 |
|
866 *aDest++ = char(aLength-1); |
|
867 *aDest++ = lowByte; |
|
868 *aDest++ = highByte; |
|
869 |
|
870 return NoError; |
|
871 } |
|
872 |
|
873 int BitmapCompiler::CompressTwentyFourBitData(char*& aDest,char* aSrce,int aSizeInBytes) |
|
874 { |
|
875 const char* destEnd = aDest + aSizeInBytes; |
|
876 char* srceLimitPtr = aSrce + aSizeInBytes; |
|
877 char* srceLimitPtrMinusThree = srceLimitPtr - 3; // three bytes == one pixel |
|
878 char* destCompressedLimitPtr = aDest + (aSizeInBytes * 7 / 8); |
|
879 int ret = NoError; |
|
880 |
|
881 while (aSrce < srceLimitPtrMinusThree) |
|
882 { |
|
883 char* runStartPtr = aSrce; |
|
884 char component1 = *aSrce++; |
|
885 char component2 = *aSrce++; |
|
886 char component3 = *aSrce++; |
|
887 |
|
888 if (TrueColorPointerCompare(aSrce,component1,component2,component3)) |
|
889 { |
|
890 do |
|
891 aSrce += 3; |
|
892 while (aSrce < srceLimitPtr && TrueColorPointerCompare(aSrce,component1,component2,component3)); |
|
893 |
|
894 ret = WriteCompressedTwentyFourBitValues(aDest,component1,component2,component3,(aSrce - runStartPtr) / 3, destEnd); |
|
895 if (ret) |
|
896 return ret; |
|
897 } |
|
898 else |
|
899 { |
|
900 bool more = true; |
|
901 bool eqRun = false; |
|
902 do |
|
903 { |
|
904 component1 = *aSrce++; |
|
905 component2 = *aSrce++; |
|
906 component3 = *aSrce++; |
|
907 more = (aSrce < srceLimitPtr); |
|
908 eqRun = more && TrueColorPointerCompare(aSrce,component1,component2,component3); |
|
909 } |
|
910 while (more && !eqRun); |
|
911 if (eqRun) |
|
912 aSrce -= 3; |
|
913 int pixelLength = (aSrce - runStartPtr) / 3; |
|
914 ret = WriteCompressedTwentyFourBitData(aDest,runStartPtr,pixelLength,destEnd); |
|
915 if (ret) |
|
916 return ret; |
|
917 } |
|
918 if (aDest > destCompressedLimitPtr) |
|
919 return NoCompression; |
|
920 } |
|
921 |
|
922 if (aSrce < srceLimitPtr) |
|
923 { |
|
924 ret = WriteCompressedTwentyFourBitData(aDest,aSrce,(srceLimitPtr - aSrce) / 3, destEnd); |
|
925 if (ret) |
|
926 return ret; |
|
927 } |
|
928 |
|
929 if (aDest > destCompressedLimitPtr) |
|
930 return NoCompression; |
|
931 return NoError; |
|
932 } |
|
933 |
|
934 int BitmapCompiler::WriteCompressedTwentyFourBitData(char*& aDest,char* aData, |
|
935 int aLength, const char* aDestEnd) |
|
936 { |
|
937 if (aLength < 1) |
|
938 return CompressionError; |
|
939 |
|
940 if(!CanCopy24bppData(aDest, aDestEnd, aLength)) |
|
941 return NoCompression; |
|
942 |
|
943 while (aLength > 128) |
|
944 { |
|
945 *aDest++ = -128; |
|
946 memcpy(aDest,aData,384); |
|
947 aDest += 384; |
|
948 aData += 384; |
|
949 aLength -= 128; |
|
950 } |
|
951 |
|
952 *aDest++ = char(-aLength); |
|
953 |
|
954 int remainingBytes = aLength * 3; |
|
955 memcpy(aDest,aData,remainingBytes); |
|
956 aDest += remainingBytes; |
|
957 |
|
958 return NoError; |
|
959 } |
|
960 |
|
961 int BitmapCompiler::WriteCompressedTwentyFourBitValues(char*& aDest,char aComponent1, |
|
962 char aComponent2,char aComponent3, |
|
963 int aLength, const char* aDestEnd) |
|
964 { |
|
965 if (aLength < 1) |
|
966 return CompressionError; |
|
967 |
|
968 if(!CanWrite24bppValue(aDest, aDestEnd, aLength)) |
|
969 return NoCompression; |
|
970 |
|
971 while (aLength > 128) |
|
972 { |
|
973 *aDest++ = 127; |
|
974 *aDest++ = aComponent1; |
|
975 *aDest++ = aComponent2; |
|
976 *aDest++ = aComponent3; |
|
977 aLength -= 128; |
|
978 } |
|
979 |
|
980 *aDest++ = char(aLength-1); |
|
981 *aDest++ = aComponent1; |
|
982 *aDest++ = aComponent2; |
|
983 *aDest++ = aComponent3; |
|
984 |
|
985 return NoError; |
|
986 } |
|
987 |
|
988 /** The function encodes 32-bit buffer into 24-bit stream by using RLE compression algorithm*/ |
|
989 int BitmapCompiler::CompressThirtyTwoUBitData(char*& aDest,char* aSrce,int aSizeInBytes) |
|
990 { |
|
991 const char* destEnd = aDest + aSizeInBytes; |
|
992 char* srceLimitPtr = aSrce + aSizeInBytes; |
|
993 char* srceLimitPtrMinusFour = srceLimitPtr - 4; // four bytes == one pixel |
|
994 char* destCompressedLimitPtr = aDest + (aSizeInBytes * 7 / 8); |
|
995 int ret = NoError; |
|
996 |
|
997 while (aSrce < srceLimitPtrMinusFour) |
|
998 { |
|
999 char* runStartPtr = aSrce; |
|
1000 char component1 = *aSrce++; |
|
1001 char component2 = *aSrce++; |
|
1002 char component3 = *aSrce++; |
|
1003 aSrce++; |
|
1004 |
|
1005 if (TrueColorPointerCompare(aSrce,component1,component2,component3)) |
|
1006 { |
|
1007 do |
|
1008 aSrce += 4; |
|
1009 while (aSrce < srceLimitPtr && TrueColorPointerCompare(aSrce,component1,component2,component3)); |
|
1010 |
|
1011 ret = WriteCompressedThirtyTwoUBitValues(aDest,component1,component2,component3,(aSrce - runStartPtr) / 4, destEnd); |
|
1012 if (ret) |
|
1013 return ret; |
|
1014 } |
|
1015 else //non repeating pixel buffer |
|
1016 { |
|
1017 bool more = true; |
|
1018 bool eqRun = false; |
|
1019 do { |
|
1020 component1 = *aSrce++; |
|
1021 component2 = *aSrce++; |
|
1022 component3 = *aSrce++; |
|
1023 aSrce++; //last byte is unused (no alpha component) |
|
1024 more = (aSrce < srceLimitPtr); |
|
1025 eqRun = more && TrueColorPointerCompare(aSrce,component1,component2,component3); |
|
1026 } while (more && !eqRun); |
|
1027 if (eqRun) |
|
1028 aSrce -= 4; |
|
1029 int pixelLength = (aSrce - runStartPtr) / 4; |
|
1030 ret = WriteCompressedThirtyTwoUBitData(aDest,runStartPtr,pixelLength,destEnd); |
|
1031 if (ret) |
|
1032 return ret; |
|
1033 } |
|
1034 if (aDest > destCompressedLimitPtr) |
|
1035 return NoCompression; |
|
1036 } |
|
1037 |
|
1038 if (aSrce < srceLimitPtr) |
|
1039 { |
|
1040 ret = WriteCompressedThirtyTwoUBitData(aDest,aSrce,(srceLimitPtr - aSrce) / 4, destEnd); |
|
1041 if (ret) |
|
1042 return ret; |
|
1043 } |
|
1044 |
|
1045 if (aDest > destCompressedLimitPtr) |
|
1046 return NoCompression; |
|
1047 return NoError; |
|
1048 } |
|
1049 |
|
1050 /** The function copies non repeating 32-bit buffer to 24-bit compressed buffer*/ |
|
1051 int BitmapCompiler::WriteCompressedThirtyTwoUBitData(char*& aDest,char* aData, |
|
1052 int aLength, const char* aDestEnd) |
|
1053 { |
|
1054 if (aLength < 1) |
|
1055 return CompressionError; |
|
1056 |
|
1057 if(!CanCopy24bppData(aDest, aDestEnd, aLength)) |
|
1058 return NoCompression; |
|
1059 |
|
1060 while (aLength > 128) |
|
1061 { |
|
1062 *aDest++ = -128; |
|
1063 for(int ii = 0; ii < 128; ii++) |
|
1064 { |
|
1065 memcpy(aDest,aData, 3); |
|
1066 aDest += 3; |
|
1067 aData += 4; |
|
1068 } |
|
1069 aLength -= 128; |
|
1070 } |
|
1071 |
|
1072 *aDest++ = char(-aLength); |
|
1073 |
|
1074 while(aLength--) |
|
1075 { |
|
1076 memcpy(aDest,aData, 3); |
|
1077 aDest += 3; |
|
1078 aData += 4; |
|
1079 } |
|
1080 |
|
1081 return NoError; |
|
1082 } |
|
1083 |
|
1084 /** The function copies repeating colour to the 24-bit compressed buffer */ |
|
1085 int BitmapCompiler::WriteCompressedThirtyTwoUBitValues(char*& aDest,char aComponent1, |
|
1086 char aComponent2,char aComponent3, |
|
1087 int aLength, const char* aDestEnd) |
|
1088 { |
|
1089 if (aLength < 1) |
|
1090 return CompressionError; |
|
1091 |
|
1092 if(!CanWrite24bppValue(aDest, aDestEnd, aLength)) |
|
1093 return NoCompression; |
|
1094 while (aLength > 128) |
|
1095 { |
|
1096 *aDest++ = 127; |
|
1097 *aDest++ = aComponent1; |
|
1098 *aDest++ = aComponent2; |
|
1099 *aDest++ = aComponent3; |
|
1100 aLength -= 128; |
|
1101 } |
|
1102 |
|
1103 *aDest++ = char(aLength-1); |
|
1104 *aDest++ = aComponent1; |
|
1105 *aDest++ = aComponent2; |
|
1106 *aDest++ = aComponent3; |
|
1107 |
|
1108 return NoError; |
|
1109 } |
|
1110 |
|
1111 int BitmapCompiler::TrueColorPointerCompare(char* aColorPointer,char aComponent1,char aComponent2,char aComponent3) |
|
1112 { |
|
1113 return (*aColorPointer == aComponent1 && *(aColorPointer + 1) == aComponent2 && *(aColorPointer + 2) == aComponent3); |
|
1114 } |
|
1115 |
|
1116 /** The function encodes 32-bit buffer into 32-bit stream by using RLE compression algorithm*/ |
|
1117 int BitmapCompiler::CompressThirtyTwoABitData(char*& aDest,char* aSrce,int aSizeInBytes) |
|
1118 { |
|
1119 const char* destEnd = aDest + aSizeInBytes; |
|
1120 char* srceLimitPtr = aSrce + aSizeInBytes; |
|
1121 char* srceLimitPtrMinusFour = srceLimitPtr - 4; // four bytes == one pixel |
|
1122 char* destCompressedLimitPtr = aDest + (aSizeInBytes * 7 / 8); |
|
1123 int ret = NoError; |
|
1124 |
|
1125 while (aSrce < srceLimitPtrMinusFour) |
|
1126 { |
|
1127 char* runStartPtr = aSrce; |
|
1128 char component1 = *aSrce++; |
|
1129 char component2 = *aSrce++; |
|
1130 char component3 = *aSrce++; |
|
1131 char component4 = *aSrce++; |
|
1132 |
|
1133 if (ColorAlphaPointerCompare(aSrce,component1,component2,component3,component4)) |
|
1134 { |
|
1135 do |
|
1136 aSrce += 4; |
|
1137 while (aSrce < srceLimitPtr && ColorAlphaPointerCompare(aSrce,component1,component2,component3,component4)); |
|
1138 int eqPixelLength = (aSrce - runStartPtr) / 4; |
|
1139 ret = WriteCompressedThirtyTwoABitValues(aDest,component1,component2,component3,component4,eqPixelLength,destEnd); |
|
1140 if (ret) |
|
1141 return ret; |
|
1142 } |
|
1143 else //non repeating pixel buffer |
|
1144 { |
|
1145 bool more = true; |
|
1146 bool eqRun = false; |
|
1147 do { |
|
1148 component1 = *aSrce++; |
|
1149 component2 = *aSrce++; |
|
1150 component3 = *aSrce++; |
|
1151 component4 = *aSrce++; |
|
1152 more = (aSrce < srceLimitPtr); |
|
1153 eqRun = more && ColorAlphaPointerCompare(aSrce,component1,component2,component3,component4); |
|
1154 } while (more && !eqRun); |
|
1155 if (eqRun) |
|
1156 aSrce -= 4; |
|
1157 int nePixelLength = (aSrce - runStartPtr) / 4; |
|
1158 ret = WriteCompressedThirtyTwoABitData(aDest,runStartPtr,nePixelLength,destEnd); |
|
1159 if (ret) |
|
1160 return ret; |
|
1161 } |
|
1162 if (aDest > destCompressedLimitPtr) |
|
1163 return NoCompression; |
|
1164 } |
|
1165 |
|
1166 if (aSrce < srceLimitPtr) |
|
1167 { |
|
1168 ret = WriteCompressedThirtyTwoABitData(aDest,aSrce,(srceLimitPtr - aSrce) / 4, destEnd); |
|
1169 if (ret) |
|
1170 return ret; |
|
1171 } |
|
1172 |
|
1173 if (aDest > destCompressedLimitPtr) |
|
1174 return NoCompression; |
|
1175 return NoError; |
|
1176 } |
|
1177 |
|
1178 /** The function copies non repeating 32-bit buffer to 32-bit compressed buffer*/ |
|
1179 int BitmapCompiler::WriteCompressedThirtyTwoABitData(char*& aDest,char* aData, |
|
1180 int aLength, const char* aDestEnd) |
|
1181 { |
|
1182 if (aLength < 1) |
|
1183 return CompressionError; |
|
1184 |
|
1185 if(!CanCopy32bppData(aDest, aDestEnd, aLength)) |
|
1186 return NoCompression; |
|
1187 |
|
1188 while (aLength > 128) |
|
1189 { |
|
1190 *aDest++ = -128; |
|
1191 memcpy(aDest,aData,512); |
|
1192 aDest += 512; |
|
1193 aData += 512; |
|
1194 aLength -= 128; |
|
1195 } |
|
1196 |
|
1197 *aDest++ = char(-aLength); |
|
1198 memcpy(aDest,aData, aLength*4); |
|
1199 aDest += aLength*4; |
|
1200 return NoError; |
|
1201 } |
|
1202 |
|
1203 /** The function copies repeating pixels including alpha to a 32-bit compressed buffer */ |
|
1204 int BitmapCompiler::WriteCompressedThirtyTwoABitValues(char*& aDest,char aComponent1, |
|
1205 char aComponent2,char aComponent3, |
|
1206 char aComponent4,int aLength, |
|
1207 const char* aDestEnd) |
|
1208 |
|
1209 { |
|
1210 if (aLength < 1) |
|
1211 return CompressionError; |
|
1212 |
|
1213 if(!CanWrite32bppValue(aDest, aDestEnd, aLength)) |
|
1214 return NoCompression; |
|
1215 while (aLength > 128) |
|
1216 { |
|
1217 *aDest++ = 127; |
|
1218 *aDest++ = aComponent1; |
|
1219 *aDest++ = aComponent2; |
|
1220 *aDest++ = aComponent3; |
|
1221 *aDest++ = aComponent4; |
|
1222 aLength -= 128; |
|
1223 } |
|
1224 |
|
1225 *aDest++ = char(aLength-1); |
|
1226 *aDest++ = aComponent1; |
|
1227 *aDest++ = aComponent2; |
|
1228 *aDest++ = aComponent3; |
|
1229 *aDest++ = aComponent4; |
|
1230 |
|
1231 return NoError; |
|
1232 } |
|
1233 |
|
1234 int BitmapCompiler::ColorAlphaPointerCompare(char* aColorPointer,char aComponent1,char aComponent2,char aComponent3,char aComponent4) |
|
1235 { |
|
1236 return (*aColorPointer == aComponent1 && *(aColorPointer + 1) == aComponent2 && *(aColorPointer + 2) == aComponent3 && *(aColorPointer + 3) == aComponent4); |
|
1237 } |
|
1238 |
|
1239 int BitmapCompiler::ReadHexString(char aHexBuf[10],char*& aDataPtr,char* aDataPtrLimit) |
|
1240 { |
|
1241 while (aDataPtr < aDataPtrLimit) |
|
1242 { |
|
1243 if (aDataPtr[0] == '0') |
|
1244 { |
|
1245 if (aDataPtr[1] == 'x' || aDataPtr[1] == 'X') |
|
1246 { |
|
1247 memcpy(aHexBuf,aDataPtr,10); |
|
1248 aDataPtr += 10; |
|
1249 return NoError; |
|
1250 } |
|
1251 } |
|
1252 aDataPtr++; |
|
1253 } |
|
1254 |
|
1255 return PaletteFile; |
|
1256 } |
|
1257 |
|
1258 int BitmapCompiler::HexToInt(char aHighNibble,char aLowNibble) |
|
1259 { |
|
1260 return (HexToInt(aHighNibble) << 4) + HexToInt(aLowNibble); |
|
1261 } |
|
1262 |
|
1263 int BitmapCompiler::HexToInt(char aNibble) |
|
1264 { |
|
1265 int value = 0; |
|
1266 |
|
1267 if (aNibble >= '0' && aNibble <= '9') |
|
1268 value = aNibble - '0'; |
|
1269 else if (aNibble >= 'a' && aNibble <= 'f') |
|
1270 value = aNibble - 'a' + 10; |
|
1271 else if (aNibble >= 'A' && aNibble <= 'F') |
|
1272 value = aNibble - 'A' + 10; |
|
1273 |
|
1274 return value; |
|
1275 } |
|
1276 |
|
1277 void BitmapCompiler::CopyTail(void* aDst, void* aSrc, int aFullSize, int aSkipped) |
|
1278 { |
|
1279 memcpy(aDst, ((char*)aSrc)+aSkipped, aFullSize-aSkipped); |
|
1280 } |
|
1281 |
|
1282 |
|
1283 |
|
1284 TSourceFile::TSourceFile() |
|
1285 : iFileName(0), iInfo(EFormatNotImportant) |
|
1286 { |
|
1287 } |
|
1288 |
|
1289 char*& TSourceFile::FileName() |
|
1290 { |
|
1291 return iFileName; |
|
1292 } |
|
1293 |
|
1294 void TSourceFile::SetCompileInfo(TCompileInfo aInfo) |
|
1295 { |
|
1296 iInfo = aInfo; |
|
1297 } |
|
1298 |
|
1299 void TSourceFile::WriteCompileInfo(ostream& aOut) |
|
1300 { |
|
1301 aOut << iFileName; |
|
1302 if (iInfo == ENokiaBitmap) |
|
1303 aOut << " (Nokia format)"; |
|
1304 else if (iInfo == EThirdPartyBitmap) |
|
1305 aOut << " (Third party format)"; |
|
1306 } |
|
1307 |