GenerateRLE8.cpp
Go to the documentation of this file.00001 //*** GenerateRLE8.h *** 00002 00003 #include "GenerateRLE8.h" 00004 #include "Image.h" 00005 #include "ColorHelper.h" 00006 #include "StandardLibrary.h" 00007 #include "Bitmap_RLE8.h" 00008 #include "MedianCutPalettizer.h" 00009 #include "FloydSteinbergDither.h" 00010 00011 #include "HashTable.h" 00012 #include "HashTableIterator.h" 00013 #include "HashTableKey_Int.h" 00014 00015 00016 //*** Constructor *** 00017 00018 GenerateRLE8::GenerateRLE8(const Image& image, Bitmap_RLE8* bitmap, bool dither): 00019 usesMask_(0), 00020 xOffset_(0), 00021 yOffset_(0), 00022 activeWidth_(0), 00023 activeHeight_(0), 00024 width_(0), 00025 height_(0), 00026 opaqueSize_(0), 00027 opaqueData_(0), 00028 alphaSize_(0), 00029 alphaData_(0), 00030 colorCount_(0), 00031 palette_(0) 00032 { 00033 CreateFromImage(&image, dither); 00034 00035 bitmap->usesMask_=usesMask_; 00036 bitmap->xOffset_=xOffset_; 00037 bitmap->yOffset_=yOffset_; 00038 bitmap->activeWidth_=activeWidth_; 00039 bitmap->activeHeight_=activeHeight_; 00040 bitmap->width_=width_; 00041 bitmap->height_=height_; 00042 bitmap->opaqueSize_=opaqueSize_; 00043 bitmap->opaqueData_=opaqueData_; 00044 bitmap->alphaSize_=alphaSize_; 00045 bitmap->alphaData_=alphaData_; 00046 bitmap->colorCount_=colorCount_; 00047 bitmap->palette_=palette_; 00048 00049 usesMask_=0; 00050 xOffset_=0; 00051 yOffset_=0; 00052 activeWidth_=0; 00053 activeHeight_=0; 00054 width_=0; 00055 height_=0; 00056 opaqueSize_=0; 00057 opaqueData_=0; 00058 alphaSize_=0; 00059 alphaData_=0; 00060 colorCount_=0; 00061 palette_=0; 00062 } 00063 00064 00065 00066 00067 //*** CalculateDiff *** 00068 00069 int CalculateDiff(unsigned short a, unsigned short b) 00070 { 00071 unsigned char ar=(unsigned char)((a & 0xf800)>>11); 00072 unsigned char ag=(unsigned char)((a & 0x7e0)>>5); 00073 unsigned char ab=(unsigned char)((a & 0x1f)); 00074 unsigned char br=(unsigned char)((b & 0xf800)>>11); 00075 unsigned char bg=(unsigned char)((b & 0x7e0)>>5); 00076 unsigned char bb=(unsigned char)((b & 0x1f)); 00077 00078 // Diff 00079 int dr=Abs(ar-br); 00080 int dg=Abs(ab-bb); 00081 int db=Abs(ag-bg); 00082 00083 return dr+dg+db; 00084 } 00085 00086 00087 00088 00089 //*** CreateFromImage *** 00090 00091 void GenerateRLE8::CreateFromImage(const Image* image, bool dither) 00092 { 00093 width_=(unsigned short)image->GetWidth(); 00094 height_=(unsigned short)image->GetHeight(); 00095 int minX=0; 00096 int minY=0; 00097 int maxX=0; 00098 int maxY=0; 00099 00100 // Crop image 00101 Crop(image,&minX,&minY,&maxX,&maxY); 00102 if (maxX<minX || maxY<minY) 00103 { 00104 return; 00105 } 00106 00107 activeWidth_=(unsigned short)(maxX-minX+1); 00108 activeHeight_=(unsigned short)(maxY-minY+1); 00109 00110 xOffset_=(unsigned short)minX; 00111 yOffset_=(unsigned short)minY; 00112 00113 // First, create palettized version 00114 unsigned char* data=0; 00115 unsigned char* mask=0; 00116 Palettize(image,&data,&mask,&palette_,&colorCount_,dither); 00117 00118 if (mask) 00119 usesMask_=1; 00120 else 00121 usesMask_=0; 00122 00123 // Create RLE data 00124 opaqueSize_=GetRLESize(data,mask); 00125 if (opaqueSize_>0) 00126 { 00127 opaqueData_=static_cast<unsigned char*>(Malloc(opaqueSize_)); 00128 CreateRLE(data,mask,opaqueData_); 00129 } 00130 00131 // Create RLE mask 00132 if (mask) 00133 { 00134 alphaSize_=GetRLESize_Alpha(data,mask); 00135 if (alphaSize_>0) 00136 { 00137 alphaData_=static_cast<unsigned char*>(Malloc(alphaSize_)); 00138 CreateRLE_Alpha(data,mask,alphaData_); 00139 } 00140 } 00141 00142 00143 // Release temp stuff 00144 if (data) 00145 { 00146 Free(data); 00147 } 00148 if (mask) 00149 { 00150 Free(mask); 00151 } 00152 } 00153 00154 00155 //*** GetRunLength *** 00156 00157 int GenerateRLE8::GetRunLength(unsigned char* data, unsigned char* mask,int size) 00158 { 00159 int length=0; 00160 int currCol=*data; 00161 if (mask && *mask<255) 00162 { 00163 currCol=255; 00164 } 00165 int c=currCol; 00166 while ((currCol==c) && size>0) 00167 { 00168 length++; 00169 00170 data++; 00171 if (mask) 00172 { 00173 mask++; 00174 } 00175 size--; 00176 00177 if (size>0) 00178 { 00179 currCol=*data; 00180 if (mask && *mask<255) 00181 { 00182 currCol=255; 00183 } 00184 } 00185 } 00186 return length; 00187 } 00188 00189 00190 //*** GetUniquesLength *** 00191 00192 int GenerateRLE8::GetUniquesLength(unsigned char* data, unsigned char* mask,int size) 00193 { 00194 int length=0; 00195 while (size>0 && GetRunLength(data,mask,size)<=2) 00196 { 00197 length++; 00198 data++; 00199 if (mask) 00200 { 00201 mask++; 00202 } 00203 size--; 00204 } 00205 return length; 00206 } 00207 00208 00209 //*** GetRLESize *** 00210 00211 int GenerateRLE8::GetRLESize(unsigned char* data,unsigned char* mask) 00212 { 00213 return CreateRLE(data,mask,0); 00214 } 00215 00216 00217 //*** CreateRLE *** 00218 00219 int GenerateRLE8::CreateRLE(unsigned char* source, unsigned char* mask, unsigned char* destination) 00220 { 00221 int size=activeWidth_*activeHeight_; 00222 int result=0; 00223 int xleft=activeWidth_; 00224 while (size>0) 00225 { 00226 unsigned char len=(unsigned char)GetRunLength(source,mask,Min(127,Min(size,xleft))); 00227 if (len<=2) 00228 { 00229 unsigned char len=(unsigned char)GetUniquesLength(source,mask,Min(127,Min(size,xleft))); 00230 00231 result++; // Count value 00232 if (destination) 00233 { 00234 *destination=(len | 0x80); // Top bit set to indicate run of unique colors 00235 destination++; 00236 } 00237 00238 result+=len; // Unique colors 00239 if (destination) 00240 { 00241 unsigned char* colorsource=source; 00242 unsigned char* maskvalue=mask; 00243 for (int i=0; i<len; i++) 00244 { 00245 if (mask && *maskvalue<255) 00246 *destination=255; // Transparent or semitransparent pixel 00247 else 00248 *destination=*colorsource; 00249 destination++; 00250 colorsource++; 00251 if (mask) 00252 maskvalue++; 00253 } 00254 } 00255 00256 if (mask) 00257 mask+=len; 00258 source+=len; 00259 xleft-=len; 00260 Assert(xleft>=0,"Inavlid run length"); 00261 if (xleft==0) 00262 xleft=activeWidth_; 00263 size-=len; 00264 } 00265 else 00266 { 00267 result++; // Count value 00268 if (destination) 00269 { 00270 *destination=len; // Top bit not set to indicate run of same color 00271 destination++; 00272 } 00273 00274 result++; // Repeated color 00275 if (destination) 00276 { 00277 if (mask && *mask<255) 00278 *destination=255; // Transparent or semitransparent pixel 00279 else 00280 *destination=*source; 00281 destination++; 00282 } 00283 00284 source+=len; 00285 xleft-=len; 00286 Assert(xleft>=0,"Inavlid run length"); 00287 if (xleft==0) 00288 xleft=activeWidth_; 00289 if (mask) 00290 mask+=len; 00291 size-=len; 00292 } 00293 } 00294 00295 return result; 00296 } 00297 00298 00299 00300 //*** GetRunLength_Alpha *** 00301 00302 int GenerateRLE8::GetRunLength_Alpha(unsigned char* data, unsigned char* mask,int size) 00303 { 00304 int length=0; 00305 int currCol=*data; 00306 int currMask=*mask; 00307 if (currMask==0 || currMask==255) 00308 { 00309 currMask=0; 00310 currCol=255; 00311 } 00312 int c=currCol; 00313 int m=currMask; 00314 while ((currCol==c) && (currMask==m) && size>0) 00315 { 00316 length++; 00317 data++; 00318 mask++; 00319 size--; 00320 if (size>0) 00321 { 00322 currCol=*data; 00323 currMask=*mask; 00324 if (currMask==0 || currMask==255) 00325 { 00326 currMask=0; 00327 currCol=255; 00328 } 00329 } 00330 } 00331 return length; 00332 } 00333 00334 00335 //*** GetUniquesLength_Alpha *** 00336 00337 int GenerateRLE8::GetUniquesLength_Alpha(unsigned char* data, unsigned char* mask,int size) 00338 { 00339 int length=0; 00340 while (size>0 && GetRunLength_Alpha(data,mask,size)<=2) 00341 { 00342 length++; 00343 data++; 00344 mask++; 00345 size--; 00346 } 00347 return length; 00348 } 00349 00350 00351 //*** GetRLESize_Alpha *** 00352 00353 int GenerateRLE8::GetRLESize_Alpha(unsigned char* data,unsigned char* mask) 00354 { 00355 return CreateRLE_Alpha(data,mask,0); 00356 } 00357 00358 00359 //*** CreateRLE_Alpha *** 00360 00361 int GenerateRLE8::CreateRLE_Alpha(unsigned char* source, unsigned char* mask, unsigned char* destination) 00362 { 00363 int size=activeWidth_*activeHeight_; 00364 int result=0; 00365 int xleft=activeWidth_; 00366 while (size>0) 00367 { 00368 unsigned char len=(unsigned char)GetRunLength_Alpha(source,mask,Min(127,Min(size,xleft))); 00369 if (len<=2) 00370 { 00371 unsigned char len=(unsigned char)GetUniquesLength_Alpha(source,mask,Min(127,Min(size,xleft))); 00372 00373 result++; // Count value 00374 if (destination) 00375 { 00376 *destination=(len | 0x80); // Top bit set to indicate run of unique colors 00377 destination++; 00378 } 00379 00380 // Unique colors 00381 unsigned char* colorsource=source; 00382 unsigned char* maskvalue=mask; 00383 for (int i=0; i<len; i++) 00384 { 00385 if (*maskvalue==0 || *maskvalue==255) 00386 { 00387 if (destination) 00388 { 00389 *destination=0; // Fully transparent pixel 00390 destination++; 00391 *destination=0; 00392 destination++; 00393 } 00394 result+=2; 00395 } 00396 else 00397 { 00398 if (destination) 00399 { 00400 *destination=*maskvalue; // Semi-transparent pixel 00401 destination++; 00402 *destination=*colorsource; 00403 destination++; 00404 } 00405 result+=2; 00406 } 00407 colorsource++; 00408 maskvalue++; 00409 } 00410 00411 mask+=len; 00412 source+=len; 00413 xleft-=len; 00414 Assert(xleft>=0,"Invalid run length"); 00415 if (xleft==0) 00416 xleft=activeWidth_; 00417 size-=len; 00418 } 00419 else 00420 { 00421 result++; // Count value 00422 if (destination) 00423 { 00424 *destination=len; // Top bit not set to indicate run of same color 00425 destination++; 00426 } 00427 00428 // Repeated color 00429 00430 if (*mask==0 || *mask==255) 00431 { 00432 if (destination) 00433 { 00434 *destination=0; // Fully transparent pixel 00435 destination++; 00436 *destination=0; 00437 destination++; 00438 } 00439 result+=2; 00440 } 00441 else 00442 { 00443 if (destination) 00444 { 00445 *destination=*mask; 00446 destination++; 00447 *destination=*source; 00448 destination++; 00449 } 00450 result+=2; 00451 } 00452 00453 source+=len; 00454 xleft-=len; 00455 Assert(xleft>=0,"Invalid run length"); 00456 if (xleft==0) 00457 xleft=activeWidth_; 00458 mask+=len; 00459 size-=len; 00460 } 00461 } 00462 00463 return result; 00464 } 00465 00466 00467 00468 00469 00470 //*** Palettize *** 00471 00472 void GenerateRLE8::Palettize(const Image* image,unsigned char** data, unsigned char** mask, unsigned short** palette, unsigned char* colorCount, bool dither) 00473 { 00474 int usedPaletteEntries=0; 00475 *data=static_cast<unsigned char*>(Malloc(sizeof(unsigned char)*activeWidth_*activeHeight_)); 00476 *mask=static_cast<unsigned char*>(Malloc(sizeof(unsigned char)*activeWidth_*activeHeight_)); 00477 unsigned char* img=*data; 00478 unsigned char* maskimg=*mask; 00479 bool maskUsed=false; 00480 bool maskUsedTrans=false; 00481 00482 // Create palette 00483 unsigned short pal16[256]; 00484 usedPaletteEntries=MedianCutPalettizer::GeneratePalette(image->GetPointer(),image->GetWidth(),image->GetHeight(),pal16,255); 00485 00486 // Dither 00487 unsigned int pal[256]; 00488 for (int i=0; i<usedPaletteEntries; i++) 00489 { 00490 pal[i]=RGB16TO32(pal16[i]); 00491 } 00492 unsigned char* palettized=(unsigned char*)Malloc(image->GetWidth()*image->GetHeight()); 00493 00494 if (dither) 00495 { 00496 FloydSteinbergDither::DitherImage(image->GetPointer(),image->GetWidth(), image->GetHeight(),pal,usedPaletteEntries,palettized); 00497 } 00498 else 00499 { 00500 MedianCutPalettizer::PalettizeImage(image->GetPointer(),image->GetWidth(), image->GetHeight(),pal,usedPaletteEntries,palettized); 00501 } 00502 00503 for (int y=0; y<activeHeight_; y++) 00504 { 00505 for (int x=0; x<activeWidth_; x++) 00506 { 00507 unsigned int color=image->GetPixel(xOffset_+x,yOffset_+y); 00508 unsigned char a=((unsigned char)(((color)&0xff000000)>>24)); 00509 unsigned char colIndex=palettized[xOffset_+x+image->GetWidth()*(y+yOffset_)]; 00510 *img=colIndex; 00511 img++; 00512 *maskimg=a; 00513 maskimg++; 00514 00515 if (a<255) 00516 { 00517 maskUsed=true; 00518 if (a>0) 00519 { 00520 maskUsedTrans=true; 00521 } 00522 } 00523 } 00524 } 00525 00526 Free(palettized); 00527 00528 if (!maskUsed) 00529 { 00530 Free(*mask); 00531 *mask=0; 00532 } 00533 00534 *palette=static_cast<unsigned short*>(Malloc(sizeof(unsigned short)*usedPaletteEntries)); 00535 // MemCpy(*palette,pal,sizeof(unsigned short)*usedPaletteEntries); 00536 for (int i=0; i<usedPaletteEntries; i++) 00537 { 00538 // unsigned short c=RGB32TO16(pal32[i]); 00539 unsigned short c=pal16[i]; 00540 (*palette)[i]=c; 00541 } 00542 *colorCount=(unsigned char)usedPaletteEntries; 00543 } 00544 00545 00546 //*** Crop *** 00547 00548 void GenerateRLE8::Crop(const Image* image, int* minX, int* minY, int* maxX, int* maxY) 00549 { 00550 *minX=image->GetWidth(); 00551 *minY=image->GetHeight(); 00552 *maxX=0; 00553 *maxY=0; 00554 for (int y=0; y<image->GetHeight(); y++) 00555 { 00556 for (int x=0; x<image->GetWidth(); x++) 00557 { 00558 unsigned int color=image->GetPixel(x,y); 00559 if (color>>24) 00560 { 00561 if (y<*minY) 00562 *minY=y; 00563 if (x<*minX) 00564 *minX=x; 00565 if (y>*maxY) 00566 *maxY=y; 00567 if (x>*maxX) 00568 *maxX=x; 00569 } 00570 } 00571 } 00572 } 00573
Reproduction/republishing of any material on this site without permission is strictly prohibited.
