1 /* Copyright (C) 2001-2017 Peter Selinger.
2 This file is part of Potrace. It is free software and it is covered
3 by the GNU General Public License. See the file COPYING for details. */
4
5 #ifdef HAVE_CONFIG_H
6 #include <config.h>
7 #endif
8
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <limits.h>
13
14 #include "potracelib.h"
15 #include "curve.h"
16 #include "lists.h"
17 #include "bitmap.h"
18 #include "decompose.h"
19 #include "progress.h"
20
21 /* ---------------------------------------------------------------------- */
22 /* deterministically and efficiently hash (x,y) into a pseudo-random bit */
23
detrand(int x,int y)24 static inline int detrand(int x, int y) {
25 unsigned int z;
26 static const unsigned char t[256] = {
27 /* non-linear sequence: constant term of inverse in GF(8),
28 mod x^8+x^4+x^3+x+1 */
29 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1,
30 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0,
31 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
32 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1,
33 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0,
34 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0,
35 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0,
36 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1,
37 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0,
38 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1,
39 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
40 };
41
42 /* 0x04b3e375 and 0x05a8ef93 are chosen to contain every possible
43 5-bit sequence */
44 z = ((0x04b3e375 * x) ^ y) * 0x05a8ef93;
45 z = t[z & 0xff] ^ t[(z>>8) & 0xff] ^ t[(z>>16) & 0xff] ^ t[(z>>24) & 0xff];
46 return z;
47 }
48
49 /* ---------------------------------------------------------------------- */
50 /* auxiliary bitmap manipulations */
51
52 /* set the excess padding to 0 */
bm_clearexcess(potrace_bitmap_t * bm)53 static void bm_clearexcess(potrace_bitmap_t *bm) {
54 potrace_word mask;
55 int y;
56
57 if (bm->w % BM_WORDBITS != 0) {
58 mask = BM_ALLBITS << (BM_WORDBITS - (bm->w % BM_WORDBITS));
59 for (y=0; y<bm->h; y++) {
60 *bm_index(bm, bm->w, y) &= mask;
61 }
62 }
63 }
64
65 struct bbox_s {
66 int x0, x1, y0, y1; /* bounding box */
67 };
68 typedef struct bbox_s bbox_t;
69
70 /* clear the bm, assuming the bounding box is set correctly (faster
71 than clearing the whole bitmap) */
clear_bm_with_bbox(potrace_bitmap_t * bm,bbox_t * bbox)72 static void clear_bm_with_bbox(potrace_bitmap_t *bm, bbox_t *bbox) {
73 int imin = (bbox->x0 / BM_WORDBITS);
74 int imax = ((bbox->x1 + BM_WORDBITS-1) / BM_WORDBITS);
75 int i, y;
76
77 for (y=bbox->y0; y<bbox->y1; y++) {
78 for (i=imin; i<imax; i++) {
79 bm_scanline(bm, y)[i] = 0;
80 }
81 }
82 }
83
84 /* ---------------------------------------------------------------------- */
85 /* auxiliary functions */
86
87 /* return the "majority" value of bitmap bm at intersection (x,y). We
88 assume that the bitmap is balanced at "radius" 1. */
majority(potrace_bitmap_t * bm,int x,int y)89 static int majority(potrace_bitmap_t *bm, int x, int y) {
90 int i, a, ct;
91
92 for (i=2; i<5; i++) { /* check at "radius" i */
93 ct = 0;
94 for (a=-i+1; a<=i-1; a++) {
95 ct += BM_GET(bm, x+a, y+i-1) ? 1 : -1;
96 ct += BM_GET(bm, x+i-1, y+a-1) ? 1 : -1;
97 ct += BM_GET(bm, x+a-1, y-i) ? 1 : -1;
98 ct += BM_GET(bm, x-i, y+a) ? 1 : -1;
99 }
100 if (ct>0) {
101 return 1;
102 } else if (ct<0) {
103 return 0;
104 }
105 }
106 return 0;
107 }
108
109 /* ---------------------------------------------------------------------- */
110 /* decompose image into paths */
111
112 /* efficiently invert bits [x,infty) and [xa,infty) in line y. Here xa
113 must be a multiple of BM_WORDBITS. */
xor_to_ref(potrace_bitmap_t * bm,int x,int y,int xa)114 static void xor_to_ref(potrace_bitmap_t *bm, int x, int y, int xa) {
115 int xhi = x & -BM_WORDBITS;
116 int xlo = x & (BM_WORDBITS-1); /* = x % BM_WORDBITS */
117 int i;
118
119 if (xhi<xa) {
120 for (i = xhi; i < xa; i+=BM_WORDBITS) {
121 *bm_index(bm, i, y) ^= BM_ALLBITS;
122 }
123 } else {
124 for (i = xa; i < xhi; i+=BM_WORDBITS) {
125 *bm_index(bm, i, y) ^= BM_ALLBITS;
126 }
127 }
128 /* note: the following "if" is needed because x86 treats a<<b as
129 a<<(b&31). I spent hours looking for this bug. */
130 if (xlo) {
131 *bm_index(bm, xhi, y) ^= (BM_ALLBITS << (BM_WORDBITS - xlo));
132 }
133 }
134
135 /* a path is represented as an array of points, which are thought to
136 lie on the corners of pixels (not on their centers). The path point
137 (x,y) is the lower left corner of the pixel (x,y). Paths are
138 represented by the len/pt components of a path_t object (which
139 also stores other information about the path) */
140
141 /* xor the given pixmap with the interior of the given path. Note: the
142 path must be within the dimensions of the pixmap. */
xor_path(potrace_bitmap_t * bm,path_t * p)143 static void xor_path(potrace_bitmap_t *bm, path_t *p) {
144 int xa, x, y, k, y1;
145
146 if (p->priv->len <= 0) { /* a path of length 0 is silly, but legal */
147 return;
148 }
149
150 y1 = p->priv->pt[p->priv->len-1].y;
151
152 xa = p->priv->pt[0].x & -BM_WORDBITS;
153 for (k=0; k<p->priv->len; k++) {
154 x = p->priv->pt[k].x;
155 y = p->priv->pt[k].y;
156
157 if (y != y1) {
158 /* efficiently invert the rectangle [x,xa] x [y,y1] */
159 xor_to_ref(bm, x, min(y,y1), xa);
160 y1 = y;
161 }
162 }
163 }
164
165 /* Find the bounding box of a given path. Path is assumed to be of
166 non-zero length. */
setbbox_path(bbox_t * bbox,path_t * p)167 static void setbbox_path(bbox_t *bbox, path_t *p) {
168 int x, y;
169 int k;
170
171 bbox->y0 = INT_MAX;
172 bbox->y1 = 0;
173 bbox->x0 = INT_MAX;
174 bbox->x1 = 0;
175
176 for (k=0; k<p->priv->len; k++) {
177 x = p->priv->pt[k].x;
178 y = p->priv->pt[k].y;
179
180 if (x < bbox->x0) {
181 bbox->x0 = x;
182 }
183 if (x > bbox->x1) {
184 bbox->x1 = x;
185 }
186 if (y < bbox->y0) {
187 bbox->y0 = y;
188 }
189 if (y > bbox->y1) {
190 bbox->y1 = y;
191 }
192 }
193 }
194
195 /* compute a path in the given pixmap, separating black from white.
196 Start path at the point (x0,x1), which must be an upper left corner
197 of the path. Also compute the area enclosed by the path. Return a
198 new path_t object, or NULL on error (note that a legitimate path
199 cannot have length 0). Sign is required for correct interpretation
200 of turnpolicies. */
findpath(potrace_bitmap_t * bm,int x0,int y0,int sign,int turnpolicy)201 static path_t *findpath(potrace_bitmap_t *bm, int x0, int y0, int sign, int turnpolicy) {
202 int x, y, dirx, diry, len, size, area;
203 int c, d, tmp;
204 point_t *pt, *pt1;
205 path_t *p = NULL;
206
207 x = x0;
208 y = y0;
209 dirx = 0;
210 diry = -1;
211
212 len = size = 0;
213 pt = NULL;
214 area = 0;
215
216 while (1) {
217 /* add point to path */
218 if (len>=size) {
219 size += 100;
220 size = (int)(1.3 * size);
221 pt1 = (point_t *)realloc(pt, size * sizeof(point_t));
222 if (!pt1) {
223 goto error;
224 }
225 pt = pt1;
226 }
227 pt[len].x = x;
228 pt[len].y = y;
229 len++;
230
231 /* move to next point */
232 x += dirx;
233 y += diry;
234 area += x*diry;
235
236 /* path complete? */
237 if (x==x0 && y==y0) {
238 break;
239 }
240
241 /* determine next direction */
242 c = BM_GET(bm, x + (dirx+diry-1)/2, y + (diry-dirx-1)/2);
243 d = BM_GET(bm, x + (dirx-diry-1)/2, y + (diry+dirx-1)/2);
244
245 if (c && !d) { /* ambiguous turn */
246 if (turnpolicy == POTRACE_TURNPOLICY_RIGHT
247 || (turnpolicy == POTRACE_TURNPOLICY_BLACK && sign == '+')
248 || (turnpolicy == POTRACE_TURNPOLICY_WHITE && sign == '-')
249 || (turnpolicy == POTRACE_TURNPOLICY_RANDOM && detrand(x,y))
250 || (turnpolicy == POTRACE_TURNPOLICY_MAJORITY && majority(bm, x, y))
251 || (turnpolicy == POTRACE_TURNPOLICY_MINORITY && !majority(bm, x, y))) {
252 tmp = dirx; /* right turn */
253 dirx = diry;
254 diry = -tmp;
255 } else {
256 tmp = dirx; /* left turn */
257 dirx = -diry;
258 diry = tmp;
259 }
260 } else if (c) { /* right turn */
261 tmp = dirx;
262 dirx = diry;
263 diry = -tmp;
264 } else if (!d) { /* left turn */
265 tmp = dirx;
266 dirx = -diry;
267 diry = tmp;
268 }
269 } /* while this path */
270
271 /* allocate new path object */
272 p = path_new();
273 if (!p) {
274 goto error;
275 }
276
277 p->priv->pt = pt;
278 p->priv->len = len;
279 p->area = area;
280 p->sign = sign;
281
282 return p;
283
284 error:
285 free(pt);
286 return NULL;
287 }
288
289 /* Give a tree structure to the given path list, based on "insideness"
290 testing. I.e., path A is considered "below" path B if it is inside
291 path B. The input pathlist is assumed to be ordered so that "outer"
292 paths occur before "inner" paths. The tree structure is stored in
293 the "childlist" and "sibling" components of the path_t
294 structure. The linked list structure is also changed so that
295 negative path components are listed immediately after their
296 positive parent. Note: some backends may ignore the tree
297 structure, others may use it e.g. to group path components. We
298 assume that in the input, point 0 of each path is an "upper left"
299 corner of the path, as returned by bm_to_pathlist. This makes it
300 easy to find an "interior" point. The bm argument should be a
301 bitmap of the correct size (large enough to hold all the paths),
302 and will be used as scratch space. Return 0 on success or -1 on
303 error with errno set. */
304
pathlist_to_tree(path_t * plist,potrace_bitmap_t * bm)305 static void pathlist_to_tree(path_t *plist, potrace_bitmap_t *bm) {
306 path_t *p, *p1;
307 path_t *heap, *heap1;
308 path_t *cur;
309 path_t *head;
310 path_t **plist_hook; /* for fast appending to linked list */
311 path_t **hook_in, **hook_out; /* for fast appending to linked list */
312 bbox_t bbox;
313
314 bm_clear(bm, 0);
315
316 /* save original "next" pointers */
317 list_forall(p, plist) {
318 p->sibling = p->next;
319 p->childlist = NULL;
320 }
321
322 heap = plist;
323
324 /* the heap holds a list of lists of paths. Use "childlist" field
325 for outer list, "next" field for inner list. Each of the sublists
326 is to be turned into a tree. This code is messy, but it is
327 actually fast. Each path is rendered exactly once. We use the
328 heap to get a tail recursive algorithm: the heap holds a list of
329 pathlists which still need to be transformed. */
330
331 while (heap) {
332 /* unlink first sublist */
333 cur = heap;
334 heap = heap->childlist;
335 cur->childlist = NULL;
336
337 /* unlink first path */
338 head = cur;
339 cur = cur->next;
340 head->next = NULL;
341
342 /* render path */
343 xor_path(bm, head);
344 setbbox_path(&bbox, head);
345
346 /* now do insideness test for each element of cur; append it to
347 head->childlist if it's inside head, else append it to
348 head->next. */
349 hook_in=&head->childlist;
350 hook_out=&head->next;
351 list_forall_unlink(p, cur) {
352 if (p->priv->pt[0].y <= bbox.y0) {
353 list_insert_beforehook(p, hook_out);
354 /* append the remainder of the list to hook_out */
355 *hook_out = cur;
356 break;
357 }
358 if (BM_GET(bm, p->priv->pt[0].x, p->priv->pt[0].y-1)) {
359 list_insert_beforehook(p, hook_in);
360 } else {
361 list_insert_beforehook(p, hook_out);
362 }
363 }
364
365 /* clear bm */
366 clear_bm_with_bbox(bm, &bbox);
367
368 /* now schedule head->childlist and head->next for further
369 processing */
370 if (head->next) {
371 head->next->childlist = heap;
372 heap = head->next;
373 }
374 if (head->childlist) {
375 head->childlist->childlist = heap;
376 heap = head->childlist;
377 }
378 }
379
380 /* copy sibling structure from "next" to "sibling" component */
381 p = plist;
382 while (p) {
383 p1 = p->sibling;
384 p->sibling = p->next;
385 p = p1;
386 }
387
388 /* reconstruct a new linked list ("next") structure from tree
389 ("childlist", "sibling") structure. This code is slightly messy,
390 because we use a heap to make it tail recursive: the heap
391 contains a list of childlists which still need to be
392 processed. */
393 heap = plist;
394 if (heap) {
395 heap->next = NULL; /* heap is a linked list of childlists */
396 }
397 plist = NULL;
398 plist_hook = &plist;
399 while (heap) {
400 heap1 = heap->next;
401 for (p=heap; p; p=p->sibling) {
402 /* p is a positive path */
403 /* append to linked list */
404 list_insert_beforehook(p, plist_hook);
405
406 /* go through its children */
407 for (p1=p->childlist; p1; p1=p1->sibling) {
408 /* append to linked list */
409 list_insert_beforehook(p1, plist_hook);
410 /* append its childlist to heap, if non-empty */
411 if (p1->childlist) {
412 list_append(path_t, heap1, p1->childlist);
413 }
414 }
415 }
416 heap = heap1;
417 }
418
419 return;
420 }
421
422 /* find the next set pixel in a row <= y. Pixels are searched first
423 left-to-right, then top-down. In other words, (x,y)<(x',y') if y>y'
424 or y=y' and x<x'. If found, return 0 and store pixel in
425 (*xp,*yp). Else return 1. Note that this function assumes that
426 excess bytes have been cleared with bm_clearexcess. */
findnext(potrace_bitmap_t * bm,int * xp,int * yp)427 static int findnext(potrace_bitmap_t *bm, int *xp, int *yp) {
428 int x;
429 int y;
430 int x0;
431
432 x0 = (*xp) & ~(BM_WORDBITS-1);
433
434 for (y=*yp; y>=0; y--) {
435 for (x=x0; x<bm->w && x>=0; x+=(unsigned)BM_WORDBITS) {
436 if (*bm_index(bm, x, y)) {
437 while (!BM_GET(bm, x, y)) {
438 x++;
439 }
440 /* found */
441 *xp = x;
442 *yp = y;
443 return 0;
444 }
445 }
446 x0 = 0;
447 }
448 /* not found */
449 return 1;
450 }
451
452 /* Decompose the given bitmap into paths. Returns a linked list of
453 path_t objects with the fields len, pt, area, sign filled
454 in. Returns 0 on success with plistp set, or -1 on error with errno
455 set. */
456
bm_to_pathlist(const potrace_bitmap_t * bm,path_t ** plistp,const potrace_param_t * param,progress_t * progress)457 int bm_to_pathlist(const potrace_bitmap_t *bm, path_t **plistp, const potrace_param_t *param, progress_t *progress) {
458 int x;
459 int y;
460 path_t *p;
461 path_t *plist = NULL; /* linked list of path objects */
462 path_t **plist_hook = &plist; /* used to speed up appending to linked list */
463 potrace_bitmap_t *bm1 = NULL;
464 int sign;
465
466 bm1 = bm_dup(bm);
467 if (!bm1) {
468 goto error;
469 }
470
471 /* be sure the byte padding on the right is set to 0, as the fast
472 pixel search below relies on it */
473 bm_clearexcess(bm1);
474
475 /* iterate through components */
476 x = 0;
477 y = bm1->h - 1;
478 while (findnext(bm1, &x, &y) == 0) {
479 /* calculate the sign by looking at the original */
480 sign = BM_GET(bm, x, y) ? '+' : '-';
481
482 /* calculate the path */
483 p = findpath(bm1, x, y+1, sign, param->turnpolicy);
484 if (p==NULL) {
485 goto error;
486 }
487
488 /* update buffered image */
489 xor_path(bm1, p);
490
491 /* if it's a turd, eliminate it, else append it to the list */
492 if (p->area <= param->turdsize) {
493 path_free(p);
494 } else {
495 list_insert_beforehook(p, plist_hook);
496 }
497
498 if (bm1->h > 0) { /* to be sure */
499 progress_update(1-y/(double)bm1->h, progress);
500 }
501 }
502
503 pathlist_to_tree(plist, bm1);
504 bm_free(bm1);
505 *plistp = plist;
506
507 progress_update(1.0, progress);
508
509 return 0;
510
511 error:
512 bm_free(bm1);
513 list_forall_unlink(p, plist) {
514 path_free(p);
515 }
516 return -1;
517 }
518