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
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
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
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
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
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
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
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
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
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
00386
00387 mainloop:
00388 xor eax,eax
00389
00390 movzx edx,BYTE PTR [esi+1]
00391 add eax,edx
00392
00393 movzx edx,BYTE PTR [esi-1]
00394 add eax,edx
00395
00396 mov ecx,esi
00397 add ecx,s
00398 movzx edx,BYTE PTR [ecx]
00399 add eax,edx
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
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
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
00470 mov edi, pDst
00471
00472
00473 mainloop2:
00474 xor eax,eax
00475
00476 movzx edx,BYTE PTR [esi+1]
00477 add eax,edx
00478
00479 movzx edx,BYTE PTR [esi-1]
00480 add eax,edx
00481
00482 mov ecx,esi
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
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
00545
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
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
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
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);
00899 *G = minmax(g,0,255);
00900 *B = minmax(b,0,255);
00901 }
00902
00903