25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

line.c 12 KiB

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