You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

230 line
6.2 KiB

  1. /*
  2. * libcaca ASCII-Art library
  3. * Copyright (c) 2002, 2003 Sam Hocevar <sam@zoy.org>
  4. * All Rights Reserved
  5. *
  6. * $Id$
  7. *
  8. * This library is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU Lesser General Public
  10. * License as published by the Free Software Foundation; either
  11. * version 2 of the License, or (at your option) any later version.
  12. *
  13. * This library is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. * Lesser General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with this library; if not, write to the Free Software
  20. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
  21. * 02111-1307 USA
  22. */
  23. #include "config.h"
  24. #ifdef HAVE_INTTYPES_H
  25. # include <inttypes.h>
  26. #else
  27. typedef unsigned char uint8_t;
  28. #endif
  29. #include <stdlib.h>
  30. #include "caca.h"
  31. #include "caca_internals.h"
  32. /* Dithering methods */
  33. static void init_no_dither(int);
  34. static int get_no_dither(void);
  35. static void increment_no_dither(void);
  36. static void init_ordered_dither(int);
  37. static int get_ordered_dither(void);
  38. static void increment_ordered_dither(void);
  39. static void init_random_dither(int);
  40. static int get_random_dither(void);
  41. static void increment_random_dither(void);
  42. /* Current dithering method */
  43. static enum caca_dithering _caca_dithering = CACA_DITHER_NONE;
  44. static void (*_init_dither) (int) = init_no_dither;
  45. static int (*_get_dither) (void) = get_no_dither;
  46. static void (*_increment_dither) (void) = increment_no_dither;
  47. void caca_set_dithering(enum caca_dithering dither)
  48. {
  49. switch(dither)
  50. {
  51. case CACA_DITHER_NONE:
  52. _init_dither = init_no_dither;
  53. _get_dither = get_no_dither;
  54. _increment_dither = increment_no_dither;
  55. break;
  56. case CACA_DITHER_ORDERED:
  57. _init_dither = init_ordered_dither;
  58. _get_dither = get_ordered_dither;
  59. _increment_dither = increment_ordered_dither;
  60. break;
  61. case CACA_DITHER_RANDOM:
  62. _init_dither = init_random_dither;
  63. _get_dither = get_random_dither;
  64. _increment_dither = increment_random_dither;
  65. break;
  66. default:
  67. return;
  68. }
  69. _caca_dithering = dither;
  70. }
  71. void caca_blit(int x1, int y1, int x2, int y2, void *pixels, int w, int h)
  72. {
  73. static int white_colors[] = {CACA_COLOR_DARKGRAY, CACA_COLOR_LIGHTGRAY, CACA_COLOR_WHITE};
  74. static int light_colors[] = {CACA_COLOR_LIGHTMAGENTA, CACA_COLOR_LIGHTRED, CACA_COLOR_YELLOW, CACA_COLOR_LIGHTGREEN, CACA_COLOR_LIGHTCYAN, CACA_COLOR_LIGHTBLUE, CACA_COLOR_LIGHTMAGENTA};
  75. static int dark_colors[] = {CACA_COLOR_MAGENTA, CACA_COLOR_RED, CACA_COLOR_BROWN, CACA_COLOR_GREEN, CACA_COLOR_CYAN, CACA_COLOR_BLUE, CACA_COLOR_MAGENTA};
  76. static char foo[] = { ' ', '.', ':', ';', '=', '%', '$', 'W', '#', '8', '@' };
  77. int x, y, pitch;
  78. if(x1 > x2)
  79. {
  80. int tmp = x2; x2 = x1; x1 = tmp;
  81. }
  82. if(y1 > y2)
  83. {
  84. int tmp = y2; y2 = y1; y1 = tmp;
  85. }
  86. //pitch = (3 * w + 3) / 4 * 4;
  87. pitch = 4 * w;
  88. for(y = y1 > 0 ? y1 : 0; y <= y2 && y <= (int)caca_get_height(); y++)
  89. {
  90. /* Initialize dither tables for the current line */
  91. _init_dither(y);
  92. /* Dither the current line */
  93. for(x = x1 > 0 ? x1 : 0; x <= x2 && x <= (int)caca_get_width(); x++)
  94. {
  95. int fromx = w * (x - x1) / (x2 - x1 + 1);
  96. int fromy = h * (y - y1) / (y2 - y1 + 1);
  97. //int r = ((unsigned char *)pixels)[3 * fromx + pitch * fromy];
  98. //int g = ((unsigned char *)pixels)[3 * fromx + 1 + pitch * fromy];
  99. //int b = ((unsigned char *)pixels)[3 * fromx + 2 + pitch * fromy];
  100. int b = ((unsigned char *)pixels)[4 * fromx + pitch * fromy];
  101. int g = ((unsigned char *)pixels)[4 * fromx + 1 + pitch * fromy];
  102. int r = ((unsigned char *)pixels)[4 * fromx + 2 + pitch * fromy];
  103. int hue, sat, val;
  104. int min = r, max = r, delta;
  105. if(min > g) min = g; if(max < g) max = g;
  106. if(min > b) min = b; if(max < b) max = b;
  107. delta = max - min;
  108. val = max; /* 0 - 255 */
  109. sat = max ? 256 * delta / max : 0; /* 0 - 255 */
  110. if(sat > (_get_dither() + 24) * 4)
  111. {
  112. /* XXX: Values should be between 1 and 6, but since we
  113. * are dithering, there may be overflows, hence our bigger
  114. * *_colors[] tables. */
  115. if( r == max )
  116. hue = 256 + 256 * (g - b) / delta;
  117. else if( g == max )
  118. hue = 768 + 256 * (b - r) / delta;
  119. else
  120. hue = 1280 + 256 * (r - g) / delta;
  121. hue = (hue + 128 + 8 * _get_dither()) / 256;
  122. if(val > (_get_dither() + 40) * 4)
  123. caca_set_color(light_colors[hue]);
  124. else
  125. caca_set_color(dark_colors[hue]);
  126. }
  127. else
  128. {
  129. caca_set_color(white_colors[max * 3 / 256]);
  130. }
  131. caca_putchar(x, y, foo[(r + g + b + 2 * _get_dither()) / 3 / 25]);
  132. _increment_dither();
  133. }
  134. }
  135. }
  136. /*
  137. * XXX: The following functions are local.
  138. */
  139. /*
  140. * No dithering
  141. */
  142. static void init_no_dither(int line)
  143. {
  144. ;
  145. }
  146. static int get_no_dither(void)
  147. {
  148. return 0;
  149. }
  150. static void increment_no_dither(void)
  151. {
  152. return;
  153. }
  154. /*
  155. * Ordered dithering
  156. */
  157. static int dither4x4[] = {-8, 0, -6, 2,
  158. 4, -4, 6, -2,
  159. -5, 3, -7, 1,
  160. 7, -1, 5, -3};
  161. static int *dither_table;
  162. static int dither_index;
  163. static void init_ordered_dither(int line)
  164. {
  165. dither_table = dither4x4 + (line % 4) * 4;
  166. dither_index = 0;
  167. }
  168. static int get_ordered_dither(void)
  169. {
  170. return dither_table[dither_index];
  171. }
  172. static void increment_ordered_dither(void)
  173. {
  174. dither_index = (dither_index + 1) % 4;
  175. }
  176. /*
  177. * Random dithering
  178. */
  179. static void init_random_dither(int line)
  180. {
  181. ;
  182. }
  183. static int get_random_dither(void)
  184. {
  185. return caca_rand(-8, 7);
  186. }
  187. static void increment_random_dither(void)
  188. {
  189. return;
  190. }