Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.
 
 
 
 
 
 

393 wiersze
11 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. #undef __USE_MISC /* THAT sucks */
  24. #undef __USE_XOPEN /* THAT sucks, too (avoid declaring y1 in math.h) */
  25. #include <math.h>
  26. #include "pipi.h"
  27. #include "pipi_internals.h"
  28. #if !defined TEMPLATE_FILE /* This file uses the template system */
  29. struct line
  30. {
  31. int x1, y1;
  32. int x2, y2;
  33. void (*draw) (pipi_image_t*, struct line*);
  34. union {
  35. uint32_t color32;
  36. float colorf[3];
  37. };
  38. union {
  39. uint32_t *buf_u32;
  40. float *buf_f;
  41. };
  42. };
  43. #define TEMPLATE_FLAGS SET_FLAG_GRAY | SET_FLAG_8BIT
  44. #define TEMPLATE_FILE "paint/line.c"
  45. #include "pipi_template.h"
  46. static void clip_line(pipi_image_t*, struct line*);
  47. static uint8_t clip_bits(pipi_image_t*, int, int);
  48. static void draw_antialiased_line_float(pipi_image_t *img, struct line* s);
  49. static void draw_antialiased_line_gray(pipi_image_t *img, struct line* s);
  50. int pipi_draw_line(pipi_image_t *img , int x1, int y1, int x2, int y2, uint32_t c, int aa)
  51. {
  52. struct line s;
  53. s.x1 = x1;
  54. s.y1 = y1;
  55. s.x2 = x2;
  56. s.y2 = y2;
  57. /* No Transparency routine for u32 yet, fallback to float version */
  58. if(img->last_modified == PIPI_PIXELS_RGBA_C)
  59. {
  60. if(!aa)
  61. {
  62. uint32_t *dstdata;
  63. dstdata = (uint32_t *)pipi_getpixels(img, PIPI_PIXELS_RGBA_C)->pixels;
  64. s.color32 = c;
  65. s.buf_u32 = dstdata;
  66. s.draw = aliased_line_8bit;
  67. }
  68. else
  69. {
  70. float *dstdata;
  71. dstdata = (float *)pipi_getpixels(img, PIPI_PIXELS_RGBA_F)->pixels;
  72. s.colorf[2] = ((c&0x00FF0000)>>16)/255.0f; /* XXX FIXME */
  73. s.colorf[1] = ((c&0x0000FF00)>>8)/255.0f; /* XXX FIXME */
  74. s.colorf[0] = (c&0x000000FF)/255.0f; /* XXX FIXME */
  75. s.buf_f = dstdata;
  76. s.draw = draw_antialiased_line_float;
  77. }
  78. }
  79. else if(img->last_modified == PIPI_PIXELS_Y_F)
  80. {
  81. float *dstdata;
  82. dstdata = (float *)pipi_getpixels(img, PIPI_PIXELS_Y_F)->pixels;
  83. s.colorf[0] = (c & 0xff) / 255.0f; /* XXX FIXME */
  84. s.buf_f = dstdata;
  85. s.draw = aa==0?aliased_line_gray:draw_antialiased_line_gray;
  86. }
  87. else
  88. {
  89. float *dstdata;
  90. dstdata = (float *)pipi_getpixels(img, PIPI_PIXELS_RGBA_F)->pixels;
  91. s.colorf[2] = ((c&0x00FF0000)>>16)/255.0f; /* XXX FIXME */
  92. s.colorf[1] = ((c&0x0000FF00)>>8)/255.0f; /* XXX FIXME */
  93. s.colorf[0] = (c&0x000000FF)/255.0f; /* XXX FIXME */
  94. s.buf_f = dstdata;
  95. s.draw = aa==0?aliased_line:draw_antialiased_line_float;
  96. }
  97. clip_line(img, &s);
  98. return 0;
  99. }
  100. int pipi_draw_polyline(pipi_image_t *img, int const x[], int const y[],
  101. int n, uint32_t c, int aa)
  102. {
  103. int i;
  104. struct line s;
  105. if(img->last_modified == PIPI_PIXELS_RGBA_C)
  106. {
  107. if(!aa)
  108. {
  109. uint32_t *dstdata;
  110. dstdata = (uint32_t *)pipi_getpixels(img, PIPI_PIXELS_RGBA_C)->pixels;
  111. s.color32 = c;
  112. s.buf_u32 = dstdata;
  113. s.draw = aliased_line_8bit;
  114. }
  115. else
  116. {
  117. float *dstdata;
  118. dstdata = (float *)pipi_getpixels(img, PIPI_PIXELS_RGBA_F)->pixels;
  119. s.colorf[2] = ((c&0x00FF0000)>>16)/255.0f; /* XXX FIXME */
  120. s.colorf[1] = ((c&0x0000FF00)>>8)/255.0f; /* XXX FIXME */
  121. s.colorf[0] = (c&0x000000FF)/255.0f; /* XXX FIXME */
  122. s.buf_f = dstdata;
  123. s.draw = draw_antialiased_line_float;
  124. }
  125. }
  126. else if(img->last_modified == PIPI_PIXELS_Y_F)
  127. {
  128. float *dstdata;
  129. dstdata = (float *)pipi_getpixels(img, PIPI_PIXELS_Y_F)->pixels;
  130. s.colorf[0] = c/255.0f; /* XXX FIXME */
  131. s.buf_f = dstdata;
  132. s.draw = aa==0?aliased_line_gray:draw_antialiased_line_gray;
  133. }
  134. else
  135. {
  136. float *dstdata;
  137. dstdata = (float *)pipi_getpixels(img, PIPI_PIXELS_RGBA_F)->pixels;
  138. s.colorf[0] = (c&0x00FF0000)/255.0f; /* XXX FIXME */
  139. s.colorf[1] = (c&0x0000FF00)/255.0f; /* XXX FIXME */
  140. s.colorf[2] = (c&0x000000FF)/255.0f; /* XXX FIXME */
  141. s.buf_f = dstdata;
  142. s.draw = aa==0?aliased_line:draw_antialiased_line_float;
  143. img->last_modified = PIPI_PIXELS_RGBA_F;
  144. }
  145. for(i = 0; i < n; i++)
  146. {
  147. s.x1 = x[i];
  148. s.y1 = y[i];
  149. s.x2 = x[i+1];
  150. s.y2 = y[i+1];
  151. clip_line(img, &s);
  152. }
  153. return 0;
  154. }
  155. /*
  156. * XXX: The following functions are local.
  157. */
  158. /* Generic Cohen-Sutherland line clipping function. */
  159. static void clip_line(pipi_image_t *img, struct line* s)
  160. {
  161. uint8_t bits1, bits2;
  162. bits1 = clip_bits(img, s->x1, s->y1);
  163. bits2 = clip_bits(img, s->x2, s->y2);
  164. if(bits1 & bits2)
  165. return;
  166. if(bits1 == 0)
  167. {
  168. if(bits2 == 0)
  169. s->draw(img, s);
  170. else
  171. {
  172. int tmp;
  173. tmp = s->x1; s->x1 = s->x2; s->x2 = tmp;
  174. tmp = s->y1; s->y1 = s->y2; s->y2 = tmp;
  175. clip_line(img, s);
  176. }
  177. return;
  178. }
  179. if(bits1 & (1<<0))
  180. {
  181. s->y1 = s->y2 - (s->x2 - 0) * (s->y2 - s->y1) / (s->x2 - s->x1);
  182. s->x1 = 0;
  183. }
  184. else if(bits1 & (1<<1))
  185. {
  186. int xmax = img->w - 1;
  187. s->y1 = s->y2 - (s->x2 - xmax) * (s->y2 - s->y1) / (s->x2 - s->x1);
  188. s->x1 = xmax;
  189. }
  190. else if(bits1 & (1<<2))
  191. {
  192. s->x1 = s->x2 - (s->y2 - 0) * (s->x2 - s->x1) / (s->y2 - s->y1);
  193. s->y1 = 0;
  194. }
  195. else if(bits1 & (1<<3))
  196. {
  197. int ymax = img->h - 1;
  198. s->x1 = s->x2 - (s->y2 - ymax) * (s->x2 - s->x1) / (s->y2 - s->y1);
  199. s->y1 = ymax;
  200. }
  201. clip_line(img, s);
  202. }
  203. /* Helper function for clip_line(). */
  204. static uint8_t clip_bits(pipi_image_t *img, int x, int y)
  205. {
  206. uint8_t b = 0;
  207. if(x < 0)
  208. b |= (1<<0);
  209. else if(x >= (int)img->w)
  210. b |= (1<<1);
  211. if(y < 0)
  212. b |= (1<<2);
  213. else if(y >= (int)img->h)
  214. b |= (1<<3);
  215. return b;
  216. }
  217. /* Xiaolin Wu's line algorithm, as seen at http://portal.acm.org/citation.cfm?id=122734 */
  218. /* math.h doesn't like y1 (sucker) */
  219. float floorf(float x);
  220. float truncf(float x);
  221. float fabsf(float x);
  222. static float fractf(float d) { return (d - floorf(d)); }
  223. static float fractinvf(float d) { return (1 - (d - floorf(d))); }
  224. static void draw_antialiased_line_float(pipi_image_t *img, struct line* s)
  225. {
  226. /* Is that an horrible mess ? Yes, it is. */
  227. #undef PLOT
  228. #define PLOT(x, y, c) \
  229. { int qwer = (((int)(x)*4))+((int)(y))*(img->w*4);\
  230. int qweg = (1+((int)(x)*4))+((int)(y))*(img->w*4); \
  231. int qweb = (2+((int)(x)*4))+((int)(y))*(img->w*4); \
  232. s->buf_f[qwer] = (c*s->colorf[0]) + (1-c) * s->buf_f[qwer]; \
  233. s->buf_f[qweg] = (c*s->colorf[1]) + (1-c) * s->buf_f[qweg]; \
  234. s->buf_f[qweb] = (c*s->colorf[2]) + (1-c) * s->buf_f[qweb]; \
  235. if(s->buf_f[qwer] > 1.0f) s->buf_f[qwer] = 1.0f; \
  236. if(s->buf_f[qwer] < 0.0f || isnan(s->buf_f[qwer])) s->buf_f[qwer] = 0.0f; \
  237. if(s->buf_f[qweg] > 1.0f) s->buf_f[qweg] = 1.0f; \
  238. if(s->buf_f[qweg] < 0.0f || isnan(s->buf_f[qweg])) s->buf_f[qweg] = 0.0f; \
  239. if(s->buf_f[qweb] > 1.0f) s->buf_f[qweb] = 1.0f; \
  240. if(s->buf_f[qweb] < 0.0f || isnan(s->buf_f[qweb])) s->buf_f[qweb] = 0.0f; }
  241. #include "aline_template.h"
  242. }
  243. static void draw_antialiased_line_gray(pipi_image_t *img, struct line* s)
  244. {
  245. #undef PLOT
  246. #define PLOT(x, y, c) s->buf_f[((int)(x))+((int)(y))*img->w] = \
  247. (c*s->colorf[0]) + (1-c) * s->buf_f[((int)(x))+((int)(y))*img->w]; \
  248. if(s->buf_f[((int)(x))+((int)(y))*img->w] > 1.0f) s->buf_f[((int)(x))+((int)(y))*img->w] = 1.0f; \
  249. if(s->buf_f[((int)(x))+((int)(y))*img->w] < 0.0f) s->buf_f[((int)(x))+((int)(y))*img->w] = 0.0f; \
  250. if(isnan(s->buf_f[((int)(x))+((int)(y))*img->w])) s->buf_f[((int)(x))+((int)(y))*img->w] = 0.0f;
  251. #include "aline_template.h"
  252. }
  253. #else /* XXX: the following functions use the template system */
  254. /* Solid line drawing function, using Bresenham's mid-point line
  255. * scan-conversion algorithm. */
  256. static void SUFFIX(aliased_line)(pipi_image_t *img, struct line* s)
  257. {
  258. int x1, y1, x2, y2;
  259. int dx, dy;
  260. int xinc, yinc;
  261. x1 = s->x1; y1 = s->y1; x2 = s->x2; y2 = s->y2;
  262. dx = abs(x2 - x1);
  263. dy = abs(y2 - y1);
  264. xinc = (x1 > x2) ? -1 : 1;
  265. yinc = (y1 > y2) ? -1 : 1;
  266. if(dx >= dy)
  267. {
  268. int dpr = dy << 1;
  269. int dpru = dpr - (dx << 1);
  270. int delta = dpr - dx;
  271. for(; dx >= 0; dx--)
  272. {
  273. if(FLAG_GRAY)
  274. {
  275. if(FLAG_8BIT)
  276. /* TODO */;
  277. else
  278. s->buf_f[x1 + y1 * img->w] = s->colorf[0];
  279. }
  280. else
  281. {
  282. if(FLAG_8BIT)
  283. s->buf_u32[x1 + y1 * img->w] = s->color32;
  284. else
  285. {
  286. s->buf_f[4 * (y1 * img->w + x1)] = s->colorf[0];
  287. s->buf_f[4 * (y1 * img->w + x1) + 1] = s->colorf[1];
  288. s->buf_f[4 * (y1 * img->w + x1) + 2] = s->colorf[2];
  289. }
  290. }
  291. if(delta > 0)
  292. {
  293. x1 += xinc;
  294. y1 += yinc;
  295. delta += dpru;
  296. }
  297. else
  298. {
  299. x1 += xinc;
  300. delta += dpr;
  301. }
  302. }
  303. }
  304. else
  305. {
  306. int dpr = dx << 1;
  307. int dpru = dpr - (dy << 1);
  308. int delta = dpr - dy;
  309. for(; dy >= 0; dy--)
  310. {
  311. if(FLAG_GRAY)
  312. {
  313. if(FLAG_8BIT)
  314. /* TODO */;
  315. else
  316. s->buf_f[x1 + y1 * img->w] = s->colorf[0];
  317. }
  318. else
  319. {
  320. if(FLAG_8BIT)
  321. s->buf_u32[x1 + y1 * img->w] = s->color32;
  322. else
  323. {
  324. s->buf_f[4 * (y1 * img->w + x1)] = s->colorf[0];
  325. s->buf_f[4 * (y1 * img->w + x1) + 1] = s->colorf[1];
  326. s->buf_f[4 * (y1 * img->w + x1) + 2] = s->colorf[2];
  327. }
  328. }
  329. if(delta > 0)
  330. {
  331. x1 += xinc;
  332. y1 += yinc;
  333. delta += dpru;
  334. }
  335. else
  336. {
  337. y1 += yinc;
  338. delta += dpr;
  339. }
  340. }
  341. }
  342. }
  343. #endif