1 /* 2 * Copyright 2006, Haiku. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Stephan Aßmus <superstippi@gmx.de> 7 */ 8 9 #ifndef BLENDING_H 10 #define BLENDING_H 11 12 #include <SupportDefs.h> 13 14 // faster bit error version: 15 //#define INT_MULT(a, b, t) ((t) = (a) * (b), ((((t) >> 8) + (t)) >> 8)) 16 // correct version 17 #define INT_MULT(a, b, t) ((t) = (a) * (b) + 0x80, ((((t) >> 8) + (t)) >> 8)) 18 19 #define INT_LERP(p, q, a, t) ((p) + INT_MULT(a, ((q) - (p)), t)) 20 21 #define INT_PRELERP(p, q, a, t) ((p) + (q) - INT_MULT(a, p, t)) 22 23 24 25 #define GAMMA_BLEND 1 26 27 #if GAMMA_BLEND 28 29 extern uint16* kGammaTable; 30 extern uint8* kInverseGammaTable; 31 32 void init_gamma_blending(); 33 void uninit_gamma_blending(); 34 35 // blend 36 inline void 37 blend_gamma(uint16 b1, uint16 b2, uint16 b3, uint8 ba, // bottom components 38 uint16 t1, uint16 t2, uint16 t3, uint8 ta, // top components 39 uint8* d1, uint8* d2, uint8* d3, uint8* da) // dest components 40 { 41 if (ba == 255) { 42 uint32 destAlpha = 255 - ta; 43 *d1 = kInverseGammaTable[(b1 * destAlpha + t1 * ta) / 255]; 44 *d2 = kInverseGammaTable[(b2 * destAlpha + t2 * ta) / 255]; 45 *d3 = kInverseGammaTable[(b3 * destAlpha + t3 * ta) / 255]; 46 *da = 255; 47 } else { 48 uint8 alphaRest = 255 - ta; 49 register uint32 alphaTemp = (65025 - alphaRest * (255 - ba)); 50 uint32 alphaDest = ba * alphaRest; 51 uint32 alphaSrc = 255 * ta; 52 *d1 = kInverseGammaTable[(b1 * alphaDest + t1 * alphaSrc) / alphaTemp]; 53 *d2 = kInverseGammaTable[(b2 * alphaDest + t2 * alphaSrc) / alphaTemp]; 54 *d3 = kInverseGammaTable[(b3 * alphaDest + t3 * alphaSrc) / alphaTemp]; 55 *da = alphaTemp / 255; 56 } 57 } 58 59 // blend 60 inline void 61 blend(uint8 b1, uint8 b2, uint8 b3, uint8 ba, // bottom components 62 uint8 t1, uint8 t2, uint8 t3, uint8 ta, // top components 63 uint8* d1, uint8* d2, uint8* d3, uint8* da) // dest components 64 { 65 // convert to linear rgb 66 uint16 gt1 = kGammaTable[t1]; 67 uint16 gt2 = kGammaTable[t2]; 68 uint16 gt3 = kGammaTable[t3]; 69 70 uint16 gb1 = kGammaTable[b1]; 71 uint16 gb2 = kGammaTable[b2]; 72 uint16 gb3 = kGammaTable[b3]; 73 74 blend_gamma(gb1, gb2, gb3, ba, 75 gt1, gt2, gt3, ta, 76 d1, d2, d3, da); 77 } 78 79 // convert_to_gamma 80 // 81 // converted value will be gamma corrected in the range [0...2550] 82 // and can be passed on to the other functions that take uint16 components 83 uint16 84 convert_to_gamma(uint8 value); 85 86 // blend_colors_copy 87 inline void 88 blend_colors_copy(uint8* bottom, uint8 alpha, uint8* dest, 89 uint8 c1, uint8 c2, uint8 c3, 90 uint16 gc1, uint16 gc2, uint16 gc3) 91 { 92 if (alpha > 0) { 93 if (bottom[3] == 0 || alpha == 255) { 94 dest[0] = c1; 95 dest[1] = c2; 96 dest[2] = c3; 97 dest[3] = alpha; 98 } else { 99 // only bottom components need to be gamma corrected 100 uint16 gb1 = kGammaTable[bottom[0]]; 101 uint16 gb2 = kGammaTable[bottom[1]]; 102 uint16 gb3 = kGammaTable[bottom[2]]; 103 104 blend_gamma(gb1, gb2, gb3, bottom[3], 105 gc1, gc2, gc3, alpha, 106 &dest[0], &dest[1], &dest[2], &dest[3]); 107 } 108 } else { 109 *((uint32*)dest) = *((uint32*)bottom); 110 } 111 } 112 113 // blend_colors 114 inline void 115 blend_colors(uint8* bottom, uint8 alpha, 116 uint8 c1, uint8 c2, uint8 c3, 117 uint16 gc1, uint16 gc2, uint16 gc3) 118 { 119 if (alpha > 0) { 120 if (bottom[3] == 0 || alpha == 255) { 121 bottom[0] = c1; 122 bottom[1] = c2; 123 bottom[2] = c3; 124 bottom[3] = alpha; 125 } else { 126 // only bottom components need to be gamma corrected 127 uint16 gb1 = kGammaTable[bottom[0]]; 128 uint16 gb2 = kGammaTable[bottom[1]]; 129 uint16 gb3 = kGammaTable[bottom[2]]; 130 131 blend_gamma(gb1, gb2, gb3, bottom[3], 132 gc1, gc2, gc3, alpha, 133 &bottom[0], &bottom[1], &bottom[2], &bottom[3]); 134 } 135 } 136 } 137 138 // blend_colors_copy 139 inline void 140 blend_colors_copy(uint8* bottom, uint8 alpha, uint8* dest, 141 uint8 c1, uint8 c2, uint8 c3) 142 { 143 if (alpha > 0) { 144 if (bottom[3] == 0 || alpha == 255) { 145 dest[0] = c1; 146 dest[1] = c2; 147 dest[2] = c3; 148 dest[3] = alpha; 149 } else { 150 blend(bottom[0], bottom[1], bottom[2], bottom[3], 151 c1, c2, c3, alpha, 152 &dest[0], &dest[1], &dest[2], &dest[3]); 153 } 154 } else { 155 *((uint32*)dest) = *((uint32*)bottom); 156 } 157 } 158 159 // blend_colors 160 inline void 161 blend_colors(uint8* bottom, uint8 alpha, uint8 c1, uint8 c2, uint8 c3) 162 { 163 if (alpha > 0) { 164 if (bottom[3] == 0 || alpha == 255) { 165 bottom[0] = c1; 166 bottom[1] = c2; 167 bottom[2] = c3; 168 bottom[3] = alpha; 169 } else { 170 blend(bottom[0], bottom[1], bottom[2], bottom[3], 171 c1, c2, c3, alpha, 172 &bottom[0], &bottom[1], &bottom[2], &bottom[3]); 173 } 174 } 175 } 176 177 // blend_colors 178 inline void 179 blend_colors(uint8* bottom, uint8* source, uint8 alphaOverride) 180 { 181 uint8 alpha = (source[3] * alphaOverride) / 255; 182 if (alpha > 0) { 183 if (bottom[3] == 0 || alpha == 255) { 184 bottom[0] = source[0]; 185 bottom[1] = source[1]; 186 bottom[2] = source[2]; 187 bottom[3] = alpha; 188 } else { 189 blend(bottom[0], bottom[1], bottom[2], bottom[3], 190 source[0], source[1], source[2], alpha, 191 &bottom[0], &bottom[1], &bottom[2], &bottom[3]); 192 } 193 } 194 } 195 196 // blend_colors 197 inline void 198 blend_colors(uint8* bottom, uint8* source) 199 { 200 if (source[3] > 0) { 201 if (bottom[3] == 0 || source[3] == 255) { 202 bottom[0] = source[0]; 203 bottom[1] = source[1]; 204 bottom[2] = source[2]; 205 bottom[3] = source[3]; 206 } else { 207 blend(bottom[0], bottom[1], bottom[2], bottom[3], 208 source[0], source[1], source[2], source[3], 209 &bottom[0], &bottom[1], &bottom[2], &bottom[3]); 210 } 211 } 212 } 213 214 // blend_colors_copy 215 inline void 216 blend_colors_copy(uint8* dest, uint8* bottom, uint8* top) 217 { 218 if (bottom[3] == 0 || top[3] == 255) { 219 dest[0] = top[0]; 220 dest[1] = top[1]; 221 dest[2] = top[2]; 222 dest[3] = top[3]; 223 } else { 224 blend(bottom[0], bottom[1], bottom[2], bottom[3], 225 top[0], top[1], top[2], top[3], 226 &dest[0], &dest[1], &dest[2], &dest[3]); 227 } 228 } 229 230 // blend_pixels 231 inline void 232 blend_pixels(uint8* bottom, uint8* top, uint8 alpha) 233 { 234 if (alpha > 0) { 235 if (alpha == 255) { 236 bottom[0] = top[0]; 237 bottom[1] = top[1]; 238 bottom[2] = top[2]; 239 bottom[3] = top[3]; 240 } else { 241 // convert to linear rgb 242 uint16 t1 = kGammaTable[top[0]]; 243 uint16 t2 = kGammaTable[top[1]]; 244 uint16 t3 = kGammaTable[top[2]]; 245 uint16 b1 = kGammaTable[bottom[0]]; 246 uint16 b2 = kGammaTable[bottom[1]]; 247 uint16 b3 = kGammaTable[bottom[2]]; 248 249 uint8 mergeAlpha = bottom[3] ? (top[3] * alpha) / 255 : 255; 250 uint8 invAlpha = 255 - mergeAlpha; 251 bottom[0] = kInverseGammaTable[(b1 * invAlpha + t1 * mergeAlpha) / 255]; 252 bottom[1] = kInverseGammaTable[(b2 * invAlpha + t2 * mergeAlpha) / 255]; 253 bottom[2] = kInverseGammaTable[(b3 * invAlpha + t3 * mergeAlpha) / 255]; 254 bottom[3] = (bottom[3] * (255 - alpha) + top[3] * alpha) / 255; 255 } 256 } 257 } 258 259 // blend_pixels_copy 260 inline void 261 blend_pixels_copy(uint8* bottom, uint8* top, uint8* dest, uint8 alpha) 262 { 263 if (alpha > 0) { 264 if (alpha == 255) { 265 dest[0] = top[0]; 266 dest[1] = top[1]; 267 dest[2] = top[2]; 268 dest[3] = top[3]; 269 } else { 270 // convert to linear rgb 271 uint16 t1 = kGammaTable[top[0]]; 272 uint16 t2 = kGammaTable[top[1]]; 273 uint16 t3 = kGammaTable[top[2]]; 274 uint16 b1 = kGammaTable[bottom[0]]; 275 uint16 b2 = kGammaTable[bottom[1]]; 276 uint16 b3 = kGammaTable[bottom[2]]; 277 278 uint8 mergeAlpha = bottom[3] ? (top[3] * alpha) / 255 : 255; 279 uint8 invAlpha = 255 - mergeAlpha; 280 dest[0] = kInverseGammaTable[(b1 * invAlpha + t1 * mergeAlpha) / 255]; 281 dest[1] = kInverseGammaTable[(b2 * invAlpha + t2 * mergeAlpha) / 255]; 282 dest[2] = kInverseGammaTable[(b3 * invAlpha + t3 * mergeAlpha) / 255]; 283 dest[3] = (bottom[3] * (255 - alpha) + top[3] * alpha) / 255; 284 } 285 } else { 286 dest[0] = bottom[0]; 287 dest[1] = bottom[1]; 288 dest[2] = bottom[2]; 289 dest[3] = bottom[3]; 290 } 291 } 292 293 // blend_pixels_overlay 294 inline void 295 blend_pixels_overlay(uint8* bottom, uint8* top, uint8 alphaOverride) 296 { 297 uint8 alpha = (top[3] * alphaOverride) / 255; 298 if (alpha > 0) { 299 if (alpha == 255) { 300 bottom[0] = top[0]; 301 bottom[1] = top[1]; 302 bottom[2] = top[2]; 303 bottom[3] = top[3]; 304 } else { 305 // convert to linear rgb 306 uint16 t1 = kGammaTable[top[0]]; 307 uint16 t2 = kGammaTable[top[1]]; 308 uint16 t3 = kGammaTable[top[2]]; 309 uint16 b1 = kGammaTable[bottom[0]]; 310 uint16 b2 = kGammaTable[bottom[1]]; 311 uint16 b3 = kGammaTable[bottom[2]]; 312 313 uint8 mergeAlpha = bottom[3] ? alpha : 255; 314 uint8 invAlpha = 255 - mergeAlpha; 315 bottom[0] = kInverseGammaTable[(b1 * invAlpha + t1 * mergeAlpha) / 255]; 316 bottom[1] = kInverseGammaTable[(b2 * invAlpha + t2 * mergeAlpha) / 255]; 317 bottom[2] = kInverseGammaTable[(b3 * invAlpha + t3 * mergeAlpha) / 255]; 318 bottom[3] = (bottom[3] * (255 - alpha) + top[3] * alpha) / 255; 319 } 320 } 321 } 322 323 // blend_pixels_overlay_copy 324 inline void 325 blend_pixels_overlay_copy(uint8* bottom, uint8* top, uint8* dest, uint8 alphaOverride) 326 { 327 uint8 alpha = (top[3] * alphaOverride) / 255; 328 if (alpha > 0) { 329 if (alpha == 255) { 330 dest[0] = top[0]; 331 dest[1] = top[1]; 332 dest[2] = top[2]; 333 dest[3] = top[3]; 334 } else { 335 // convert to linear rgb 336 uint16 t1 = kGammaTable[top[0]]; 337 uint16 t2 = kGammaTable[top[1]]; 338 uint16 t3 = kGammaTable[top[2]]; 339 uint16 b1 = kGammaTable[bottom[0]]; 340 uint16 b2 = kGammaTable[bottom[1]]; 341 uint16 b3 = kGammaTable[bottom[2]]; 342 343 uint8 mergeAlpha = bottom[3] ? alpha : 255; 344 uint8 invAlpha = 255 - mergeAlpha; 345 dest[0] = kInverseGammaTable[(b1 * invAlpha + t1 * mergeAlpha) / 255]; 346 dest[1] = kInverseGammaTable[(b2 * invAlpha + t2 * mergeAlpha) / 255]; 347 dest[2] = kInverseGammaTable[(b3 * invAlpha + t3 * mergeAlpha) / 255]; 348 dest[3] = (bottom[3] * (255 - alpha) + top[3] * alpha) / 255; 349 } 350 } else { 351 dest[0] = bottom[0]; 352 dest[1] = bottom[1]; 353 dest[2] = bottom[2]; 354 dest[3] = bottom[3]; 355 } 356 } 357 358 /////////////////////////////////////////////////////////////////////////////////////////////////////// 359 #else // GAMMA_BLEND 360 361 // blend_colors_copy 362 inline void 363 blend_colors_copy(uint8* bottom, uint8 alpha, uint8* dest, 364 uint8 c1, uint8 c2, uint8 c3) 365 { 366 if (alpha > 0) { 367 if (bottom[3] == 0 || alpha == 255) { 368 dest[0] = c1; 369 dest[1] = c2; 370 dest[2] = c3; 371 dest[3] = alpha; 372 } else { 373 if (bottom[3] == 255) { 374 uint32 destAlpha = 255 - alpha; 375 dest[0] = (uint8)((bottom[0] * destAlpha + c1 * alpha) / 255); 376 dest[1] = (uint8)((bottom[1] * destAlpha + c2 * alpha) / 255); 377 dest[2] = (uint8)((bottom[2] * destAlpha + c3 * alpha) / 255); 378 dest[3] = 255; 379 } else { 380 uint8 alphaRest = 255 - alpha; 381 uint32 alphaTemp = (65025 - alphaRest * (255 - bottom[3])); 382 uint32 alphaDest = bottom[3] * alphaRest; 383 uint32 alphaSrc = 255 * alpha; 384 dest[0] = (bottom[0] * alphaDest + c1 * alphaSrc) / alphaTemp; 385 dest[1] = (bottom[1] * alphaDest + c2 * alphaSrc) / alphaTemp; 386 dest[2] = (bottom[2] * alphaDest + c3 * alphaSrc) / alphaTemp; 387 dest[3] = alphaTemp / 255; 388 } 389 } 390 } else { 391 *((uint32*)dest) = *((uint32*)bottom); 392 } 393 } 394 395 // blend_colors 396 inline void 397 blend_colors(uint8* bottom, uint8 alpha, uint8 c1, uint8 c2, uint8 c3) 398 { 399 if (alpha > 0) { 400 if (bottom[3] == 0 || alpha == 255) { 401 bottom[0] = c1; 402 bottom[1] = c2; 403 bottom[2] = c3; 404 bottom[3] = alpha; 405 } else { 406 if (bottom[3] == 255) { 407 uint32 destAlpha = 255 - alpha; 408 bottom[0] = (uint8)((bottom[0] * destAlpha + c1 * alpha) / 255); 409 bottom[1] = (uint8)((bottom[1] * destAlpha + c2 * alpha) / 255); 410 bottom[2] = (uint8)((bottom[2] * destAlpha + c3 * alpha) / 255); 411 } else { 412 uint8 alphaRest = 255 - alpha; 413 uint32 alphaTemp = (65025 - alphaRest * (255 - bottom[3])); 414 uint32 alphaDest = bottom[3] * alphaRest; 415 uint32 alphaSrc = 255 * alpha; 416 bottom[0] = (bottom[0] * alphaDest + c1 * alphaSrc) / alphaTemp; 417 bottom[1] = (bottom[1] * alphaDest + c2 * alphaSrc) / alphaTemp; 418 bottom[2] = (bottom[2] * alphaDest + c3 * alphaSrc) / alphaTemp; 419 bottom[3] = alphaTemp / 255; 420 } 421 } 422 } 423 } 424 425 // blend_colors 426 inline void 427 blend_colors(uint8* bottom, uint8* source, uint8 alphaOverride) 428 { 429 uint8 alpha = (source[3] * alphaOverride) / 255; 430 if (alpha > 0) { 431 if (bottom[3] == 0 || alpha == 255) { 432 bottom[0] = source[0]; 433 bottom[1] = source[1]; 434 bottom[2] = source[2]; 435 bottom[3] = alpha; 436 } else { 437 if (bottom[3] == 255) { 438 uint32 destAlpha = 255 - alpha; 439 bottom[0] = (uint8)((bottom[0] * destAlpha + source[0] * alpha) / 255); 440 bottom[1] = (uint8)((bottom[1] * destAlpha + source[1] * alpha) / 255); 441 bottom[2] = (uint8)((bottom[2] * destAlpha + source[2] * alpha) / 255); 442 } else { 443 uint8 alphaRest = 255 - alpha; 444 uint32 alphaTemp = (65025 - alphaRest * (255 - bottom[3])); 445 uint32 alphaDest = bottom[3] * alphaRest; 446 uint32 alphaSrc = 255 * alpha; 447 bottom[0] = (bottom[0] * alphaDest + source[0] * alphaSrc) / alphaTemp; 448 bottom[1] = (bottom[1] * alphaDest + source[1] * alphaSrc) / alphaTemp; 449 bottom[2] = (bottom[2] * alphaDest + source[2] * alphaSrc) / alphaTemp; 450 bottom[3] = alphaTemp / 255; 451 } 452 } 453 } 454 } 455 456 // blend_colors 457 inline void 458 blend_colors(uint8* bottom, uint8* source) 459 { 460 if (source[3] > 0) { 461 if (bottom[3] == 0 || source[3] == 255) { 462 bottom[0] = source[0]; 463 bottom[1] = source[1]; 464 bottom[2] = source[2]; 465 bottom[3] = source[3]; 466 } else { 467 if (bottom[3] == 255) { 468 uint32 destAlpha = 255 - source[3]; 469 bottom[0] = (uint8)((bottom[0] * destAlpha + source[0] * source[3]) / 255); 470 bottom[1] = (uint8)((bottom[1] * destAlpha + source[1] * source[3]) / 255); 471 bottom[2] = (uint8)((bottom[2] * destAlpha + source[2] * source[3]) / 255); 472 } else { 473 uint8 alphaRest = 255 - source[3]; 474 uint32 alphaTemp = (65025 - alphaRest * (255 - bottom[3])); 475 uint32 alphaDest = bottom[3] * alphaRest; 476 uint32 alphaSrc = 255 * source[3]; 477 bottom[0] = (bottom[0] * alphaDest + source[0] * alphaSrc) / alphaTemp; 478 bottom[1] = (bottom[1] * alphaDest + source[1] * alphaSrc) / alphaTemp; 479 bottom[2] = (bottom[2] * alphaDest + source[2] * alphaSrc) / alphaTemp; 480 bottom[3] = alphaTemp / 255; 481 } 482 } 483 } 484 } 485 486 // blend_colors_copy 487 inline void 488 blend_colors_copy(uint8* dest, uint8* bottom, uint8* top) 489 { 490 if (bottom[3] == 0 || top[3] == 255) { 491 dest[0] = top[0]; 492 dest[1] = top[1]; 493 dest[2] = top[2]; 494 dest[3] = top[3]; 495 } else { 496 if (bottom[3] == 255) { 497 uint32 destAlpha = 255 - top[3]; 498 dest[0] = (uint8)((bottom[0] * destAlpha + top[0] * top[3]) / 255); 499 dest[1] = (uint8)((bottom[1] * destAlpha + top[1] * top[3]) / 255); 500 dest[2] = (uint8)((bottom[2] * destAlpha + top[2] * top[3]) / 255); 501 dest[3] = 255; 502 } else { 503 uint8 alphaRest = 255 - top[3]; 504 uint32 alphaTemp = (65025 - alphaRest * (255 - bottom[3])); 505 uint32 alphaDest = bottom[3] * alphaRest; 506 uint32 alphaSrc = 255 * top[3]; 507 dest[0] = (bottom[0] * alphaDest + top[0] * alphaSrc) / alphaTemp; 508 dest[1] = (bottom[1] * alphaDest + top[1] * alphaSrc) / alphaTemp; 509 dest[2] = (bottom[2] * alphaDest + top[2] * alphaSrc) / alphaTemp; 510 dest[3] = alphaTemp / 255; 511 } 512 } 513 } 514 515 // blend_pixels 516 inline void 517 blend_pixels(uint8* bottom, uint8* top, uint8 alpha) 518 { 519 if (alpha > 0) { 520 if (alpha == 255) { 521 bottom[0] = top[0]; 522 bottom[1] = top[1]; 523 bottom[2] = top[2]; 524 bottom[3] = top[3]; 525 } else { 526 uint8 mergeAlpha = bottom[3] ? (top[3] * alpha) / 255 : 255; 527 uint8 invAlpha = 255 - mergeAlpha; 528 bottom[0] = (bottom[0] * invAlpha + top[0] * mergeAlpha) / 255; 529 bottom[1] = (bottom[1] * invAlpha + top[1] * mergeAlpha) / 255; 530 bottom[2] = (bottom[2] * invAlpha + top[2] * mergeAlpha) / 255; 531 bottom[3] = (bottom[3] * (255 - alpha) + top[3] * alpha) / 255; 532 } 533 } 534 } 535 536 // blend_pixels_copy 537 inline void 538 blend_pixels_copy(uint8* bottom, uint8* top, uint8* dest, uint8 alpha) 539 { 540 if (alpha > 0) { 541 if (alpha == 255) { 542 dest[0] = top[0]; 543 dest[1] = top[1]; 544 dest[2] = top[2]; 545 dest[3] = top[3]; 546 } else { 547 uint8 mergeAlpha = bottom[3] ? (top[3] * alpha) / 255 : 255; 548 uint8 invAlpha = 255 - mergeAlpha; 549 dest[0] = (bottom[0] * invAlpha + top[0] * mergeAlpha) / 255; 550 dest[1] = (bottom[1] * invAlpha + top[1] * mergeAlpha) / 255; 551 dest[2] = (bottom[2] * invAlpha + top[2] * mergeAlpha) / 255; 552 dest[3] = (bottom[3] * (255 - alpha) + top[3] * alpha) / 255; 553 } 554 } else { 555 dest[0] = bottom[0]; 556 dest[1] = bottom[1]; 557 dest[2] = bottom[2]; 558 dest[3] = bottom[3]; 559 } 560 } 561 562 // blend_pixels_overlay 563 inline void 564 blend_pixels_overlay(uint8* bottom, uint8* top, uint8 alphaOverride) 565 { 566 uint8 alpha = (top[3] * alphaOverride) / 255; 567 if (alpha > 0) { 568 if (alpha == 255) { 569 bottom[0] = top[0]; 570 bottom[1] = top[1]; 571 bottom[2] = top[2]; 572 bottom[3] = top[3]; 573 } else { 574 uint8 mergeAlpha = bottom[3] ? alpha : 255; 575 uint8 invAlpha = 255 - mergeAlpha; 576 bottom[0] = (bottom[0] * invAlpha + top[0] * mergeAlpha) / 255; 577 bottom[1] = (bottom[1] * invAlpha + top[1] * mergeAlpha) / 255; 578 bottom[2] = (bottom[2] * invAlpha + top[2] * mergeAlpha) / 255; 579 bottom[3] = (bottom[3] * (255 - alpha) + top[3] * alpha) / 255; 580 } 581 } 582 } 583 584 // blend_pixels_overlay_copy 585 inline void 586 blend_pixels_overlay_copy(uint8* bottom, uint8* top, uint8* dest, uint8 alphaOverride) 587 { 588 uint8 alpha = (top[3] * alphaOverride) / 255; 589 if (alpha > 0) { 590 if (alpha == 255) { 591 dest[0] = top[0]; 592 dest[1] = top[1]; 593 dest[2] = top[2]; 594 dest[3] = top[3]; 595 } else { 596 uint8 mergeAlpha = bottom[3] ? alpha : 255; 597 uint8 invAlpha = 255 - mergeAlpha; 598 dest[0] = (bottom[0] * invAlpha + top[0] * mergeAlpha) / 255; 599 dest[1] = (bottom[1] * invAlpha + top[1] * mergeAlpha) / 255; 600 dest[2] = (bottom[2] * invAlpha + top[2] * mergeAlpha) / 255; 601 dest[3] = (bottom[3] * (255 - alpha) + top[3] * alpha) / 255; 602 } 603 } else { 604 dest[0] = bottom[0]; 605 dest[1] = bottom[1]; 606 dest[2] = bottom[2]; 607 dest[3] = bottom[3]; 608 } 609 } 610 611 #endif // GAMMA_BLEND 612 613 #endif // BLENDING_H 614