Changeset 249 for libcaca/trunk/src/bitmap.c
- Timestamp:
- Dec 12, 2003, 3:49:41 PM (19 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
libcaca/trunk/src/bitmap.c
r247 r249 47 47 #include "caca_internals.h" 48 48 49 #define NEW_RENDERER 1 50 49 /* 50 * Global variables 51 */ 52 enum caca_feature _caca_background; 53 enum caca_feature _caca_dithering; 54 enum caca_feature _caca_antialiasing; 55 56 /* 57 * Local prototypes 58 */ 51 59 static void mask2shift(unsigned int, int *, int *); 52 60 … … 76 84 static unsigned int get_random_dither(void); 77 85 static void increment_random_dither(void); 78 79 /* Current dithering method */80 static enum caca_dithering _caca_dithering = CACA_DITHERING_NONE;81 82 static void (*_init_dither) (int) = init_no_dither;83 static unsigned int (*_get_dither) (void) = get_no_dither;84 static void (*_increment_dither) (void) = increment_no_dither;85 86 void caca_set_dithering(enum caca_dithering dither)87 {88 switch(dither)89 {90 case CACA_DITHERING_NONE:91 _init_dither = init_no_dither;92 _get_dither = get_no_dither;93 _increment_dither = increment_no_dither;94 break;95 96 case CACA_DITHERING_ORDERED2:97 _init_dither = init_ordered2_dither;98 _get_dither = get_ordered2_dither;99 _increment_dither = increment_ordered2_dither;100 break;101 102 case CACA_DITHERING_ORDERED4:103 _init_dither = init_ordered4_dither;104 _get_dither = get_ordered4_dither;105 _increment_dither = increment_ordered4_dither;106 break;107 108 case CACA_DITHERING_ORDERED8:109 _init_dither = init_ordered8_dither;110 _get_dither = get_ordered8_dither;111 _increment_dither = increment_ordered8_dither;112 break;113 114 case CACA_DITHERING_RANDOM:115 _init_dither = init_random_dither;116 _get_dither = get_random_dither;117 _increment_dither = increment_random_dither;118 break;119 120 default:121 return;122 }123 124 _caca_dithering = dither;125 }126 86 127 87 struct caca_bitmap … … 288 248 if(bitmap->palette) 289 249 { 290 *r = bitmap->red[bits];291 *g = bitmap->green[bits];292 *b = bitmap->blue[bits];293 *a = bitmap->alpha[bits];250 *r += bitmap->red[bits]; 251 *g += bitmap->green[bits]; 252 *b += bitmap->blue[bits]; 253 *a += bitmap->alpha[bits]; 294 254 } 295 255 else 296 256 { 297 *r = ((bits & bitmap->rmask) >> bitmap->rright) << bitmap->rleft;298 *g = ((bits & bitmap->gmask) >> bitmap->gright) << bitmap->gleft;299 *b = ((bits & bitmap->bmask) >> bitmap->bright) << bitmap->bleft;300 *a = ((bits & bitmap->amask) >> bitmap->aright) << bitmap->aleft;257 *r += ((bits & bitmap->rmask) >> bitmap->rright) << bitmap->rleft; 258 *g += ((bits & bitmap->gmask) >> bitmap->gright) << bitmap->gleft; 259 *b += ((bits & bitmap->bmask) >> bitmap->bright) << bitmap->bleft; 260 *a += ((bits & bitmap->amask) >> bitmap->aright) << bitmap->aleft; 301 261 } 302 262 } … … 335 295 const struct caca_bitmap *bitmap, void *pixels) 336 296 { 337 #if !NEW_RENDERER 297 /* Current dithering method */ 298 void (*_init_dither) (int); 299 unsigned int (*_get_dither) (void); 300 void (*_increment_dither) (void); 301 302 /* Only used when background is black */ 338 303 static const int white_colors[] = 339 304 { … … 343 308 CACA_COLOR_WHITE 344 309 }; 345 #endif346 310 347 311 static const int light_colors[] = … … 404 368 } 405 369 370 switch(_caca_dithering) 371 { 372 case CACA_DITHERING_NONE: 373 _init_dither = init_no_dither; 374 _get_dither = get_no_dither; 375 _increment_dither = increment_no_dither; 376 break; 377 378 case CACA_DITHERING_ORDERED2: 379 _init_dither = init_ordered2_dither; 380 _get_dither = get_ordered2_dither; 381 _increment_dither = increment_ordered2_dither; 382 break; 383 384 case CACA_DITHERING_ORDERED4: 385 _init_dither = init_ordered4_dither; 386 _get_dither = get_ordered4_dither; 387 _increment_dither = increment_ordered4_dither; 388 break; 389 390 case CACA_DITHERING_ORDERED8: 391 _init_dither = init_ordered8_dither; 392 _get_dither = get_ordered8_dither; 393 _increment_dither = increment_ordered8_dither; 394 break; 395 396 case CACA_DITHERING_RANDOM: 397 _init_dither = init_random_dither; 398 _get_dither = get_random_dither; 399 _increment_dither = increment_random_dither; 400 break; 401 402 default: 403 /* Something wicked happened! */ 404 return; 405 } 406 406 407 for(y = y1 > 0 ? y1 : 0; y <= y2 && y <= (int)_caca_height; y++) 407 408 for(x = x1 > 0 ? x1 : 0, _init_dither(y); … … 410 411 { 411 412 int ch; 412 unsigned int r, g, b, a , R, G, B;413 unsigned int r, g, b, a; 413 414 int hue, sat, val; 414 int fromx = w * (x - x1) / (x2 - x1 + 1); 415 int fromy = h * (y - y1) / (y2 - y1 + 1); 415 int fromx, fromy, tox, toy, myx, myy, dots; 416 416 enum caca_color outfg, outbg; 417 417 char outch; 418 #if NEW_RENDERER 418 419 /* Only used by coloured background */ 419 420 int distbg, distfg, dist, hue1, hue2; 420 #endif 421 422 /* Clip values (yuck) */ 423 if(fromx == 0) fromx = 1; 424 if(fromy == 0) fromy = 1; 421 422 r = g = b = a = 0; 425 423 426 424 /* First get RGB */ 427 R = 0, G = 0, B = 0; 428 get_rgba_default(bitmap, pixels, fromx, fromy, &r, &g, &b, &a); 429 if(a == 0) 430 continue; 431 #if 1 432 R += r; G += g; B += b; 433 #else 434 R += r; G += g; B += b; 435 get_rgba_default(bitmap, pixels, fromx - 1, fromy, &r, &g, &b, &a); 436 R += r; G += g; B += b; 437 get_rgba_default(bitmap, pixels, fromx, fromy - 1, &r, &g, &b, &a); 438 R += r; G += g; B += b; 439 get_rgba_default(bitmap, pixels, fromx + 1, fromy, &r, &g, &b, &a); 440 R += r; G += g; B += b; 441 get_rgba_default(bitmap, pixels, fromx, fromy + 1, &r, &g, &b, &a); 442 R += r; G += g; B += b; 443 R /= 5; G /= 5; B /= 5; 444 #endif 445 446 /* Now get HSV from RGB */ 447 rgb2hsv_default(R, G, B, &hue, &sat, &val); 448 449 /* The hard work: calculate foreground and background colours, 450 * as well as the most appropriate character to output. */ 451 #if NEW_RENDERER 452 # define XRATIO 5*5 453 # define YRATIO 3*3 454 # define HRATIO 2*2 455 # define FUZZINESS XRATIO * 0x800 456 457 /* distance to black */ 458 distbg = XRATIO * val * val; 459 distbg += FUZZINESS * _get_dither() - 0x80 * FUZZINESS; 460 distbg = distbg * 2 / 4; 461 outbg = CACA_COLOR_BLACK; 462 463 /* distance to 30% */ 464 dist = XRATIO * (val - 0x600) * (val - 0x600) 465 + YRATIO * sat * sat; 466 dist += FUZZINESS * _get_dither() - 0x80 * FUZZINESS; 467 dist = dist * 3 / 2; 468 if(dist <= distbg) 425 if(_caca_antialiasing == CACA_ANTIALIASING_PREFILTER) 469 426 { 470 outfg = outbg; 471 distfg = distbg; 472 outbg = CACA_COLOR_DARKGRAY; 473 distbg = dist; 427 fromx = ((x - x1) * (w - 1)) / (x2 - x1 + 1); 428 fromy = ((y - y1) * (h - 1)) / (y2 - y1 + 1); 429 tox = ((x - x1 + 1) * (w - 1)) / (x2 - x1 + 1); 430 toy = ((y - y1 + 1) * (h - 1)) / (y2 - y1 + 1); 431 dots = 0; 432 433 for(myx = fromx; myx <= tox; myx++) 434 for(myy = fromy; myy <= toy; myy++) 435 { 436 dots++; 437 get_rgba_default(bitmap, pixels, myx, myy, &r, &g, &b, &a); 438 } 439 440 /* Normalize */ 441 r /= dots; 442 g /= dots; 443 b /= dots; 444 a /= dots; 474 445 } 475 446 else 476 447 { 477 outfg = CACA_COLOR_DARKGRAY; 478 distfg = dist; 448 fromx = ((x - x1) * (w - 1)) / (x2 - x1 + 1); 449 fromy = ((y - y1) * (h - 1)) / (y2 - y1 + 1); 450 tox = ((x - x1 + 1) * (w - 1)) / (x2 - x1 + 1); 451 toy = ((y - y1 + 1) * (h - 1)) / (y2 - y1 + 1); 452 453 myx = (fromx + tox) / 2; 454 myy = (fromy + toy) / 2; 455 456 get_rgba_default(bitmap, pixels, myx, myy, &r, &g, &b, &a); 479 457 } 480 458 481 /* check dist to 70% */ 482 dist = XRATIO * (val - 0xa00) * (val - 0xa00) 483 + YRATIO * sat * sat; 484 dist += FUZZINESS * _get_dither() - 0x80 * FUZZINESS; 485 dist = dist * 3 / 2; 486 if(dist <= distbg) 459 if(a < 0x100) 460 continue; 461 462 /* Now get HSV from RGB */ 463 rgb2hsv_default(r, g, b, &hue, &sat, &val); 464 465 /* The hard work: calculate foreground and background colours, 466 * as well as the most appropriate character to output. */ 467 if(_caca_background == CACA_BACKGROUND_SOLID) 487 468 { 488 outfg = outbg; 489 distfg = distbg; 490 outbg = CACA_COLOR_LIGHTGRAY; 491 distbg = dist; 469 # define XRATIO 5*5 470 # define YRATIO 3*3 471 # define HRATIO 2*2 472 # define FUZZINESS XRATIO * 0x800 473 474 /* distance to black */ 475 distbg = XRATIO * val * val; 476 distbg += FUZZINESS * _get_dither() - 0x80 * FUZZINESS; 477 distbg = distbg * 2 / 4; 478 outbg = CACA_COLOR_BLACK; 479 480 /* distance to 30% */ 481 dist = XRATIO * (val - 0x600) * (val - 0x600) 482 + YRATIO * sat * sat; 483 dist += FUZZINESS * _get_dither() - 0x80 * FUZZINESS; 484 dist = dist * 3 / 2; 485 if(dist <= distbg) 486 { 487 outfg = outbg; 488 distfg = distbg; 489 outbg = CACA_COLOR_DARKGRAY; 490 distbg = dist; 491 } 492 else 493 { 494 outfg = CACA_COLOR_DARKGRAY; 495 distfg = dist; 496 } 497 498 /* check dist to 70% */ 499 dist = XRATIO * (val - 0xa00) * (val - 0xa00) 500 + YRATIO * sat * sat; 501 dist += FUZZINESS * _get_dither() - 0x80 * FUZZINESS; 502 dist = dist * 3 / 2; 503 if(dist <= distbg) 504 { 505 outfg = outbg; 506 distfg = distbg; 507 outbg = CACA_COLOR_LIGHTGRAY; 508 distbg = dist; 509 } 510 else if(dist <= distfg) 511 { 512 outfg = CACA_COLOR_LIGHTGRAY; 513 distfg = dist; 514 } 515 516 /* check dist to white */ 517 dist = XRATIO * (val - 0x1000) * (val - 0x1000) 518 + YRATIO * sat * sat; 519 dist += FUZZINESS * _get_dither() - 0x80 * FUZZINESS; 520 if(dist <= distbg) 521 { 522 outfg = outbg; 523 distfg = distbg; 524 outbg = CACA_COLOR_WHITE; 525 distbg = dist; 526 } 527 else if(dist <= distfg) 528 { 529 outfg = CACA_COLOR_WHITE; 530 distfg = dist; 531 } 532 533 hue1 = (hue + 0x800) & ~0xfff; 534 if(hue > hue1) 535 hue2 = (hue + 0x1800) & ~0xfff; 536 else 537 hue2 = (hue - 0x800) & ~0xfff; 538 539 /* check dist to 2nd closest dark color */ 540 dist = XRATIO * (val - 0x600) * (val - 0x600) 541 + YRATIO * (sat - 0x1000) * (sat - 0x1000) 542 + HRATIO * (hue - hue2) * (hue - hue2); 543 dist += FUZZINESS * _get_dither() - 0x80 * FUZZINESS; 544 //dist = dist * 3 / 4; 545 if(dist <= distbg) 546 { 547 outfg = outbg; 548 distfg = distbg; 549 outbg = dark_colors[hue2 / 0x1000]; 550 distbg = dist; 551 } 552 else if(dist <= distfg) 553 { 554 outfg = dark_colors[hue2 / 0x1000]; 555 distfg = dist; 556 } 557 558 /* check dist to 2nd closest light color */ 559 dist = XRATIO * (val - 0x1000) * (val - 0x1000) 560 + YRATIO * (sat - 0x1000) * (sat - 0x1000) 561 + HRATIO * (hue - hue2) * (hue - hue2); 562 dist += FUZZINESS * _get_dither() - 0x80 * FUZZINESS; 563 //dist = dist * 3 / 4; 564 //dist = dist / 2; 565 if(dist <= distbg) 566 { 567 outfg = outbg; 568 distfg = distbg; 569 outbg = light_colors[hue2 / 0x1000]; 570 distbg = dist; 571 } 572 else if(dist <= distfg) 573 { 574 outfg = light_colors[hue2 / 0x1000]; 575 distfg = dist; 576 } 577 578 /* check dist to closest dark color */ 579 dist = XRATIO * (val - 0x600) * (val - 0x600) 580 + YRATIO * (sat - 0x1000) * (sat - 0x1000) 581 + HRATIO * (hue - hue1) * (hue - hue1); 582 dist += FUZZINESS * _get_dither() - 0x80 * FUZZINESS; 583 dist = dist * 3 / 4; 584 if(dist <= distbg) 585 { 586 outfg = outbg; 587 distfg = distbg; 588 outbg = dark_colors[hue1 / 0x1000]; 589 distbg = dist; 590 } 591 else if(dist <= distfg) 592 { 593 outfg = dark_colors[hue1 / 0x1000]; 594 distfg = dist; 595 } 596 597 /* check dist to closest light color */ 598 dist = XRATIO * (val - 0x1000) * (val - 0x1000) 599 + YRATIO * (sat - 0x1000) * (sat - 0x1000) 600 + HRATIO * (hue - hue1) * (hue - hue1); 601 dist += FUZZINESS * _get_dither() - 0x80 * FUZZINESS; 602 dist = dist / 2; 603 if(dist <= distbg) 604 { 605 outfg = outbg; 606 distfg = distbg; 607 outbg = light_colors[hue1 / 0x1000]; 608 distbg = dist; 609 } 610 else if(dist <= distfg) 611 { 612 outfg = light_colors[hue1 / 0x1000]; 613 distfg = dist; 614 } 615 616 if(distbg <= 0) distbg = 1; 617 if(distfg <= 0) distfg = 1; 618 619 /* distbg can be > distfg because of dithering fuzziness */ 620 ch = distbg * 2 * (DENSITY_CHARS - 1) / (distbg + distfg); 621 ch = 4 * ch + _get_dither() / 0x40; 622 outch = density_chars[ch]; 492 623 } 493 else if(dist <= distfg)624 else 494 625 { 495 outfg = CACA_COLOR_LIGHTGRAY; 496 distfg = dist; 626 outbg = CACA_COLOR_BLACK; 627 if((unsigned int)sat < 0x200 + _get_dither() * 0x8) 628 outfg = white_colors[1 + (val * 2 + _get_dither() * 0x10) 629 / 0x1000]; 630 else if((unsigned int)val > 0x800 + _get_dither() * 0x4) 631 outfg = light_colors[(hue + _get_dither() * 0x10) / 0x1000]; 632 else 633 outfg = dark_colors[(hue + _get_dither() * 0x10) / 0x1000]; 634 635 ch = (val + 0x2 * _get_dither()) * 10 / 0x1000; 636 ch = 4 * ch + _get_dither() / 0x40; 637 outch = density_chars[ch]; 497 638 } 498 499 /* check dist to white */500 dist = XRATIO * (val - 0x1000) * (val - 0x1000)501 + YRATIO * sat * sat;502 dist += FUZZINESS * _get_dither() - 0x80 * FUZZINESS;503 if(dist <= distbg)504 {505 outfg = outbg;506 distfg = distbg;507 outbg = CACA_COLOR_WHITE;508 distbg = dist;509 }510 else if(dist <= distfg)511 {512 outfg = CACA_COLOR_WHITE;513 distfg = dist;514 }515 516 hue1 = (hue + 0x800) & ~0xfff;517 if(hue > hue1)518 hue2 = (hue + 0x1800) & ~0xfff;519 else520 hue2 = (hue - 0x800) & ~0xfff;521 522 /* check dist to 2nd closest dark color */523 dist = XRATIO * (val - 0x600) * (val - 0x600)524 + YRATIO * (sat - 0x1000) * (sat - 0x1000)525 + HRATIO * (hue - hue2) * (hue - hue2);526 dist += FUZZINESS * _get_dither() - 0x80 * FUZZINESS;527 // dist = dist * 3 / 4;528 if(dist <= distbg)529 {530 outfg = outbg;531 distfg = distbg;532 outbg = dark_colors[hue2 / 0x1000];533 distbg = dist;534 }535 else if(dist <= distfg)536 {537 outfg = dark_colors[hue2 / 0x1000];538 distfg = dist;539 }540 541 /* check dist to 2nd closest light color */542 dist = XRATIO * (val - 0x1000) * (val - 0x1000)543 + YRATIO * (sat - 0x1000) * (sat - 0x1000)544 + HRATIO * (hue - hue2) * (hue - hue2);545 dist += FUZZINESS * _get_dither() - 0x80 * FUZZINESS;546 //dist = dist * 3 / 4;547 //dist = dist / 2;548 if(dist <= distbg)549 {550 outfg = outbg;551 distfg = distbg;552 outbg = light_colors[hue2 / 0x1000];553 distbg = dist;554 }555 else if(dist <= distfg)556 {557 outfg = light_colors[hue2 / 0x1000];558 distfg = dist;559 }560 561 /* check dist to closest dark color */562 dist = XRATIO * (val - 0x600) * (val - 0x600)563 + YRATIO * (sat - 0x1000) * (sat - 0x1000)564 + HRATIO * (hue - hue1) * (hue - hue1);565 dist += FUZZINESS * _get_dither() - 0x80 * FUZZINESS;566 dist = dist * 3 / 4;567 if(dist <= distbg)568 {569 outfg = outbg;570 distfg = distbg;571 outbg = dark_colors[hue1 / 0x1000];572 distbg = dist;573 }574 else if(dist <= distfg)575 {576 outfg = dark_colors[hue1 / 0x1000];577 distfg = dist;578 }579 580 /* check dist to closest light color */581 dist = XRATIO * (val - 0x1000) * (val - 0x1000)582 + YRATIO * (sat - 0x1000) * (sat - 0x1000)583 + HRATIO * (hue - hue1) * (hue - hue1);584 dist += FUZZINESS * _get_dither() - 0x80 * FUZZINESS;585 dist = dist / 2;586 if(dist <= distbg)587 {588 outfg = outbg;589 distfg = distbg;590 outbg = light_colors[hue1 / 0x1000];591 distbg = dist;592 }593 else if(dist <= distfg)594 {595 outfg = light_colors[hue1 / 0x1000];596 distfg = dist;597 }598 599 if(distbg <= 0) distbg = 1;600 if(distfg <= 0) distfg = 1;601 602 /* distbg can be > distfg because of dithering fuzziness */603 ch = distbg * 2 * (DENSITY_CHARS - 1) / (distbg + distfg);604 ch = 4 * ch + _get_dither() / 0x40;605 outch = density_chars[ch];606 607 #else608 outbg = CACA_COLOR_BLACK;609 if((unsigned int)sat < 0x200 + _get_dither() * 0x8)610 outfg = white_colors[1 + (val * 2 + _get_dither() * 0x10) / 0x1000];611 else if((unsigned int)val > 0x800 + _get_dither() * 0x4)612 outfg = light_colors[(hue + _get_dither() * 0x10) / 0x1000];613 else614 outfg = dark_colors[(hue + _get_dither() * 0x10) / 0x1000];615 616 ch = (val + 0x2 * _get_dither()) * 10 / 0x1000;617 ch = 4 * ch + _get_dither() / 0x40;618 outch = density_chars[ch];619 620 #endif621 639 622 640 /* Now output the character */
Note: See TracChangeset
for help on using the changeset viewer.