Changeset 373
- Timestamp:
- Nov 4, 2004, 10:18:52 PM (18 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
libcaca/trunk/src/bitmap.c
r351 r373 42 42 #endif 43 43 44 #include <stdio.h> 44 45 #include <stdlib.h> 46 #include <limits.h> 47 #include <string.h> 45 48 46 49 #include "caca.h" … … 78 81 3, 0x0, 0xfff, 0x5ff, /* dark red */ 79 82 2, 0x0, 0xfff, 0xfff /* light red */ 83 }; 84 85 /* RGB palette for the new colour picker */ 86 static int rgb_palette[] = 87 { 88 0x0, 0x0, 0x0, 89 0x0, 0x0, 0x7ff, 90 0x0, 0x7ff, 0x0, 91 0x0, 0x7ff, 0x7ff, 92 0x7ff, 0x0, 0x0, 93 0x7ff, 0x0, 0x7ff, 94 0x7ff, 0x7ff, 0x0, 95 0x7ff, 0x7ff, 0x7ff, 96 0x3ff, 0x3ff, 0x3ff, 97 0x000, 0x000, 0xfff, 98 0x000, 0xfff, 0x000, 99 0x000, 0xfff, 0xfff, 100 0xfff, 0x000, 0x000, 101 0xfff, 0x000, 0xfff, 102 0xfff, 0xfff, 0x000, 103 0xfff, 0xfff, 0xfff, 80 104 }; 81 105 … … 108 132 unsigned int *); 109 133 static inline void rgb2hsv_default(int, int, int, int *, int *, int *); 134 static inline int sq(int); 110 135 111 136 /* Dithering methods */ … … 385 410 } 386 411 412 static inline int sq(int x) 413 { 414 return x * x; 415 } 416 387 417 /** 388 418 * \brief Draw a bitmap on the screen. … … 405 435 unsigned int (*_get_dither) (void); 406 436 void (*_increment_dither) (void); 437 438 int *floyd_steinberg, *fs_r, *fs_g, *fs_b; 439 int fs_length; 407 440 408 441 /* Only used when background is black */ … … 439 472 /* FIXME: choose better characters! */ 440 473 #if !defined(_DOXYGEN_SKIP_ME) 441 # define D ENSITY_CHARS((sizeof(density_chars)/sizeof(char const)/4)-1)474 # define DCHMAX ((sizeof(density_chars)/sizeof(char const)/4)-1) 442 475 #endif 443 476 static char const density_chars[] = 444 477 " " 445 ". "446 ".. "447 478 "...." 448 479 "::::" … … 450 481 "tftf" 451 482 "%$%$" 452 " &KSZ"453 " WXGM"483 "SK&Z" 484 "XWGM" 454 485 "@@@@" 455 486 "8888" … … 516 547 } 517 548 549 fs_length = ((int)_caca_width <= x2 ? (int)_caca_width : x2) + 1; 550 floyd_steinberg = malloc(3 * (fs_length + 2) * sizeof(int)); 551 memset(floyd_steinberg, 0, 3 * (fs_length + 2) * sizeof(int)); 552 fs_r = floyd_steinberg + 1; 553 fs_g = fs_r + fs_length + 2; 554 fs_b = fs_g + fs_length + 2; 555 518 556 for(y = y1 > 0 ? y1 : 0; y <= y2 && y <= (int)_caca_height; y++) 557 { 558 int remain_r = 0, remain_g = 0, remain_b = 0; 559 int remain_r_next = 0, remain_g_next = 0, remain_b_next = 0; 560 519 561 for(x = x1 > 0 ? x1 : 0, _init_dither(y); 520 562 x <= x2 && x <= (int)_caca_width; 521 563 x++) 522 564 { 523 int ch; 524 unsigned int r, g, b, a; 525 int hue, sat, val; 526 int fromx, fromy, tox, toy, myx, myy, dots; 527 enum caca_color outfg, outbg; 565 unsigned int i; 566 int ch = 0, distmin; 567 int r, g, b, a, fg_r, fg_g, fg_b, bg_r, bg_g, bg_b; 568 int fromx, fromy, tox, toy, myx, myy, dots, dist; 569 570 enum caca_color outfg = 0, outbg = 0; 528 571 char outch; 529 572 … … 574 617 575 618 if(bitmap->has_alpha && a < 0x800) 619 { 620 remain_r = remain_g = remain_b = 0; 621 fs_r[x] = 0; 622 fs_g[x] = 0; 623 fs_b[x] = 0; 576 624 continue; 577 578 /* Now get HSV from RGB */ 579 rgb2hsv_default(r, g, b, &hue, &sat, &val); 580 581 /* The hard work: calculate foreground and background colours, 582 * as well as the most appropriate character to output. */ 583 if(_caca_background == CACA_BACKGROUND_SOLID) 625 } 626 627 r += remain_r; 628 g += remain_g; 629 b += remain_b; 630 r += remain_r_next; 631 g += remain_g_next; 632 b += remain_b_next; 633 remain_r_next = fs_r[x+1]; 634 remain_g_next = fs_g[x+1]; 635 remain_b_next = fs_b[x+1]; 636 637 distmin = INT_MAX; 638 for(i = 0; i < 16; i++) 584 639 { 585 unsigned char point; 586 int distfg, distbg; 587 588 lookup_colors[4] = dark_colors[1 + hue / 0x1000]; 589 lookup_colors[5] = light_colors[1 + hue / 0x1000]; 590 lookup_colors[6] = dark_colors[hue / 0x1000]; 591 lookup_colors[7] = light_colors[hue / 0x1000]; 592 593 point = hsv_distances[(val + _get_dither() * (0x1000 / LOOKUP_VAL) 594 / 0x100) * (LOOKUP_VAL - 1) / 0x1000] 595 [(sat + _get_dither() * (0x1000 / LOOKUP_SAT) 596 / 0x100) * (LOOKUP_SAT - 1) / 0x1000] 597 [((hue & 0xfff) + _get_dither() 598 * (0x1000 / LOOKUP_HUE) / 0x100) 599 * (LOOKUP_HUE - 1) / 0x1000]; 600 601 distfg = HSV_DISTANCE(hue % 0xfff, sat, val, (point >> 4)); 602 distbg = HSV_DISTANCE(hue % 0xfff, sat, val, (point & 0xf)); 603 604 /* Sanity check due to the lack of precision in hsv_distances, 605 * and distbg can be > distfg because of dithering fuzziness. */ 606 if(distbg > distfg) 607 distbg = distfg; 608 609 outfg = lookup_colors[(point >> 4)]; 610 outbg = lookup_colors[(point & 0xf)]; 611 612 ch = distbg * 2 * (DENSITY_CHARS - 1) / (distbg + distfg); 613 ch = 4 * ch + _get_dither() / 0x40; 614 outch = density_chars[ch]; 640 dist = sq(r - rgb_palette[i * 3]) 641 + sq(g - rgb_palette[i * 3 + 1]) 642 + sq(b - rgb_palette[i * 3 + 2]); 643 if(dist < distmin) 644 { 645 outbg = i; 646 distmin = dist; 647 } 615 648 } 616 else 649 bg_r = rgb_palette[outbg * 3]; 650 bg_g = rgb_palette[outbg * 3 + 1]; 651 bg_b = rgb_palette[outbg * 3 + 2]; 652 653 distmin = INT_MAX; 654 for(i = 0; i < 16; i++) 617 655 { 618 outbg = CACA_COLOR_BLACK; 619 if((unsigned int)sat < 0x200 + _get_dither() * 0x8) 620 outfg = white_colors[1 + (val * 2 + _get_dither() * 0x10) 621 / 0x1000]; 622 else if((unsigned int)val > 0x800 + _get_dither() * 0x4) 623 outfg = light_colors[(hue + _get_dither() * 0x10) / 0x1000]; 624 else 625 outfg = dark_colors[(hue + _get_dither() * 0x10) / 0x1000]; 626 627 ch = (val + 0x2 * _get_dither()) * 10 / 0x1000; 628 ch = 4 * ch + _get_dither() / 0x40; 629 outch = density_chars[ch]; 656 if(i == outbg) 657 continue; 658 dist = sq(r - rgb_palette[i * 3]) 659 + sq(g - rgb_palette[i * 3 + 1]) 660 + sq(b - rgb_palette[i * 3 + 2]); 661 if(dist < distmin) 662 { 663 outfg = i; 664 distmin = dist; 665 } 630 666 } 667 fg_r = rgb_palette[outfg * 3]; 668 fg_g = rgb_palette[outfg * 3 + 1]; 669 fg_b = rgb_palette[outfg * 3 + 2]; 670 671 distmin = INT_MAX; 672 for(i = 0; i < DCHMAX - 1; i++) 673 { 674 int newr = i * fg_r + ((2*DCHMAX-1) - i) * bg_r; 675 int newg = i * fg_g + ((2*DCHMAX-1) - i) * bg_g; 676 int newb = i * fg_b + ((2*DCHMAX-1) - i) * bg_b; 677 dist = abs(r * (2*DCHMAX-1) - newr) 678 * abs(g * (2*DCHMAX-1) - newg) 679 * abs(b * (2*DCHMAX-1) - newb); 680 681 if(dist < distmin) 682 { 683 ch = i; 684 distmin = dist; 685 } 686 } 687 outch = density_chars[4 * ch]; 688 689 remain_r = r - (fg_r * ch + bg_r * ((2*DCHMAX-1) - ch)) / (2*DCHMAX-1); 690 remain_g = g - (fg_g * ch + bg_g * ((2*DCHMAX-1) - ch)) / (2*DCHMAX-1); 691 remain_b = b - (fg_b * ch + bg_b * ((2*DCHMAX-1) - ch)) / (2*DCHMAX-1); 692 remain_r_next = fs_r[x+1]; 693 remain_g_next = fs_g[x+1]; 694 remain_b_next = fs_b[x+1]; 695 fs_r[x-1] += 3 * remain_r / 16; 696 fs_g[x-1] += 3 * remain_g / 16; 697 fs_b[x-1] += 3 * remain_b / 16; 698 fs_r[x] = 5 * remain_r / 16; 699 fs_g[x] = 5 * remain_g / 16; 700 fs_b[x] = 5 * remain_b / 16; 701 fs_r[x+1] = 1 * remain_r / 16; 702 fs_g[x+1] = 1 * remain_g / 16; 703 fs_b[x+1] = 1 * remain_b / 16; 704 remain_r = 7 * remain_r / 16; 705 remain_g = 7 * remain_g / 16; 706 remain_b = 7 * remain_b / 16; 631 707 632 708 /* Now output the character */ … … 636 712 _increment_dither(); 637 713 } 714 /* end loop */ 715 } 716 717 free(floyd_steinberg); 638 718 } 639 719
Note: See TracChangeset
for help on using the changeset viewer.