Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
 
 
 
 
 
 

279 lignes
7.6 KiB

  1. /*
  2. * libpipi Proper image processing implementation library
  3. * Copyright (c) 2004-2008 Sam Hocevar <sam@zoy.org>
  4. * 2008 Jean-Yves Lamoureux <jylam@lnxscene.org
  5. * All Rights Reserved
  6. *
  7. * $Id$
  8. *
  9. * This library is free software. It comes without any warranty, to
  10. * the extent permitted by applicable law. You can redistribute it
  11. * and/or modify it under the terms of the Do What The Fuck You Want
  12. * To Public License, Version 2, as published by Sam Hocevar. See
  13. * http://sam.zoy.org/wtfpl/COPYING for more details.
  14. */
  15. /*
  16. * line.c: line rendering functions
  17. */
  18. #include "config.h"
  19. #include "common.h"
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #include "pipi.h"
  24. #include "pipi_internals.h"
  25. struct line
  26. {
  27. int x1, y1;
  28. int x2, y2;
  29. void (*draw) (pipi_image_t*, struct line*);
  30. union {
  31. uint32_t color32;
  32. float colorf[3];
  33. };
  34. union {
  35. uint32_t *buf_u32;
  36. float *buf_f;
  37. };
  38. };
  39. static void clip_line(pipi_image_t*, struct line*);
  40. static uint8_t clip_bits(pipi_image_t*, int, int);
  41. static void draw_aliased_line_u32(pipi_image_t*, struct line*);
  42. static void draw_aliased_line_gray(pipi_image_t *img, struct line* s);
  43. static void draw_aliased_line_float(pipi_image_t *img, struct line* s);
  44. static void draw_antialiased_line_float(pipi_image_t *img, struct line* s);
  45. static void draw_antialiased_line_gray(pipi_image_t *img, struct line* s);
  46. int pipi_draw_line(pipi_image_t *img , int x1, int y1, int x2, int y2, uint32_t c, int aa)
  47. {
  48. struct line s;
  49. s.x1 = x1;
  50. s.y1 = y1;
  51. s.x2 = x2;
  52. s.y2 = y2;
  53. /* No Transparency routine for u32 yet, fallback to float version */
  54. if(img->last_modified == PIPI_PIXELS_RGBA_C)
  55. {
  56. if(!aa)
  57. {
  58. uint32_t *dstdata;
  59. dstdata = (uint32_t *)pipi_getpixels(img, PIPI_PIXELS_RGBA_C)->pixels;
  60. s.color32 = c;
  61. s.buf_u32 = dstdata;
  62. s.draw = draw_aliased_line_u32;
  63. }
  64. else
  65. {
  66. float *dstdata;
  67. dstdata = (float *)pipi_getpixels(img, PIPI_PIXELS_RGBA_F)->pixels;
  68. s.colorf[2] = ((c&0x00FF0000)>>16)/255.0f; /* XXX FIXME */
  69. s.colorf[1] = ((c&0x0000FF00)>>8)/255.0f; /* XXX FIXME */
  70. s.colorf[0] = (c&0x000000FF)/255.0f; /* XXX FIXME */
  71. s.buf_f = dstdata;
  72. s.draw = draw_antialiased_line_float;
  73. }
  74. }
  75. else if(img->last_modified == PIPI_PIXELS_Y_F)
  76. {
  77. float *dstdata;
  78. dstdata = (float *)pipi_getpixels(img, PIPI_PIXELS_Y_F)->pixels;
  79. s.colorf[0] = c/255.0f; /* XXX FIXME */
  80. s.buf_f = dstdata;
  81. s.draw = aa==0?draw_aliased_line_gray:draw_antialiased_line_gray;
  82. }
  83. else
  84. {
  85. float *dstdata;
  86. dstdata = (float *)pipi_getpixels(img, PIPI_PIXELS_RGBA_F)->pixels;
  87. s.colorf[2] = ((c&0x00FF0000)>>16)/255.0f; /* XXX FIXME */
  88. s.colorf[1] = ((c&0x0000FF00)>>8)/255.0f; /* XXX FIXME */
  89. s.colorf[0] = (c&0x000000FF)/255.0f; /* XXX FIXME */
  90. s.buf_f = dstdata;
  91. s.draw = aa==0?draw_aliased_line_float:draw_antialiased_line_float;
  92. }
  93. clip_line(img, &s);
  94. return 0;
  95. }
  96. int pipi_draw_polyline(pipi_image_t *img, int const x[], int const y[],
  97. int n, uint32_t c)
  98. {
  99. int i;
  100. struct line s;
  101. if(img->last_modified == PIPI_PIXELS_RGBA_C)
  102. {
  103. uint32_t *dstdata;
  104. dstdata = (uint32_t *)pipi_getpixels(img, PIPI_PIXELS_RGBA_C)->pixels;
  105. s.color32 = c;
  106. s.buf_u32 = dstdata;
  107. s.draw = draw_aliased_line_u32;
  108. }
  109. else
  110. {
  111. float *dstdata;
  112. dstdata = (float *)pipi_getpixels(img, PIPI_PIXELS_RGBA_F)->pixels;
  113. s.colorf[0] = (c&0x00FF0000)/255.0f; /* XXX FIXME */
  114. s.colorf[1] = (c&0x0000FF00)/255.0f; /* XXX FIXME */
  115. s.colorf[2] = (c&0x000000FF)/255.0f; /* XXX FIXME */
  116. s.buf_f = dstdata;
  117. s.draw = draw_aliased_line_float;
  118. img->last_modified = PIPI_PIXELS_RGBA_F;
  119. }
  120. for(i = 0; i < n; i++)
  121. {
  122. s.x1 = x[i];
  123. s.y1 = y[i];
  124. s.x2 = x[i+1];
  125. s.y2 = y[i+1];
  126. clip_line(img, &s);
  127. }
  128. return 0;
  129. }
  130. /*
  131. * XXX: The following functions are local.
  132. */
  133. /* Generic Cohen-Sutherland line clipping function. */
  134. static void clip_line(pipi_image_t *img, struct line* s)
  135. {
  136. uint8_t bits1, bits2;
  137. bits1 = clip_bits(img, s->x1, s->y1);
  138. bits2 = clip_bits(img, s->x2, s->y2);
  139. if(bits1 & bits2)
  140. return;
  141. if(bits1 == 0)
  142. {
  143. if(bits2 == 0)
  144. s->draw(img, s);
  145. else
  146. {
  147. int tmp;
  148. tmp = s->x1; s->x1 = s->x2; s->x2 = tmp;
  149. tmp = s->y1; s->y1 = s->y2; s->y2 = tmp;
  150. clip_line(img, s);
  151. }
  152. return;
  153. }
  154. if(bits1 & (1<<0))
  155. {
  156. s->y1 = s->y2 - (s->x2 - 0) * (s->y2 - s->y1) / (s->x2 - s->x1);
  157. s->x1 = 0;
  158. }
  159. else if(bits1 & (1<<1))
  160. {
  161. int xmax = img->w - 1;
  162. s->y1 = s->y2 - (s->x2 - xmax) * (s->y2 - s->y1) / (s->x2 - s->x1);
  163. s->x1 = xmax;
  164. }
  165. else if(bits1 & (1<<2))
  166. {
  167. s->x1 = s->x2 - (s->y2 - 0) * (s->x2 - s->x1) / (s->y2 - s->y1);
  168. s->y1 = 0;
  169. }
  170. else if(bits1 & (1<<3))
  171. {
  172. int ymax = img->h - 1;
  173. s->x1 = s->x2 - (s->y2 - ymax) * (s->x2 - s->x1) / (s->y2 - s->y1);
  174. s->y1 = ymax;
  175. }
  176. clip_line(img, s);
  177. }
  178. /* Helper function for clip_line(). */
  179. static uint8_t clip_bits(pipi_image_t *img, int x, int y)
  180. {
  181. uint8_t b = 0;
  182. if(x < 0)
  183. b |= (1<<0);
  184. else if(x >= (int)img->w)
  185. b |= (1<<1);
  186. if(y < 0)
  187. b |= (1<<2);
  188. else if(y >= (int)img->h)
  189. b |= (1<<3);
  190. return b;
  191. }
  192. /* Solid line drawing function, using Bresenham's mid-point line
  193. * scan-conversion algorithm. */
  194. static void draw_aliased_line_u32(pipi_image_t *img, struct line* s)
  195. {
  196. #undef ASSIGN
  197. #define ASSIGN(x, y, w) s->buf_u32[x+y*w] = s->color32;
  198. #include "line_template.c"
  199. }
  200. static void draw_aliased_line_float(pipi_image_t *img, struct line* s)
  201. {
  202. #undef ASSIGN
  203. #define ASSIGN(x, y, w) s->buf_f[(x*4)+y*(w*4)] = s->colorf[0]; \
  204. s->buf_f[1 + (x*4)+y*(w*4)] = s->colorf[1]; \
  205. s->buf_f[2 + (x*4)+y*(w*4)] = s->colorf[2];
  206. #include "line_template.c"
  207. }
  208. static void draw_aliased_line_gray(pipi_image_t *img, struct line* s)
  209. {
  210. #undef ASSIGN
  211. #define ASSIGN(x, y, w) s->buf_f[x+y*w] = s->colorf[0];
  212. #include "line_template.c"
  213. }
  214. /* Xiaolin Wu's line algorithm, as seen at http://portal.acm.org/citation.cfm?id=122734 */
  215. /* math.h doesn't like y0 (sucker) */
  216. float floorf(float x);
  217. float truncf(float x);
  218. float fabsf(float x);
  219. static float fractf(float d) { return (d - floorf(d)); }
  220. static float fractinvf(float d) { return (1 - (d - floorf(d))); }
  221. static void draw_antialiased_line_float(pipi_image_t *img, struct line* s)
  222. {
  223. /* Is that an horrible mess ? Yes, it is. */
  224. #undef PLOT
  225. #define PLOT(x, y, c) \
  226. s->buf_f[(((int)(x)*4))+((int)(y))*(img->w*4)] = \
  227. (c*s->colorf[0]) + (1-c) * s->buf_f[(((int)(x)*4))+((int)(y))*(img->w*4)]; \
  228. s->buf_f[(1+((int)(x)*4))+((int)(y))*(img->w*4)] = \
  229. (c*s->colorf[1]) + (1-c) * s->buf_f[(1+((int)(x)*4))+((int)(y))*(img->w*4)]; \
  230. s->buf_f[(2+((int)(x)*4))+((int)(y))*(img->w*4)] = \
  231. (c*s->colorf[2]) + (1-c) * s->buf_f[(2+((int)(x)*4))+((int)(y))*(img->w*4)];
  232. #include "aline_template.c"
  233. }
  234. static void draw_antialiased_line_gray(pipi_image_t *img, struct line* s)
  235. {
  236. #undef PLOT
  237. #define PLOT(x, y, c) s->buf_f[((int)(x))+((int)(y))*img->w] = \
  238. (c*s->colorf[0]) + (1-c) * s->buf_f[((int)(x))+((int)(y))*img->w];
  239. #include "aline_template.c"
  240. }