Main Page | Alphabetical List | Compound List | File List | Compound Members | File Members

gebmutil.c

Go to the documentation of this file.
00001 
00002 #define WIN32_LEAN_AND_MEAN
00003 #pragma warning(disable : 4201 4214 4115)
00004 #include <windows.h>
00005 #pragma warning(default : 4201 4214 4115)
00006 
00007 #include "gebmutil.h"
00008 #include "Ram.h"
00009 #include "errorlog.h"
00010 #include <stdlib.h>
00011 #include <assert.h>
00012 #include <math.h>
00013 
00014 #include "vfile.h"
00015 
00016 #ifdef _LOG
00017 #include "log.h"
00018 #else
00019 #pragma warning (disable:4100)
00020 static _inline void Log_Printf(const char * str, ...) { }
00021 #pragma warning (default:4100)
00022 #endif
00023 
00024 #ifdef _TSC
00025 #include "tsc.h"
00026 #else
00027 #define pushTSC()
00028 #define showPopTSC(s)
00029 #endif
00030 
00031 /*}{*************** HBITMAP utilities ******************/
00032 
00033 HBITMAP geBitmapUtil_CreateHBITMAP(geBitmap *Bitmap,HWND window,int mip)
00034 {
00035 geBitmap * Lock;
00036 gePixelFormat Format;
00037 geBitmap_Info info;
00038 HBITMAP hbm = NULL;
00039 
00040 #pragma message("gebmu_CreateHBITMAP : choose format to be 8,16,or 24, whichever is closest to Bitmap")
00041 
00042         Format = GE_PIXELFORMAT_24BIT_BGR;
00043 
00044         if ( geBitmap_GetBits(Bitmap) )
00045         {
00046                 Lock = Bitmap;
00047         }
00048         else
00049         {
00050                 if ( ! geBitmap_LockForRead(Bitmap, &Lock, mip,mip, Format,     GE_FALSE,0) )
00051                         return NULL;
00052         }
00053 
00054         geBitmap_GetInfo(Lock,&info,NULL);
00055 
00056         if ( info.Format != Format )
00057                 return NULL;
00058 
00059         {
00060         void * bits;
00061         HDC hdc;
00062         BITMAPINFOHEADER bmih;
00063         int pelbytes;
00064 
00065                 pelbytes = gePixelFormat_BytesPerPel(Format);
00066                 bits = geBitmap_GetBits(Lock);
00067 
00068                 hdc = GetDC(window);
00069 
00070                 bmih.biSize = sizeof(bmih);
00071                 bmih.biHeight = - info.Height;
00072                 bmih.biPlanes = 1;
00073                 bmih.biBitCount = 24;
00074                 bmih.biCompression = BI_RGB;
00075                 bmih.biSizeImage = 0;
00076                 bmih.biXPelsPerMeter = bmih.biYPelsPerMeter = 10000;
00077                 bmih.biClrUsed = bmih.biClrImportant = 0;
00078 
00079                 if ( (info.Stride*pelbytes) == (((info.Stride*pelbytes)+3)&(~3)) )
00080                 {
00081                         bmih.biWidth = info.Stride;
00082                         hbm = CreateDIBitmap( hdc, &bmih , CBM_INIT , bits, (BITMAPINFO *)&bmih , DIB_RGB_COLORS );
00083                 }
00084                 else
00085                 {
00086                 void * newbits;
00087                 int Stride;
00088                         bmih.biWidth = info.Width;
00089                         Stride = (((info.Width*pelbytes)+3)&(~3));
00090                         newbits = geRam_Allocate(Stride * info.Height);
00091                         if ( newbits )
00092                         {
00093                         char *newptr,*oldptr;
00094                         int y;
00095                                 newptr = newbits;
00096                                 oldptr = bits;
00097                                 for(y=0;y<info.Height;y++)
00098                                 {
00099                                         memcpy(newptr,oldptr,(info.Width)*pelbytes);
00100                                         oldptr += info.Stride*pelbytes;
00101                                         newptr += Stride;
00102                                 }
00103                                 hbm = CreateDIBitmap( hdc, &bmih , CBM_INIT , newbits, (BITMAPINFO *)&bmih , DIB_RGB_COLORS );
00104                                 geRam_Free(newbits);
00105                         }
00106                 }
00107 
00108                 ReleaseDC(window,hdc);
00109         }
00110 
00111         if ( Lock != Bitmap )
00112                 geBitmap_UnLock(Lock);
00113 
00114 return hbm;
00115 }
00116 
00117 geBitmap * geBitmapUtil_CreateFromHBITMAP(HWND window,HBITMAP hbm)
00118 {
00119 geBitmap * Bmp;
00120 char bmidata[sizeof(BITMAPINFOHEADER)+12];
00121 BITMAPINFOHEADER * pbmi;
00122 HDC hdc;
00123 int lines;
00124 
00125         if ( ! window || ! hbm )
00126                 return NULL;
00127 
00128         pbmi = (BITMAPINFOHEADER *)bmidata;
00129 
00130         pbmi->biSize = sizeof(BITMAPINFOHEADER);
00131         pbmi->biWidth = 0;
00132         pbmi->biHeight = 0;
00133         pbmi->biPlanes = 1;
00134         pbmi->biBitCount = 0;
00135         pbmi->biCompression = BI_RGB;
00136         pbmi->biSizeImage = 0;
00137         pbmi->biXPelsPerMeter = pbmi->biYPelsPerMeter = 1000;
00138         pbmi->biClrUsed = pbmi->biClrImportant = 0;
00139 
00140         hdc = GetDC(window);
00141         if ( ! hdc )
00142                 return NULL;
00143 
00144         lines = GetDIBits(hdc,hbm,0,0,NULL,(BITMAPINFO *)pbmi,0);
00145 
00146         ReleaseDC(window,hdc);
00147 
00148         if ( ! lines )
00149                 return NULL;
00150 
00151         {
00152         geBitmap * Lock;
00153         void * bits;
00154         int ret;
00155         uint32 * masks;
00156 
00157                 Bmp = geBitmap_Create(pbmi->biWidth,abs(pbmi->biHeight),1,GE_PIXELFORMAT_32BIT_XRGB);
00158                 if ( ! Bmp )
00159                         return NULL;
00160 
00161                 masks = (uint32 *)(bmidata + sizeof(BITMAPINFOHEADER));
00162                 masks[0] = 0x00FF0000;
00163                 masks[1] = 0x0000FF00;
00164                 masks[2] = 0x000000FF;
00165 
00166                 if ( ! geBitmap_LockForWrite(Bmp,&Lock,0,0) )
00167                 {
00168                         geBitmap_Destroy(&Bmp);
00169                         return NULL;
00170                 }
00171 
00172                 bits = geBitmap_GetBits(Lock);
00173                 assert(bits);
00174 
00175                 pbmi->biSize = sizeof(BITMAPINFOHEADER);
00176                 pbmi->biHeight = - abs(pbmi->biHeight);
00177                 pbmi->biPlanes = 1;
00178                 pbmi->biBitCount = 32;
00179                 pbmi->biCompression = BI_RGB;
00180                 pbmi->biSizeImage = 0;
00181                 pbmi->biClrUsed = pbmi->biClrImportant = 0;
00182 
00183                 hdc = GetDC(window);
00184                 assert(hdc);
00185 
00186                 ret = GetDIBits(hdc,hbm,0,lines,bits,(BITMAPINFO *)pbmi,0);
00187 
00188                 ReleaseDC(window,hdc);
00189 
00190                 geBitmap_UnLock(Lock);
00191 
00192                 if ( ! ret )
00193                 {
00194                         geBitmap_Destroy(&Bmp);
00195                         return NULL;
00196                 }
00197         }
00198 
00199 return Bmp;
00200 }
00201 
00202 /*}{*************** SmoothBits !! ******************/
00203 
00204 /*******
00205 
00206 SmoothBits with radius == 1 is actually the solution of the diffusion equation (!!)
00207 
00208 *pSrc = (pSrc[-1] + pSrc[1] + pSrc[s]+ pSrc[s-1])>>2;
00209 
00210 rewriting :
00211 
00212 f'(x,y) = ( f(x+1,y) + f(x-1,y) + f(x,y+1) + f(x,y-1) )/4
00213 
00214 f'(x,y) - f(x,y)  = ( f(x+1,y) + f(x-1,y) + f(x,y+1) + f(x,y-1) )/4 - f(x,y)
00215 
00216 [f'(x,y) - f(x,y)]/a  = (b^2/a) [ ( f(x+1,y) + f(x-1,y) + f(x,y+1) + f(x,y-1) )/4 - f(x,y) ]/b^2
00217 
00218 now the left is a time-derivative with time step a and the right side is a grad-squared with
00219 x-spacing of b.  Since b = 1 pixel :
00220 
00221 dt f(x,y)  = (1 pixel^2/a) grad^2 f(x,y)
00222 
00223 in our application, 'a' is like 1/50 second = 0.02 or such, so we have a diffusion equation:
00224 
00225         dt f() = lambda  grad^2 f()
00226 
00227 with a fixed diffusion coefficient lambda = 50 pixel^2/second
00228 
00229 ********/
00230 geBoolean geBitmapUtil_SmoothBits(geBitmap_Info *pInfo,void *FmBits,void *ToBits,int radius,geBoolean wrap)
00231 {
00232 int bpp,x,y,w,h,s;
00233 
00234         assert(FmBits && ToBits);
00235         assert(radius > 0);
00236 
00237         if ( radius > 3 ) radius = 3;
00238 
00239         bpp = gePixelFormat_BytesPerPel(pInfo->Format);
00240 
00241         w = pInfo->Width;
00242         h = pInfo->Height;
00243         s = pInfo->Stride;
00244 
00245         switch(bpp)
00246         {
00247                 case 0:
00248                         return GE_FALSE;
00249                 case 1:
00250                 {
00251                 uint8 *pSrc,*pDst;
00252 
00253                         pSrc = FmBits;
00254                         pDst = ToBits;
00255 
00256                         if ( wrap )
00257                         {
00258                         uint8 *pSrcN,*pSrcP;
00259                                 switch(radius)
00260                                 {
00261                                 case 1:
00262                                         for(y=0;y<h;y++)
00263                                         {                                               
00264                                                 pSrcN = pSrc+s;
00265                                                 pSrcP = pSrc-s;
00266 
00267                                                 if ( y == 0 )
00268                                                 {
00269                                                         pSrcP = pSrc + s*(h-1);
00270                                                 }
00271                                                 else if ( y == (h-1) )
00272                                                 {
00273                                                         pSrcN = FmBits;
00274                                                 }
00275 
00276                                                 //first pel                                             
00277                                                 *pDst++ = (pSrc[w-1] + pSrc[1] + *pSrcN + *pSrcP)>>2;
00278                                                 pSrc++;
00279                                                 pSrcN++;
00280                                                 pSrcP++;
00281 
00282                                                 for(x = w-2;x--;)
00283                                                 {
00284                                                         *pDst++ = (pSrc[-1] + pSrc[1] + *pSrcN + *pSrcP)>>2;
00285                                                         pSrc++;
00286                                                         pSrcN++;
00287                                                         pSrcP++;
00288                                                 }
00289 
00290                                                 // last pel
00291                                                 *pDst++ = (pSrc[-1] + pSrc[1-w] + *pSrcN + *pSrcP)>>2;
00292                                                 pSrc++;
00293                                                 pSrcN++;
00294                                                 pSrcP++;
00295 
00296                                                 pDst += (s-w);
00297                                                 pSrc += (s-w);
00298                                         }
00299                                         break;
00300 
00301                                 default:
00302                                 case 2:
00303                                         for(y=0;y<h;y++)
00304                                         {                                               
00305                                                 pSrcN = pSrc+s;
00306                                                 pSrcP = pSrc-s;
00307 
00308                                                 if ( y == 0 )
00309                                                 {
00310                                                         pSrcP = pSrc + s*(h-1);
00311                                                 }
00312                                                 else if ( y == (h-1) )
00313                                                 {
00314                                                         pSrcN = FmBits;
00315                                                 }
00316 
00317                                                 //first pel                                             
00318                                                 *pDst++ = (pSrcN[-1] + pSrc[1] + *pSrcN + *pSrcP)>>2;
00319                                                 pSrc++;
00320                                                 pSrcN++;
00321                                                 pSrcP++;
00322 
00323                                                 for(x = w-2;x--;)
00324                                                 {
00325                                                         *pDst++ = (pSrc[-1] + pSrc[1] + pSrcN[0] + pSrcP[0] +
00326                                                                                 pSrcN[1] + pSrcN[-1] + pSrcP[1] + pSrcP[-1])>>3;
00327                                                         pSrc++;
00328                                                         pSrcN++;
00329                                                         pSrcP++;
00330                                                 }
00331 
00332                                                 // last pel
00333                                                 *pDst++ = (pSrc[-1] + pSrcP[1] + *pSrcN + *pSrcP)>>2;
00334                                                 pSrc++;
00335                                                 pSrcN++;
00336                                                 pSrcP++;
00337 
00338                                                 pDst += (s-w);
00339                                                 pSrc += (s-w);
00340                                         }
00341                                         break;
00342                                 }
00343                         }
00344                         else
00345                         {
00346                                 switch(radius)
00347                                 {
00348                                 case 1:
00349                                         
00350                                                 // first line
00351                                                 *pDst++ = (pSrc[1] + pSrc[s])>>1;
00352                                                 pSrc++;
00353                                                 for(x=w-1;x--;)
00354                                                 {
00355                                                         *pDst++ = (pSrc[-1] + pSrc[1] + pSrc[s]+ pSrc[s-1])>>2;
00356                                                         pSrc++;
00357                                                 }
00358                                                 pDst += (s-w);
00359                                                 pSrc += (s-w);
00360 
00361                                         for(y=h-2;y--;)
00362                                         {
00363                                                 // middle lines
00364                                                 
00365                                                 x = w;
00366 
00367                                                 #ifdef DONT_USE_ASM //{
00368 
00369                                                 while(x--)
00370                                                 {
00371                                                         *pDst++ = (pSrc[-1] + pSrc[1] + pSrc[s] + pSrc[-s])>>2;
00372                                                         pSrc++;
00373                                                 }
00374 
00375                                                 pDst += (s-w);
00376                                                 pSrc += (s-w);
00377 
00378                                                 #else //}{
00379 
00380                                                 __asm 
00381                                                 {
00382                                                         mov esi, pSrc
00383                                                         mov edi, pDst
00384                                                 
00385                                                         // something like 10 clocks per byte = molto bene
00386                                                         
00387                                                 mainloop:
00388                                                         xor eax,eax                                             // load the sum into eax
00389 
00390                                                         movzx edx,BYTE PTR [esi+1]              // port 2, latency 1
00391                                                         add eax,edx                                             // port 1, latency 1
00392 
00393                                                         movzx edx,BYTE PTR [esi-1]
00394                                                         add eax,edx     
00395                                                                 
00396                                                         mov ecx,esi                                             // ecx = esi + s
00397                                                         add ecx,s
00398                                                         movzx edx,BYTE PTR [ecx]                // eax += (BYTE) [ecx]
00399                                                         add eax,edx                                             // we have to use edx cuz of the byte 
00400 
00401                                                         mov ecx,esi     
00402                                                         sub ecx,s
00403                                                         movzx edx,BYTE PTR [ecx]
00404                                                         add eax,edx     
00405 
00406                                                         shr eax,2
00407 
00408                                                         mov [edi],al
00409 
00410                                                         inc edi
00411                                                         inc esi
00412                                                         dec x
00413 
00414                                                         jnz mainloop
00415                                                 }
00416 
00417                                                 pDst += s;
00418                                                 pSrc += s;
00419 
00420                                                 #endif // }
00421                                         }
00422                                         
00423                                                 // last line
00424                                                 for(x=w-1;x--;)
00425                                                 {
00426                                                         *pDst++ = (pSrc[-1] + pSrc[1] + pSrc[-s]+ pSrc[-s+1])>>2;
00427                                                         pSrc++;
00428                                                 }
00429                                                 *pDst++ = (pSrc[-1] + pSrc[-s])>>1;
00430                                                 pSrc++;
00431                                                 pSrc += (s-w);
00432                                                 pDst += (s-w);
00433                                         break;
00434 
00435                                 default:
00436                                 case 2:                 
00437                                                 // first line
00438                                                 *pDst++ = (pSrc[1] + pSrc[s])>>1;
00439                                                 pSrc++;
00440                                                 for(x=w-1;x--;)
00441                                                 {
00442                                                         *pDst++ = (pSrc[-1] + pSrc[1] + pSrc[s]+ pSrc[s-1])>>2;
00443                                                         pSrc++;
00444                                                 }
00445                                                 pSrc += (s-w);
00446                                                 pDst += (s-w);
00447 
00448                                         for(y=h-2;y--;)
00449                                         {
00450                                                 *pDst++ = (pSrc[-1] + pSrc[1] + pSrc[s] + pSrc[-s])>>2;
00451                                                 pSrc++;
00452 
00453                                                 #ifdef DONT_USE_ASM //{
00454 
00455                                                 for(x=w-2;x--;)
00456                                                 {
00457                                                         *pDst++ = (pSrc[-1] + pSrc[1] + pSrc[s] + pSrc[-s] +
00458                                                                                 pSrc[s+1] + pSrc[s-1] + pSrc[-s+1] + pSrc[-s-1])>>3;
00459                                                         pSrc++;
00460                                                 }
00461 
00462                                                 #else //}{
00463 
00464                                                 x = w-2;
00465 
00466                                                 __asm 
00467                                                 {
00468                                                         mov esi, pSrc
00469                                                         //lea esi, [pSrc]
00470                                                         mov edi, pDst
00471                                                         //lea edi, [pDst]
00472                                                         
00473                                                 mainloop2:
00474                                                         xor eax,eax                                             // load the sum into eax
00475 
00476                                                         movzx edx,BYTE PTR [esi+1]              // eax += (BYTE) esi[1]
00477                                                         add eax,edx                                             // we have to use edx cuz of the byte
00478 
00479                                                         movzx edx,BYTE PTR [esi-1]
00480                                                         add eax,edx     
00481 
00482                                                         mov ecx,esi                                             // ecx = esi + s
00483                                                         add ecx,s
00484                                                         movzx edx,BYTE PTR [ecx-1]              
00485                                                         add eax,edx                                             
00486                                                         movzx edx,BYTE PTR [ecx]                
00487                                                         add eax,edx
00488                                                         movzx edx,BYTE PTR [ecx+1]
00489                                                         add eax,edx                                             
00490 
00491                                                         mov ecx,esi     
00492                                                         sub ecx,s
00493                                                         movzx edx,BYTE PTR [ecx-1]
00494                                                         add eax,edx     
00495                                                         movzx edx,BYTE PTR [ecx]
00496                                                         add eax,edx     
00497                                                         movzx edx,BYTE PTR [ecx+1]
00498                                                         add eax,edx     
00499 
00500                                                         shr eax,3
00501 
00502                                                         mov [edi],al
00503 
00504                                                         inc edi
00505                                                         inc esi
00506                                                         dec x
00507 
00508                                                         jnz mainloop2
00509                                                 }
00510 
00511                                                 pDst += w-2;
00512                                                 pSrc += w-2;
00513 
00514                                                 #endif //}
00515 
00516                                                 *pDst++ = (pSrc[-1] + pSrc[1] + pSrc[s] + pSrc[-s])>>2;
00517                                                 pSrc++;
00518                                                 pSrc += (s-w);
00519                                                 pDst += (s-w);
00520                                         }
00521                                                 // last line
00522                                                 for(x=w-1;x--;)
00523                                                 {
00524                                                         *pDst++ = (pSrc[-1] + pSrc[1] + pSrc[-s]+ pSrc[-s+1])>>2;
00525                                                         pSrc++;
00526                                                 }
00527                                                 *pDst++ = (pSrc[-1] + pSrc[-s])>>1;
00528                                                 pSrc++;
00529                                                 pSrc += (s-w);
00530                                                 pDst += (s-w);
00531                                         break;
00532                                 }
00533                         }
00534 
00535                         assert( pSrc == ((uint8 *)FmBits + h*s) );
00536                         assert( pDst == ((uint8 *)ToBits + h*s) );
00537                         break;
00538                 }
00539 
00540 
00541                 case 2:
00542                 case 3:
00543                 case 4:
00544                         // can't just use a simple blender for 2-3-4-byte pixel formats;
00545                         // must decompose pixels to RGBA and blend
00546                         geErrorLog_AddString(-1,"geBitmapUtil_SmoothBits : only implemented for 1-byte data",NULL);
00547                         return GE_FALSE;
00548         }
00549 
00550         return GE_TRUE;
00551 }
00552 
00553 geBoolean geBitmapUtil_SetAlphaFromBrightness(geBitmap *Bmp)
00554 {
00555 geBitmap_Palette * Pal;
00556         assert(Bmp);
00557 
00558         if ( Pal = geBitmap_GetPalette(Bmp) )
00559         {
00560         uint32 PalData[256];
00561         int p;
00562 
00563                 if ( ! geBitmap_Palette_SetFormat(Pal,GE_PIXELFORMAT_32BIT_ARGB) )
00564                         return GE_FALSE;
00565 
00566                 if ( ! geBitmap_Palette_GetData(Pal,PalData,GE_PIXELFORMAT_32BIT_ARGB,256) )
00567                         return GE_FALSE;
00568 
00569                 for(p=0;p<256;p++)
00570                 {
00571                 uint32 r,g,b,a,pel;
00572                         pel = PalData[p];
00573                         r = (pel>>16)&0xFF;
00574                         g = (pel>>8)&0xFF;
00575                         b = (pel>>0)&0xFF;
00576                         a = (r + g + b + 2)/3;
00577                         pel = (pel & 0x00FFFFFF) + (a<<24);
00578                         PalData[p] = pel;
00579                 }
00580 
00581                 if ( ! geBitmap_Palette_SetData(Pal,PalData,GE_PIXELFORMAT_32BIT_ARGB,256) )
00582                         return GE_FALSE;
00583 
00584                 return GE_TRUE;
00585         }
00586         else
00587         {
00588         geBitmap * Alpha;
00589         geBitmap_Info Info;
00590                 if ( ! geBitmap_GetInfo(Bmp,&Info,NULL) )
00591                         return GE_FALSE;
00592                 Info.Format = GE_PIXELFORMAT_8BIT_GRAY;
00593                 Alpha = geBitmap_CreateFromInfo(&Info);
00594                 if ( ! geBitmap_BlitBitmap(Bmp,Alpha) )
00595                         return GE_FALSE;
00596                 if ( ! geBitmap_SetAlpha(Bmp,Alpha) )
00597                         return GE_FALSE;
00598                 return GE_TRUE;
00599         }
00600 }
00601 
00602 geBoolean geBitmapUtil_SetColor(geBitmap *Bmp,int R,int G,int B,int A)
00603 {
00604 geBitmap *Lock=NULL;
00605 geBitmap_Info Info;
00606 void *Bits;
00607 int w,h,s,bpp,x;
00608 
00609         assert(Bmp);
00610 
00611         if ( ! geBitmap_LockForWrite(Bmp,&Lock,0,0) )
00612                 goto fail;
00613 
00614         if ( ! geBitmap_GetInfo(Lock,&Info,NULL) )
00615                 goto fail;
00616 
00617         Bits = geBitmap_GetBits(Lock);
00618 
00619         if ( ! Bits )
00620                 goto fail; 
00621 
00622         bpp = gePixelFormat_BytesPerPel(Info.Format);
00623 
00624         w = Info.Width;
00625         h = Info.Height;
00626         s = Info.Stride;
00627 
00628         switch(bpp)
00629         {
00630                 default:                
00631                         goto fail;
00632                 case 1:
00633                 {
00634                 uint8 * pBits,Pixel;
00635                         pBits = Bits;
00636                         Pixel = (R+G+B)/3;
00637                         while(h--)
00638                         {
00639                                 for(x=w;x--;)
00640                                 {
00641                                         *pBits++ = Pixel;
00642                                 }       
00643                                 pBits += (s-w);                         
00644                         }
00645                         break;
00646                 }               
00647                 case 2:
00648                 {
00649                 uint16 * pBits,Pixel;
00650                         pBits = Bits;
00651                         Pixel = (uint16)gePixelFormat_ComposePixel(Info.Format,R,G,B,A);
00652                         while(h--)
00653                         {
00654                                 for(x=w;x--;)
00655                                 {
00656                                         *pBits++ = Pixel;
00657                                 }       
00658                                 pBits += (s-w);                         
00659                         }
00660                         break;
00661                 }               
00662                 case 4:
00663                 {
00664                 uint32 * pBits,Pixel;
00665                         pBits = Bits;
00666                         Pixel = (uint32)gePixelFormat_ComposePixel(Info.Format,R,G,B,A);
00667                         while(h--)
00668                         {
00669                                 for(x=w;x--;)
00670                                 {
00671                                         *pBits++ = Pixel;
00672                                 }       
00673                                 pBits += (s-w);                         
00674                         }
00675                         break;
00676                 }               
00677                 case 3:
00678                 {
00679                 uint8 * pBits,b1,b2,b3;
00680                 uint32 Pixel;
00681                         pBits = Bits;
00682                         Pixel = (uint32)gePixelFormat_ComposePixel(Info.Format,R,G,B,A);
00683                         b1 = (uint8)((Pixel>>16)&0xFF);
00684                         b2 = (uint8)((Pixel>>8 )&0xFF);
00685                         b3 = (uint8)((Pixel>>0 )&0xFF);
00686                         while(h--)
00687                         {
00688                                 for(x=w;x--;)
00689                                 {
00690                                         *pBits++ = b1;
00691                                         *pBits++ = b2;
00692                                         *pBits++ = b3;
00693                                 }       
00694                                 pBits += 3*(s-w);                               
00695                         }
00696                         break;
00697                 }
00698         }
00699 
00700         if ( ! geBitmap_UnLock(Lock) )
00701                 goto fail;
00702 
00703         geBitmap_RefreshMips(Bmp);
00704 
00705         return GE_TRUE;
00706 fail:
00707 
00708         if ( Lock )
00709                 geBitmap_UnLock(Lock);
00710 
00711         return GE_FALSE;
00712 }
00713 
00714 /*}{*************** Bitmap_Create : ******************/
00715 
00716 geBitmap * geBitmapUtil_CreateFromFileName(const geVFile * BaseFS,const char * BmName)
00717 {
00718 geVFile * File;
00719 geBitmap * Bmp;
00720 
00721         if ( BaseFS )
00722                 File = geVFile_Open((geVFile *)BaseFS,BmName,GE_VFILE_OPEN_READONLY);
00723         else
00724                 File = geVFile_OpenNewSystem(NULL,GE_VFILE_TYPE_DOS,BmName,NULL,GE_VFILE_OPEN_READONLY);
00725         if ( ! File )
00726                 return NULL;
00727 
00728         Bmp = geBitmap_CreateFromFile(File);
00729         geVFile_Close(File);
00730 
00731 return Bmp;
00732 }
00733 
00734 geBitmap * geBitmapUtil_CreateFromFileAndAlphaNames(const geVFile * BaseFS,const char * BmName,const char *AlphaName)
00735 {
00736 geBitmap *Bmp,*AlphaBmp;
00737 
00738         Bmp = geBitmapUtil_CreateFromFileName(BaseFS,BmName);
00739         if ( ! Bmp )
00740                 return NULL;
00741 
00742         AlphaBmp = geBitmapUtil_CreateFromFileName(BaseFS,AlphaName);
00743         if ( ! AlphaBmp )
00744         {
00745                 geBitmap_Destroy(&Bmp);
00746                 return NULL;
00747         }
00748 
00749         if ( ! geBitmap_SetAlpha(Bmp,AlphaBmp) )
00750         {
00751                 geBitmap_Destroy(&Bmp);
00752                 geBitmap_Destroy(&AlphaBmp);
00753                 return NULL;
00754         }
00755 
00756         geBitmap_Destroy(&AlphaBmp);
00757 
00758         geBitmap_SetPreferredFormat(Bmp,GE_PIXELFORMAT_16BIT_4444_ARGB);
00759 
00760 return Bmp;
00761 }
00762 
00763 /*}{****** MSE bitmap compare stuff *********/
00764 
00765 static void RGBi_to_YUVi(int R,int G,int B,int *Y,int *U,int *V);
00766 static void YUVi_to_RGBi(int y,int u,int v,int *R,int *G,int *B);
00767 
00768 double geBitmapUtil_MSE2PSNR(double mse)
00769 {
00770 return ( 48.165 - 10.0*log10(mse));
00771 }
00772 
00773 double geBitmapUtil_PSNR2MSE(double psnr)
00774 {
00775 return pow(10.0,4.8165 - psnr*0.1);
00776 }
00777 
00778 geBoolean geBitmapUtil_CompareBitmaps(geBitmap *bm1,geBitmap *bm2,char * IntoStr,double * pMSE)
00779 {
00780 geBitmap *lock1,*lock2;
00781 uint8 *ptr1,*ptr2;
00782 geBitmap_Info wi,oi;
00783 double diff,mse;
00784 int x,y,w,h,cnt;
00785 geBoolean success;
00786 
00787         assert(bm1 && bm2);
00788 
00789         if ( ! geBitmap_LockForRead(bm1,&lock1,0,0,GE_PIXELFORMAT_32BIT_BGRA,0,0) )
00790                 return GE_FALSE;
00791         if ( ! geBitmap_LockForRead(bm2,&lock2,0,0,GE_PIXELFORMAT_32BIT_BGRA,0,0) )
00792                 return GE_FALSE;
00793 
00794         ptr1 = geBitmap_GetBits(lock1);
00795         ptr2 = geBitmap_GetBits(lock2);
00796         assert( ptr1 && ptr2 );
00797 
00798         success = geBitmap_GetInfo(lock1,&wi,NULL); assert(success);
00799         success = geBitmap_GetInfo(lock2,&oi,NULL); assert(success);
00800 
00801         h = min(oi.Height,wi.Height);
00802         w = min(oi.Width,wi.Width);
00803 
00804         diff = cnt = 0;
00805         for(y=h; y--; )
00806         {
00807                 for(x=w; x--;)
00808                 {
00809                 int dR,dG,dB,dA,R,G,B,A;
00810                         dA = *ptr1++; dR = *ptr1++; dG = *ptr1++; dB = *ptr1++;
00811                         A  = *ptr2++; R  = *ptr2++; G  = *ptr2++; B  = *ptr2++;
00812 
00813                         RGBi_to_YUVi(dR,dG,dB,&dR,&dG,&dB);
00814                         RGBi_to_YUVi( R, G, B, &R, &G, &B);
00815 
00816                         dA -= A;
00817                         dR -= R;
00818                         dG -= G;
00819                         dB -= B;
00820 
00821                         if ( dA )
00822                         {
00823                                 diff += dA*dA;
00824                         }
00825 
00826                         if ( A > 40 )
00827                         {
00828                                 diff +=(dR*dR + dG*dG + dB*dB);
00829                                 cnt ++;
00830                         }
00831                 }
00832                 ptr1 += (wi.Stride - w)*4;
00833                 ptr2 += (oi.Stride - w)*4;
00834         }
00835 
00836         geBitmap_UnLock(lock1);
00837         geBitmap_UnLock(lock2);
00838 
00839         mse = diff / (double)cnt;
00840         if ( pMSE )
00841                 *pMSE = mse;
00842         if ( IntoStr )
00843                 sprintf(IntoStr,"mse = %f, rmse = %f, psnr = %f",mse,sqrt(mse),geBitmapUtil_MSE2PSNR(mse));
00844 
00845 return GE_TRUE;
00846 }
00847 
00848 /*}{*************** the YUV routines : ******************/
00849 
00850 #define YUV_SHIFT       14
00851 #define YUV_HALF        (1<<(YUV_SHIFT-1))
00852 #define YUV_ONE         (1<<YUV_SHIFT)
00853 #define Y_R   ((int)( 0.29900 * YUV_ONE ))
00854 #define Y_G   ((int)( 0.58700 * YUV_ONE ))
00855 #define Y_B   ((int)( 0.11400 * YUV_ONE ))
00856 #define U_R   ((int)(-0.16874 * YUV_ONE ))
00857 #define U_G   ((int)(-0.33126 * YUV_ONE ))
00858 #define U_B   ((int)( 0.50000 * YUV_ONE ))
00859 #define V_R   ((int)(-0.50000 * YUV_ONE ))      // ** important sign change of 'V' from jpeg default
00860 #define V_G   ((int)( 0.41869 * YUV_ONE ))
00861 #define V_B   ((int)( 0.08131 * YUV_ONE ))
00862 #define R_Y   (                                 YUV_ONE )       
00863 #define R_U   (0)
00864 #define R_V   ((int)(-1.40200 * YUV_ONE ))
00865 #define G_Y   (                                 YUV_ONE )       
00866 #define G_U   ((int)(-0.34414 * YUV_ONE ))
00867 #define G_V   ((int)( 0.71414 * YUV_ONE ))
00868 #define B_Y   (                         YUV_ONE )       
00869 #define B_U   ((int)( 1.77200 * YUV_ONE ))
00870 #define B_V   (0)       
00871 
00872 #define Y_RGB(R,G,B) (( Y_R * (R) + Y_G * (G) + Y_B * (B) + YUV_HALF ) >> YUV_SHIFT)
00873 #define U_RGB(R,G,B) (( U_R * (R) + U_G * (G) + U_B * (B) + YUV_HALF ) >> YUV_SHIFT)
00874 #define V_RGB(R,G,B) (( V_R * (R) + V_G * (G) + V_B * (B) + YUV_HALF ) >> YUV_SHIFT)
00875 #define R_YUV(Y,U,V) (( R_Y * (Y) + R_U * (U) + R_V * (V) + YUV_HALF ) >> YUV_SHIFT)
00876 #define G_YUV(Y,U,V) (( G_Y * (Y) + G_U * (U) + G_V * (V) + YUV_HALF ) >> YUV_SHIFT)
00877 #define B_YUV(Y,U,V) (( B_Y * (Y) + B_U * (U) + B_V * (V) + YUV_HALF ) >> YUV_SHIFT)
00878 
00879 #define minmax(x,lo,hi) ( (x)<(lo)?(lo):( (x)>(hi)?(hi):(x)) )
00880 
00881 static void RGBi_to_YUVi(int R,int G,int B,int *Y,int *U,int *V)
00882 {
00883         *Y = Y_RGB(R,G,B);
00884         *U = U_RGB(R,G,B) + 127;
00885         *V = V_RGB(R,G,B) + 127;
00886 }
00887 
00888 static void YUVi_to_RGBi(int y,int u,int v,int *R,int *G,int *B)
00889 {
00890 int r,g,b;
00891 
00892         u -= 127;
00893         v -= 127;
00894         r = R_YUV(y,u,v);
00895         g = G_YUV(y,u,v);
00896         b = B_YUV(y,u,v);
00897 
00898         *R = minmax(r,0,255);   // we could get negative ones and whatnot
00899         *G = minmax(g,0,255);   //      because the y,u,v are not really 24 bits;
00900         *B = minmax(b,0,255);   //      there are regions of YUV space that will never be reached by RGBb_to_YUVb
00901 }
00902 
00903 

Generated on Tue Sep 30 12:35:48 2003 for GTestAndEngine by doxygen 1.3.2