00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "stdmisc.h"
00027
00028 #include "nel/misc/rgba.h"
00029 #include "nel/misc/stream.h"
00030 #include "nel/misc/system_info.h"
00031 #include "nel/misc/common.h"
00032
00033
00034 namespace NLMISC {
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00048 const CRGBA CRGBA::Black(0, 0, 0) ;
00049 const CRGBA CRGBA::Red(255, 0, 0) ;
00050 const CRGBA CRGBA::Green(0, 255, 0) ;
00051 const CRGBA CRGBA::Yellow(255, 255, 0) ;
00052 const CRGBA CRGBA::Blue(0, 0, 255) ;
00053 const CRGBA CRGBA::Magenta(255, 0, 255) ;
00054 const CRGBA CRGBA::Cyan(0, 255, 255) ;
00055 const CRGBA CRGBA::White(255, 255, 255) ;
00056
00057
00058 void CRGBA::serial(class NLMISC::IStream &f)
00059 {
00060 f.serial (R);
00061 f.serial (G);
00062 f.serial (B);
00063 f.serial (A);
00064 }
00065
00066 void CRGBA::set(uint8 r, uint8 g, uint8 b, uint8 a)
00067 {
00068 R = r;
00069 G = g;
00070 B = b;
00071 A = a;
00072 }
00073
00074 #ifdef NL_OS_WINDOWS
00075 #pragma warning(disable : 4731)
00076 #endif
00077
00078
00079 void CRGBA::addColors(CRGBA *dest, const CRGBA *src1, const CRGBA *src2, uint numColors, uint srcStride, uint destStride, uint dup)
00080 {
00081 if (numColors == 0) return;
00082 #if defined(NL_OS_WINDOWS) && !defined(DISABLE_MMX_OPTIM)
00083 if (!CSystemInfo::hasMMX())
00084 #endif
00085 {
00086 if (dup == 1)
00087 {
00088 while (numColors--)
00089 {
00090 dest->add(*src1, *src2);
00091 dest = (CRGBA *) ((uint8 *) dest + destStride);
00092 src1 = (CRGBA *) ((uint8 *) src1 + srcStride);
00093 src2 = (CRGBA *) ((uint8 *) src2 + srcStride);
00094 }
00095 }
00096 else
00097 {
00098 if (dup == 4)
00099 {
00100 while (numColors--)
00101 {
00102 dest->add(*src1, *src2);
00103 * (CRGBA *) ((uint8 *) dest + destStride) = *dest;
00104 dest = (CRGBA *) ((uint8 *) dest + destStride);
00105 * (CRGBA *) ((uint8 *) dest + destStride) = *dest;
00106 dest = (CRGBA *) ((uint8 *) dest + destStride);
00107 * (CRGBA *) ((uint8 *) dest + destStride) = *dest;
00108 dest = (CRGBA *) ((uint8 *) dest + (destStride << 1));
00109
00110 src1 = (CRGBA *) ((uint8 *) src1 + srcStride);
00111 src2 = (CRGBA *) ((uint8 *) src2 + srcStride);
00112 }
00113 }
00114 else
00115 {
00116 while (numColors--)
00117 {
00118 dest->add(*src1, *src2);
00119
00120 uint k = dup - 1;
00121 do
00122 {
00123 * (CRGBA *) ((uint8 *) dest + destStride) = *dest;
00124 dest = (CRGBA *) ((uint8 *) dest + destStride);
00125 }
00126 while (--k);
00127
00128 dest = (CRGBA *) ((uint8 *) dest + destStride);
00129 src1 = (CRGBA *) ((uint8 *) src1 + srcStride);
00130 src2 = (CRGBA *) ((uint8 *) src2 + srcStride);
00131 }
00132 }
00133 }
00134 }
00135 #if defined(NL_OS_WINDOWS) && !defined(DISABLE_MMX_OPTIM)
00136 else
00137 {
00139 if (dup == 1)
00140 {
00141 __asm
00142 {
00143 push ebp
00144 mov edi, dest
00145 mov esi, src1
00146 mov ebx, src2
00147 sub ebx, esi ; offset to source 2
00148 mov ecx, numColors
00149 mov edx, destStride
00150 mov ebp, srcStride
00151 sub edi, edx
00152 myLoop:
00153 movd mm0, [esi]
00154 add edi, edx
00155 movd mm1, [esi + ebx]
00156 paddusb mm0, mm1
00157 movd [edi], mm0
00158 add esi, ebp
00159 dec ecx
00160 jne myLoop
00161 pop ebp
00162 emms
00163 }
00164 }
00165 else
00166 {
00167 if (dup == 4)
00168 {
00169 __asm
00170 {
00171 push ebp
00172 mov edi, dest
00173 mov esi, src1
00174 mov ebx, src2
00175 sub ebx, esi ; offset to source 2
00176 mov ecx, numColors
00177 mov edx, destStride
00178 mov ebp, srcStride
00179 myLoop4:
00180 movd mm0, [esi]
00181 movd mm1, [esi + ebx]
00182 paddusb mm0, mm1
00183 movd eax, mm0
00184
00185 mov [edi], eax
00186 mov [edi + edx], eax
00187 mov [edi + 2 * edx], eax
00188 lea edi, [edi + edx * 2]
00189 mov [edi + edx], eax
00190 lea edi, [edi + edx * 2]
00191 add esi, ebp
00192
00193 dec ecx
00194 jne myLoop4
00195 pop ebp
00196 emms
00197 }
00198 }
00199 else
00200 {
00201 __asm
00202 {
00203 push ebp
00204 mov edi, dest
00205 mov esi, src1
00206 mov ebx, src2
00207 sub ebx, esi ; offset to source 2
00208 mov ecx, numColors
00209 mov edx, destStride
00210 mov eax, dup
00211 mov ebp, srcStride
00212 push eax
00213 myLoopN:
00214 movd mm0, [esi]
00215 movd mm1, [esi + ebx]
00216 push ecx
00217 paddusb mm0, mm1
00218 mov ecx, 4[esp]
00219 movd eax, mm0
00220 dupLoopN:
00221 mov [edi], eax
00222 dec ecx
00223 lea edi, [edi + edx]
00224 jne dupLoopN
00225 pop ecx ; get back the loop counter
00226 add esi, ebp
00227 dec ecx
00228 jne myLoopN
00229 pop eax
00230 pop ebp
00231 emms
00232 }
00233 }
00234 }
00235 }
00236 #endif
00237 }
00238
00239 void CRGBA::modulateColors(CRGBA *dest, const CRGBA *src1, const CRGBA *src2, uint numColors, uint srcStride, uint destStride, uint dup)
00240 {
00241 #if defined(NL_OS_WINDOWS) && !defined(DISABLE_MMX_OPTIM)
00242 if (!CSystemInfo::hasMMX())
00243 #endif
00244 {
00245 if (dup == 1)
00246 {
00247 while (numColors--)
00248 {
00249 dest->modulateFromColor(*src1, *src2);
00250 dest = (CRGBA *) ((uint8 *) dest + destStride);
00251 src1 = (CRGBA *) ((uint8 *) src1 + srcStride);
00252 src2 = (CRGBA *) ((uint8 *) src2 + srcStride);
00253 }
00254 }
00255 else
00256 {
00257 if (dup == 4)
00258 {
00259 while (numColors--)
00260 {
00261 dest->modulateFromColor(*src1, *src2);
00262 * (CRGBA *) ((uint8 *) dest + destStride) = *dest;
00263 dest = (CRGBA *) ((uint8 *) dest + destStride);
00264 * (CRGBA *) ((uint8 *) dest + destStride) = *dest;
00265 dest = (CRGBA *) ((uint8 *) dest + destStride);
00266 * (CRGBA *) ((uint8 *) dest + destStride) = *dest;
00267 dest = (CRGBA *) ((uint8 *) dest + (destStride << 1));
00268
00269 src1 = (CRGBA *) ((uint8 *) src1 + srcStride);
00270 src2 = (CRGBA *) ((uint8 *) src2 + srcStride);
00271 }
00272 }
00273 else
00274 {
00275 while (numColors--)
00276 {
00277 dest->modulateFromColor(*src1, *src2);
00278
00279 uint k = dup - 1;
00280 do
00281 {
00282 * (CRGBA *) ((uint8 *) dest + destStride) = *dest;
00283 dest = (CRGBA *) ((uint8 *) dest + destStride);
00284 }
00285 while (--k);
00286
00287 dest = (CRGBA *) ((uint8 *) dest + destStride);
00288 src1 = (CRGBA *) ((uint8 *) src1 + srcStride);
00289 src2 = (CRGBA *) ((uint8 *) src2 + srcStride);
00290 }
00291 }
00292 }
00293 }
00294 #if defined(NL_OS_WINDOWS) && !defined(DISABLE_MMX_OPTIM)
00295 else
00296 {
00297 uint64 blank = 0;
00299 if (dup == 1)
00300 { __asm
00301 {
00302 push ebp
00303 movq mm2, blank
00304 mov edi, dest
00305 mov esi, src1
00306 mov ebx, src2
00307 sub ebx, esi ; offset to source 2
00308 mov ecx, numColors
00309 mov edx, destStride
00310 mov ebp, srcStride
00311 myLoop:
00312 movd mm0, [esi]
00313 movd mm1, [esi + ebx]
00314 punpcklbw mm0, mm2
00315 punpcklbw mm1, mm2
00316 pmullw mm0, mm1
00317 psrlw mm0, 8
00318 packuswb mm0, mm0
00319 movd [edi], mm0
00320 add edi, edx
00321 add esi, ebp
00322
00323 dec ecx
00324 jne myLoop
00325 pop ebp
00326 emms
00327 }
00328 }
00329 else
00330 {
00331 if (dup == 4)
00332 {
00333
00334 __asm
00335 {
00336 push ebp
00337 movq mm2, blank
00338 mov edi, dest
00339 mov esi, src1
00340 mov ebx, src2
00341 sub ebx, esi ; offset to source 2
00342 mov ecx, numColors
00343 mov edx, destStride
00344 mov ebp, srcStride
00345 myLoop4:
00346 movd mm0, [esi]
00347 movd mm1, [esi + ebx]
00348 punpcklbw mm0, mm2
00349 punpcklbw mm1, mm2
00350 pmullw mm0, mm1
00351 psrlw mm0, 8
00352 packuswb mm0, mm0
00353 movd eax, mm0
00354 ; duplicate the result 4 times
00355 mov [edi], eax
00356 mov [edi + edx], eax
00357 mov [edi + 2 * edx], eax
00358 lea edi, [edi + 2 * edx]
00359 mov [edi + edx], eax
00360 lea edi, [edi + 2 * edx]
00361 add esi, ebp
00362 dec ecx
00363 jne myLoop4
00364 pop ebp
00365 emms
00366 }
00367 }
00368 else
00369 {
00370 __asm
00371 {
00372 push ebp
00373 mov edi, dest
00374 mov esi, src1
00375 mov ebx, src2
00376 sub ebx, esi ; offset to source 2
00377 mov ecx, numColors
00378 mov edx, destStride
00379 mov eax, dup
00380 mov ebp, srcStride
00381 push eax
00382 myLoopN:
00383 movd mm0, [esi]
00384 movd mm1, [esi + ebx]
00385 punpcklbw mm0, mm2
00386 punpcklbw mm1, mm2
00387 pmullw mm0, mm1
00388 push ecx
00389 psrlw mm0, 8
00390 mov ecx, 4[esp]
00391 packuswb mm0, mm0
00392 movd eax, mm0
00393 dupLoopN:
00394 mov [edi], eax
00395 dec ecx
00396 lea edi, [edi + edx]
00397 jne dupLoopN
00398 pop ecx ; get back the loop counter
00399 add esi, ebp
00400 dec ecx
00401 jne myLoopN
00402 pop eax
00403 pop ebp
00404 emms
00405 }
00406 }
00407 }
00408 }
00409 #endif
00410 }
00411
00412 void CRGBA::subtractColors(CRGBA *dest, const CRGBA *src1, const CRGBA *src2, uint numColors, uint srcStride, uint destStride, uint dup)
00413 {
00414 if (numColors == 0) return;
00415 #if defined(NL_OS_WINDOWS) && !defined(DISABLE_MMX_OPTIM)
00416 if (!CSystemInfo::hasMMX())
00417 #endif
00418 {
00419 if (dup == 1)
00420 {
00421 while (numColors--)
00422 {
00423 dest->sub(*src1, *src2);
00424 dest = (CRGBA *) ((uint8 *) dest + destStride);
00425 src1 = (CRGBA *) ((uint8 *) src1 + srcStride);
00426 src2 = (CRGBA *) ((uint8 *) src2 + srcStride);
00427 }
00428 }
00429 else
00430 {
00431 if (dup == 4)
00432 {
00433 while (numColors--)
00434 {
00435 dest->sub(*src1, *src2);
00436 * (CRGBA *) ((uint8 *) dest + destStride) = *dest;
00437 dest = (CRGBA *) ((uint8 *) dest + destStride);
00438 * (CRGBA *) ((uint8 *) dest + destStride) = *dest;
00439 dest = (CRGBA *) ((uint8 *) dest + destStride);
00440 * (CRGBA *) ((uint8 *) dest + destStride) = *dest;
00441 dest = (CRGBA *) ((uint8 *) dest + (destStride << 1));
00442
00443 src1 = (CRGBA *) ((uint8 *) src1 + srcStride);
00444 src2 = (CRGBA *) ((uint8 *) src2 + srcStride);
00445 }
00446 }
00447 else
00448 {
00449 while (numColors--)
00450 {
00451 dest->sub(*src1, *src2);
00452
00453 uint k = dup - 1;
00454 do
00455 {
00456 * (CRGBA *) ((uint8 *) dest + destStride) = *dest;
00457 dest = (CRGBA *) ((uint8 *) dest + destStride);
00458 }
00459 while (--k);
00460
00461 dest = (CRGBA *) ((uint8 *) dest + destStride);
00462 src1 = (CRGBA *) ((uint8 *) src1 + srcStride);
00463 src2 = (CRGBA *) ((uint8 *) src2 + srcStride);
00464 }
00465 }
00466 }
00467 }
00468 #if defined(NL_OS_WINDOWS) && !defined(DISABLE_MMX_OPTIM)
00469 else
00470 {
00472 if (dup == 1)
00473 {
00474 __asm
00475 {
00476 push ebp
00477 mov edi, dest
00478 mov esi, src1
00479 mov ebx, src2
00480 sub ebx, esi ; offset to source 2
00481 mov ecx, numColors
00482 mov edx, destStride
00483 mov ebp, srcStride
00484 sub edi, edx
00485 myLoop:
00486 movd mm0, [esi]
00487 add edi, edx
00488 movd mm1, [esi + ebx]
00489 psubusb mm0, mm1
00490 movd [edi], mm0
00491 add esi, ebp
00492 dec ecx
00493 jne myLoop
00494 pop ebp
00495 emms
00496 }
00497 }
00498 else
00499 {
00500 if (dup == 4)
00501 {
00502 __asm
00503 {
00504 push ebp
00505 mov edi, dest
00506 mov esi, src1
00507 mov ebx, src2
00508 sub ebx, esi ; offset to source 2
00509 mov ecx, numColors
00510 mov edx, destStride
00511 mov ebp, srcStride
00512 myLoop4:
00513 movd mm0, [esi]
00514 movd mm1, [esi + ebx]
00515 psubusb mm0, mm1
00516 movd eax, mm0
00517
00518 mov [edi], eax
00519 mov [edi + edx], eax
00520 mov [edi + 2 * edx], eax
00521 lea edi, [edi + edx * 2]
00522 mov [edi + edx], eax
00523 lea edi, [edi + edx * 2]
00524 add esi, ebp
00525
00526 dec ecx
00527 jne myLoop4
00528 pop ebp
00529 emms
00530 }
00531 }
00532 else
00533 {
00534 __asm
00535 {
00536 push ebp
00537 mov edi, dest
00538 mov esi, src1
00539 mov ebx, src2
00540 sub ebx, esi ; offset to source 2
00541 mov ecx, numColors
00542 mov edx, destStride
00543 mov eax, dup
00544 mov ebp, srcStride
00545 push eax
00546 myLoopN:
00547 movd mm0, [esi]
00548 movd mm1, [esi + ebx]
00549 push ecx
00550 psubusb mm0, mm1
00551 mov ecx, 4[esp]
00552 movd eax, mm0
00553 dupLoopN:
00554 mov [edi], eax
00555 dec ecx
00556 lea edi, [edi + edx]
00557 jne dupLoopN
00558 pop ecx ; get back the loop counter
00559 add esi, ebp
00560 dec ecx
00561 jne myLoopN
00562 pop eax
00563 pop ebp
00564 emms
00565 }
00566 }
00567 }
00568 }
00569 #endif
00570 }
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580 void CBGRA::serial(class NLMISC::IStream &f)
00581 {
00582 f.serial (B);
00583 f.serial (G);
00584 f.serial (R);
00585 f.serial (A);
00586 }
00587
00588 void CBGRA::set(uint8 r, uint8 g, uint8 b, uint8 a)
00589 {
00590 R = r;
00591 G = g;
00592 B = b;
00593 A = a;
00594 }
00595
00596 void CBGRA::blendFromui(CBGRA &c0, CBGRA &c1, uint coef)
00597 {
00598 int a1 = coef;
00599 int a2 = 256-a1;
00600 R = (c0.R*a2 + c1.R*a1) >>8;
00601 G = (c0.G*a2 + c1.G*a1) >>8;
00602 B = (c0.B*a2 + c1.B*a1) >>8;
00603 A = (c0.A*a2 + c1.A*a1) >>8;
00604 }
00605
00606
00607
00608 bool CRGBA::convertToHLS(float &h, float &l, float &s) const
00609 {
00610 float r = R / 255.f;
00611 float g = G / 255.f;
00612 float b = B / 255.f;
00613
00614 float maxV = NLMISC::maxof(r, g, b);
00615 float minV = NLMISC::minof(r, g, b);
00616
00618 l = 0.5f * (maxV + minV);
00619
00621 if (minV == maxV)
00622 {
00623 s = 0;
00624 return true;
00625 }
00626 float diff = maxV - minV;
00628 s = l > 0.5f ?
00629 diff / (2.f - maxV - minV) :
00630 diff / (maxV + minV);
00631
00632
00633
00634 if (maxV == r)
00635 {
00636 h = (g - b) / diff;
00637 }
00638 else if (maxV == g)
00639 {
00640 h = 2.f + (b - r) / diff;
00641 }
00642 else
00643 {
00644 h = 4.f + (r - g) / diff;
00645 }
00646
00647 h *= 60.f;
00648
00649 if (h < 0.f) h += 360.f;
00650
00651 return false;
00652 }
00653
00654
00655
00657
00658 {
00659
00660
00661
00662 if (h > 360.f) h -= 360.f;
00663 else if (h < 0) h += 360.f;
00664
00665 if (h < 60.f)
00666 {
00667 return v1 + (v2 - v1) * h / 60.f;
00668 }
00669 else if (h < 180.f)
00670 {
00671 return v2;
00672 }
00673 else if (h < 240.f)
00674 {
00675 return v1 + (v2 - v1) * (240.f - h) / 60.f;
00676 }
00677 else
00678 {
00679 return v1;
00680 }
00681 }
00682
00683
00684
00685 void CRGBA::buildFromHLS(float h, float l, float s)
00686 {
00687 clamp(l, 0, 1);
00688 clamp(s, 0, 1);
00689
00690 float v2 = (l <= 0.5f) ? (l * (1 + s)) : (l + s - l * s);
00691 float v1 = 2.f * l - v2;
00692
00693 if (s == 0)
00694 {
00695 R = G = B = (uint8) (255.f * l);
00696 }
00697 else
00698 {
00699 float v;
00700
00701 v = HLSValue(h + 120.f, v1, v2);
00702 clamp(v, 0.f, 1.f);
00703 R = (uint8) (255.f * v);
00704
00705 v = HLSValue(h, v1, v2);
00706 clamp(v, 0.f, 1.f);
00707 G = (uint8) (255.f * v);
00708
00709 v = HLSValue(h - 120.f, v1, v2);
00710 clamp(v, 0.f, 1.f);
00711 B = (uint8) (255.f * v);
00712 }
00713 }
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724 void CRGBAF::serial(class NLMISC::IStream &f)
00725 {
00726 f.serial (R);
00727 f.serial (G);
00728 f.serial (B);
00729 f.serial (A);
00730 }
00731
00732 void CRGBAF::set(float r, float g, float b, float a)
00733 {
00734 R = r;
00735 G = g;
00736 B = b;
00737 A = a;
00738 }
00739
00740
00741
00742
00743
00744 }