LightningIsMyName

GEGL op working strange?

Jul 11th, 2011
247
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.70 KB | None | 0 0
  1. /* This file is an image processing operation for GEGL
  2. *
  3. * GEGL is free software; you can redistribute it and/or
  4. * modify it under the terms of the GNU Lesser General Public
  5. * License as published by the Free Software Foundation; either
  6. * version 3 of the License, or (at your option) any later version.
  7. *
  8. * GEGL is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. * Lesser General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU Lesser General Public
  14. * License along with GEGL; if not, see <http://www.gnu.org/licenses/>.
  15. *
  16. * Copyright 2011 Barak Itkin <[email protected]>
  17. */
  18.  
  19. #include "config.h"
  20. #include <glib/gi18n-lib.h>
  21.  
  22.  
  23. #ifdef GEGL_CHANT_PROPERTIES
  24.  
  25. /* Needed to tril GEGL into thinking this OP can save a file */
  26. gegl_chant_string (path, _("File"), "",
  27. _("Target path and filename, use '-' for stdout."))
  28.  
  29. gegl_chant_pointer (ptList, _("Points"),
  30. _("A GPtrArray* of struct {gint x, y;} containing the points"))
  31.  
  32. gegl_chant_double (threshold, _("Threshold"), -G_MAXDOUBLE, G_MAXDOUBLE, 0.1,
  33. _("The threshold for determining the difference between black and white (white >= thres)"))
  34.  
  35.  
  36.  
  37. #else
  38.  
  39. #define GEGL_CHANT_TYPE_SINK
  40. #define GEGL_CHANT_C_FILE "selection2points.c"
  41.  
  42. #include "gegl-chant.h"
  43. #include <stdio.h>
  44.  
  45. /* 0
  46. *
  47. * 7 N 1
  48. * ^
  49. * |
  50. * |
  51. * 6 W<----+---->E 2
  52. * | =====>X
  53. * | ||
  54. * v ||
  55. * 5 S 3 ||
  56. * vv
  57. * 4 Y
  58. */
  59. typedef enum {
  60. D_N = 0, /* 000 */
  61. D_NE = 1, /* 001 */
  62. D_E = 2, /* 010 */
  63. D_SE = 3, /* 011 */
  64. D_S = 4, /* 100 */
  65. D_SW = 5, /* 101 */
  66. D_W = 6, /* 110 */
  67. D_NW = 7 /* 111 */
  68. } DIRECTION;
  69.  
  70. typedef struct {
  71. gint x, y;
  72. } SPoint;
  73.  
  74. #define cwdirection(t) (((t)+1)%8)
  75. #define ccwdirection(t) (((t)+7)%8)
  76. #define oppositedirection(t) (((t)+4)%8)
  77.  
  78. #define isSouth(s) (((s) == D_S) || ((s) == D_SE) || ((s) == D_SW))
  79. #define isNorth(s) (((s) == D_N) || ((s) == D_NE) || ((s) == D_NW))
  80.  
  81. #define isEast(s) (((s) == D_NE) || ((s) == D_E) || ((s) == D_SE))
  82. #define isWest(s) (((s) == D_NW) || ((s) == D_W) || ((s) == D_SW))
  83.  
  84. /**
  85. * Add a COPY of the given point into the array pts. The original point CAN
  86. * be freed later!
  87. */
  88. static void
  89. AddPoint (GPtrArray* pts, SPoint *pt)
  90. {
  91. SPoint *cpy = g_new (SPoint, 1);
  92. cpy->x = pt->x;
  93. cpy->y = pt->y;
  94.  
  95. printf ("Added %d,%d\n", pt->x, pt->y);
  96. g_ptr_array_add (pts, cpy);
  97. }
  98.  
  99. static inline void
  100. move (SPoint *pt, DIRECTION t, SPoint *dest)
  101. {
  102. dest->x = pt->x + (isEast(t) ? 1 : (isWest(t) ? -1 : 0));
  103. dest->y = pt->y + (isSouth(t) ? 1 : (isNorth(t) ? -1 : 0));
  104. }
  105.  
  106. typedef struct
  107. {
  108. gint xmin, xmax;
  109. gint ymin, ymax;
  110. gint rowstride;
  111. gdouble threshold;
  112. gdouble *im;
  113. } OutlineProcPrivate;
  114.  
  115. #define in_range(val,min,max) (((min) <= (val)) && ((val) <= (max)))
  116.  
  117. static inline gboolean
  118. is_inside (OutlineProcPrivate *OPP, SPoint *pt)
  119. {
  120. return in_range (pt->x, OPP->xmin, OPP->xmax)
  121. && in_range (pt->y, OPP->ymin, OPP->ymax);
  122. }
  123.  
  124. #define get_value(OPP,x,y) (((OPP)->im)[((y)-(OPP)->ymin)*(OPP)->rowstride+(x)-(OPP)->xmin])
  125. #define get_valuePT(OPP,pt) get_value(OPP,(pt)->x,(pt)->y)
  126.  
  127. static inline gboolean
  128. is_white (OutlineProcPrivate *OPP, SPoint *pt)
  129. {
  130. return is_inside (OPP, pt) && get_valuePT (OPP,pt) >= OPP->threshold;
  131. }
  132.  
  133. /* This function receives a white pixel (pt) and the direction of the movement
  134. * that lead to it (prevdirection). It will return the direction leading to the
  135. * next white pixel (while following the edges in CW order), and the pixel
  136. * itself would be stored in dest.
  137. *
  138. * The logic is simple:
  139. * 1. Try to continue in the same direction that lead us to the current pixel
  140. * 2. Dprev = oppposite(prevdirection)
  141. * 3. Dnow = cw(Dprev)
  142. * 4. While moving to Dnow is white:
  143. * 4.1. Dprev = Dnow
  144. * 4.2. Dnow = cw(D)
  145. * 5. Return the result - moving by Dprev
  146. */
  147. static inline
  148. DIRECTION walkCW (OutlineProcPrivate *OPP, DIRECTION prevdirection, SPoint *pt, SPoint *dest)
  149. {
  150. DIRECTION Dprev = oppositedirection(prevdirection);
  151. DIRECTION Dnow = cwdirection (Dprev);
  152.  
  153. SPoint ptN, ptP;
  154.  
  155. move (pt, Dprev, &ptP);
  156. move (pt, Dnow, &ptN);
  157.  
  158. while (is_white (OPP, &ptN))
  159. {
  160. Dprev = Dnow;
  161. ptP.x = ptN.x;
  162. ptP.y = ptN.y;
  163. Dnow = cwdirection (Dprev);
  164. move (pt, Dnow, &ptN);
  165. }
  166.  
  167. dest->x = ptP.x;
  168. dest->y = ptP.y;
  169. return Dprev;
  170. }
  171.  
  172. #define pteq(pt1,pt2) (((pt1)->x == (pt2)->x) && ((pt1)->y == (pt2)->y))
  173.  
  174. static void
  175. find_outline_ccw (OutlineProcPrivate *OPP, GPtrArray *pts)
  176. {
  177. gint x = OPP->xmin;
  178. gint y;
  179. gboolean found;
  180. SPoint START, pt, ptN;
  181. DIRECTION DIR, DIRN;
  182.  
  183. /* First of all try to find a white pixel */
  184. for (y = OPP->ymin; y < OPP->ymax; y++)
  185. for (x = OPP->xmin; x < OPP->xmax; x++)
  186. if (get_value (OPP, x, y) >= OPP->threshold)
  187. {
  188. found = TRUE;
  189. break;
  190. }
  191.  
  192. /* For now, assume a non empty selection */
  193. g_assert(found);
  194.  
  195. pt.x = START.x = x;
  196. pt.y = START.y = y;
  197. DIR = D_NW;
  198.  
  199. AddPoint (pts, &START);
  200.  
  201. DIRN = walkCW(OPP, DIR,&pt,&ptN);
  202.  
  203. while (! pteq(&ptN,&START))
  204. {
  205. AddPoint (pts, &ptN);
  206. pt.x = ptN.x;
  207. pt.y = ptN.y;
  208. DIR = DIRN;
  209. DIRN = walkCW(OPP, DIR,&pt,&ptN);
  210. }
  211. }
  212.  
  213. static gboolean
  214. process (GeglOperation *operation,
  215. GeglBuffer *input,
  216. const GeglRectangle *result)
  217. {
  218. GeglChantO *o = GEGL_CHANT_PROPERTIES (operation);
  219. // const GeglRectangle *rect = gegl_buffer_get_extent (input);
  220.  
  221. // TODO; get rid of this hack test leak
  222. GeglRectangle *rect = g_new(GeglRectangle, 1);
  223. rect->x = 0;
  224. rect->y = 0;
  225. rect->width = 50;
  226. rect->height = 50;
  227.  
  228.  
  229. OutlineProcPrivate *OPP = (OutlineProcPrivate *)o->chant_data;
  230. fprintf (stderr, "Rect %dx%d\n",rect->width,rect->height);
  231.  
  232. if (OPP == NULL)
  233. {
  234. printf ("Allocating %d\n",sizeof(OutlineProcPrivate));
  235. OPP = o->chant_data = g_malloc (sizeof(OutlineProcPrivate));
  236. }
  237.  
  238.  
  239. OPP->xmin = rect->x;
  240. OPP->ymin = rect->y;
  241. OPP->xmax = rect->x + rect->width - 1;
  242. OPP->ymax = rect->y + rect->height - 1;
  243. OPP->threshold = o->threshold;
  244. OPP->im = g_new (gdouble,(rect->width) * rect->height);
  245. OPP->rowstride = rect->width;
  246.  
  247. gegl_buffer_get (input, 1.0, rect, gegl_buffer_get_format (input), OPP->im, GEGL_AUTO_ROWSTRIDE);
  248.  
  249. // TODO: remove me!
  250. o->ptList = g_ptr_array_new ();
  251.  
  252. find_outline_ccw (OPP, o->ptList);
  253.  
  254. gint x, y;
  255. /* First of all try to find a white pixel */
  256. for (y = OPP->ymin; y < OPP->ymax; y++)
  257. {
  258. for (x = OPP->xmin; x < OPP->xmax; x++)
  259. {
  260. if (get_value (OPP, x, y) >= OPP->threshold)
  261. printf ("1");
  262. else
  263. printf ("0");
  264. }
  265. printf("\n");
  266. }
  267.  
  268. g_free (OPP->im);
  269. OPP->im = NULL;
  270.  
  271. return TRUE;
  272. }
  273.  
  274. static void
  275. finalize (GObject *object)
  276. {
  277. GeglChantO *o = GEGL_CHANT_PROPERTIES (object);
  278.  
  279. g_debug ("Finalizing!\n");
  280. if (o->chant_data)
  281. {
  282. g_free (o->chant_data);
  283. o->chant_data = NULL;
  284. }
  285.  
  286. G_OBJECT_CLASS (gegl_chant_parent_class)->finalize (object);
  287. }
  288.  
  289. static void
  290. prepare (GeglOperation *operation)
  291. {
  292. GeglChantO *o = GEGL_CHANT_PROPERTIES (operation);
  293. gegl_operation_set_format (operation, "input", babl_format("Y double"));
  294. // babl_format_new (babl_model ("RGBA"),
  295. // babl_type ("double"),
  296. // babl_component ("A"),
  297. // NULL));
  298.  
  299. g_debug ("Preparing!\n");
  300. if (o->chant_data == NULL)
  301. {
  302. o->chant_data = g_slice_new (OutlineProcPrivate);
  303. }
  304. }
  305.  
  306. static void
  307. gegl_chant_class_init (GeglChantClass *klass)
  308. {
  309. GeglOperationClass *operation_class;
  310. GeglOperationSinkClass *sink_class;
  311.  
  312. operation_class = GEGL_OPERATION_CLASS (klass);
  313. sink_class = GEGL_OPERATION_SINK_CLASS (klass);
  314.  
  315. sink_class->process = process;
  316. sink_class->needs_full = TRUE;
  317.  
  318.  
  319. operation_class->prepare = prepare;
  320. operation_class->name = "gegl:selection2points";
  321. operation_class->categories = "output";
  322. operation_class->description =
  323. _("Return the list of edge points of a white area in a black BG");
  324.  
  325. G_OBJECT_CLASS(klass)->finalize = finalize;
  326.  
  327. /* Needed to tril GEGL into thinking this OP can save a file */
  328. gegl_extension_handler_register_saver (".pts", "gegl:selection2points");
  329. }
  330.  
  331. #endif
Advertisement
Add Comment
Please, Sign In to add comment