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