Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.
 
 
 
 
 
 

471 рядки
12 KiB

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