Leptonica  1.77.0
Image processing and image analysis suite
maze.c
Go to the documentation of this file.
1 /*====================================================================*
2  - Copyright (C) 2001 Leptonica. All rights reserved.
3  -
4  - Redistribution and use in source and binary forms, with or without
5  - modification, are permitted provided that the following conditions
6  - are met:
7  - 1. Redistributions of source code must retain the above copyright
8  - notice, this list of conditions and the following disclaimer.
9  - 2. Redistributions in binary form must reproduce the above
10  - copyright notice, this list of conditions and the following
11  - disclaimer in the documentation and/or other materials
12  - provided with the distribution.
13  -
14  - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15  - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16  - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17  - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY
18  - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  - OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
23  - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24  - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  *====================================================================*/
26 
27 
55 #include <string.h>
56 #ifdef _WIN32
57 #include <stdlib.h>
58 #include <time.h>
59 #endif /* _WIN32 */
60 #include "allheaders.h"
61 
62 static const l_int32 MIN_MAZE_WIDTH = 50;
63 static const l_int32 MIN_MAZE_HEIGHT = 50;
64 
65 static const l_float32 DEFAULT_WALL_PROBABILITY = 0.65;
66 static const l_float32 DEFAULT_ANISOTROPY_RATIO = 0.25;
67 
68 enum { /* direction from parent to newly created element */
69  START_LOC = 0,
70  DIR_NORTH = 1,
71  DIR_SOUTH = 2,
72  DIR_WEST = 3,
73  DIR_EAST = 4
74 };
75 
76 struct MazeElement {
77  l_float32 distance;
78  l_int32 x;
79  l_int32 y;
80  l_uint32 val; /* value of maze pixel at this location */
81  l_int32 dir; /* direction from parent to child */
82 };
83 typedef struct MazeElement MAZEEL;
84 
85 
86 static MAZEEL *mazeelCreate(l_int32 x, l_int32 y, l_int32 dir);
87 static l_int32 localSearchForBackground(PIX *pix, l_int32 *px,
88  l_int32 *py, l_int32 maxrad);
89 
90 #ifndef NO_CONSOLE_IO
91 #define DEBUG_PATH 0
92 #define DEBUG_MAZE 0
93 #endif /* ~NO_CONSOLE_IO */
94 
95 
96 /*---------------------------------------------------------------------*
97  * Binary maze generation as cellular automaton *
98  *---------------------------------------------------------------------*/
141 PIX *
143  l_int32 h,
144  l_int32 xi,
145  l_int32 yi,
146  l_float32 wallps,
147  l_float32 ranis)
148 {
149 l_int32 x, y, dir;
150 l_uint32 val;
151 l_float32 frand, wallpf, testp;
152 MAZEEL *el, *elp;
153 PIX *pixd; /* the destination maze */
154 PIX *pixm; /* for bookkeeping, to indicate pixels already visited */
155 L_QUEUE *lq;
156 
157  /* On Windows, seeding is apparently necessary to get decent mazes.
158  * Windows rand() returns a value up to 2^15 - 1, whereas unix
159  * rand() returns a value up to 2^31 - 1. Therefore the generated
160  * mazes will differ on the two platforms. */
161 #ifdef _WIN32
162  srand(28*333);
163 #endif /* _WIN32 */
164 
165  if (w < MIN_MAZE_WIDTH)
166  w = MIN_MAZE_WIDTH;
167  if (h < MIN_MAZE_HEIGHT)
168  h = MIN_MAZE_HEIGHT;
169  if (xi <= 0 || xi >= w)
170  xi = w / 6;
171  if (yi <= 0 || yi >= h)
172  yi = h / 5;
173  if (wallps < 0.05 || wallps > 0.95)
174  wallps = DEFAULT_WALL_PROBABILITY;
175  if (ranis < 0.05 || ranis > 1.0)
176  ranis = DEFAULT_ANISOTROPY_RATIO;
177  wallpf = wallps * ranis;
178 
179 #if DEBUG_MAZE
180  fprintf(stderr, "(w, h) = (%d, %d), (xi, yi) = (%d, %d)\n", w, h, xi, yi);
181  fprintf(stderr, "Using: prob(wall) = %7.4f, anisotropy factor = %7.4f\n",
182  wallps, ranis);
183 #endif /* DEBUG_MAZE */
184 
185  /* These are initialized to OFF */
186  pixd = pixCreate(w, h, 1);
187  pixm = pixCreate(w, h, 1);
188 
189  lq = lqueueCreate(0);
190 
191  /* Prime the queue with the first pixel; it is OFF */
192  el = mazeelCreate(xi, yi, START_LOC);
193  pixSetPixel(pixm, xi, yi, 1); /* mark visited */
194  lqueueAdd(lq, el);
195 
196  /* While we're at it ... */
197  while (lqueueGetCount(lq) > 0) {
198  elp = (MAZEEL *)lqueueRemove(lq);
199  x = elp->x;
200  y = elp->y;
201  dir = elp->dir;
202  if (x > 0) { /* check west */
203  pixGetPixel(pixm, x - 1, y, &val);
204  if (val == 0) { /* not yet visited */
205  pixSetPixel(pixm, x - 1, y, 1); /* mark visited */
206  frand = (l_float32)rand() / (l_float32)RAND_MAX;
207  testp = wallps;
208  if (dir == DIR_WEST)
209  testp = wallpf;
210  if (frand <= testp) { /* make it a wall */
211  pixSetPixel(pixd, x - 1, y, 1);
212  } else { /* not a wall */
213  el = mazeelCreate(x - 1, y, DIR_WEST);
214  lqueueAdd(lq, el);
215  }
216  }
217  }
218  if (y > 0) { /* check north */
219  pixGetPixel(pixm, x, y - 1, &val);
220  if (val == 0) { /* not yet visited */
221  pixSetPixel(pixm, x, y - 1, 1); /* mark visited */
222  frand = (l_float32)rand() / (l_float32)RAND_MAX;
223  testp = wallps;
224  if (dir == DIR_NORTH)
225  testp = wallpf;
226  if (frand <= testp) { /* make it a wall */
227  pixSetPixel(pixd, x, y - 1, 1);
228  } else { /* not a wall */
229  el = mazeelCreate(x, y - 1, DIR_NORTH);
230  lqueueAdd(lq, el);
231  }
232  }
233  }
234  if (x < w - 1) { /* check east */
235  pixGetPixel(pixm, x + 1, y, &val);
236  if (val == 0) { /* not yet visited */
237  pixSetPixel(pixm, x + 1, y, 1); /* mark visited */
238  frand = (l_float32)rand() / (l_float32)RAND_MAX;
239  testp = wallps;
240  if (dir == DIR_EAST)
241  testp = wallpf;
242  if (frand <= testp) { /* make it a wall */
243  pixSetPixel(pixd, x + 1, y, 1);
244  } else { /* not a wall */
245  el = mazeelCreate(x + 1, y, DIR_EAST);
246  lqueueAdd(lq, el);
247  }
248  }
249  }
250  if (y < h - 1) { /* check south */
251  pixGetPixel(pixm, x, y + 1, &val);
252  if (val == 0) { /* not yet visited */
253  pixSetPixel(pixm, x, y + 1, 1); /* mark visited */
254  frand = (l_float32)rand() / (l_float32)RAND_MAX;
255  testp = wallps;
256  if (dir == DIR_SOUTH)
257  testp = wallpf;
258  if (frand <= testp) { /* make it a wall */
259  pixSetPixel(pixd, x, y + 1, 1);
260  } else { /* not a wall */
261  el = mazeelCreate(x, y + 1, DIR_SOUTH);
262  lqueueAdd(lq, el);
263  }
264  }
265  }
266  LEPT_FREE(elp);
267  }
268 
269  lqueueDestroy(&lq, TRUE);
270  pixDestroy(&pixm);
271  return pixd;
272 }
273 
274 
275 static MAZEEL *
276 mazeelCreate(l_int32 x,
277  l_int32 y,
278  l_int32 dir)
279 {
280 MAZEEL *el;
281 
282  el = (MAZEEL *)LEPT_CALLOC(1, sizeof(MAZEEL));
283  el->x = x;
284  el->y = y;
285  el->dir = dir;
286  return el;
287 }
288 
289 
290 /*---------------------------------------------------------------------*
291  * Binary maze search *
292  *---------------------------------------------------------------------*/
338 PTA *
340  l_int32 xi,
341  l_int32 yi,
342  l_int32 xf,
343  l_int32 yf,
344  PIX **ppixd)
345 {
346 l_int32 i, j, x, y, w, h, d, found;
347 l_uint32 val, rpixel, gpixel, bpixel;
348 void **lines1, **linem1, **linep8, **lined32;
349 MAZEEL *el, *elp;
350 PIX *pixd; /* the shortest path written on the maze image */
351 PIX *pixm; /* for bookkeeping, to indicate pixels already visited */
352 PIX *pixp; /* for bookkeeping, to indicate direction to parent */
353 L_QUEUE *lq;
354 PTA *pta;
355 
356  PROCNAME("pixSearchBinaryMaze");
357 
358  if (ppixd) *ppixd = NULL;
359  if (!pixs)
360  return (PTA *)ERROR_PTR("pixs not defined", procName, NULL);
361  pixGetDimensions(pixs, &w, &h, &d);
362  if (d != 1)
363  return (PTA *)ERROR_PTR("pixs not 1 bpp", procName, NULL);
364  if (xi <= 0 || xi >= w)
365  return (PTA *)ERROR_PTR("xi not valid", procName, NULL);
366  if (yi <= 0 || yi >= h)
367  return (PTA *)ERROR_PTR("yi not valid", procName, NULL);
368  pixGetPixel(pixs, xi, yi, &val);
369  if (val != 0)
370  return (PTA *)ERROR_PTR("(xi,yi) not bg pixel", procName, NULL);
371  pixd = NULL;
372  pta = NULL;
373 
374  /* Find a bg pixel near input point (xf, yf) */
375  localSearchForBackground(pixs, &xf, &yf, 5);
376 
377 #if DEBUG_MAZE
378  fprintf(stderr, "(xi, yi) = (%d, %d), (xf, yf) = (%d, %d)\n",
379  xi, yi, xf, yf);
380 #endif /* DEBUG_MAZE */
381 
382  pixm = pixCreate(w, h, 1); /* initialized to OFF */
383  pixp = pixCreate(w, h, 8); /* direction to parent stored as enum val */
384  lines1 = pixGetLinePtrs(pixs, NULL);
385  linem1 = pixGetLinePtrs(pixm, NULL);
386  linep8 = pixGetLinePtrs(pixp, NULL);
387 
388  lq = lqueueCreate(0);
389 
390  /* Prime the queue with the first pixel; it is OFF */
391  el = mazeelCreate(xi, yi, 0); /* don't need direction here */
392  pixSetPixel(pixm, xi, yi, 1); /* mark visited */
393  lqueueAdd(lq, el);
394 
395  /* Fill up the pix storing directions to parents,
396  * stopping when we hit the point (xf, yf) */
397  found = FALSE;
398  while (lqueueGetCount(lq) > 0) {
399  elp = (MAZEEL *)lqueueRemove(lq);
400  x = elp->x;
401  y = elp->y;
402  if (x == xf && y == yf) {
403  found = TRUE;
404  LEPT_FREE(elp);
405  break;
406  }
407 
408  if (x > 0) { /* check to west */
409  val = GET_DATA_BIT(linem1[y], x - 1);
410  if (val == 0) { /* not yet visited */
411  SET_DATA_BIT(linem1[y], x - 1); /* mark visited */
412  val = GET_DATA_BIT(lines1[y], x - 1);
413  if (val == 0) { /* bg, not a wall */
414  SET_DATA_BYTE(linep8[y], x - 1, DIR_EAST); /* parent E */
415  el = mazeelCreate(x - 1, y, 0);
416  lqueueAdd(lq, el);
417  }
418  }
419  }
420  if (y > 0) { /* check north */
421  val = GET_DATA_BIT(linem1[y - 1], x);
422  if (val == 0) { /* not yet visited */
423  SET_DATA_BIT(linem1[y - 1], x); /* mark visited */
424  val = GET_DATA_BIT(lines1[y - 1], x);
425  if (val == 0) { /* bg, not a wall */
426  SET_DATA_BYTE(linep8[y - 1], x, DIR_SOUTH); /* parent S */
427  el = mazeelCreate(x, y - 1, 0);
428  lqueueAdd(lq, el);
429  }
430  }
431  }
432  if (x < w - 1) { /* check east */
433  val = GET_DATA_BIT(linem1[y], x + 1);
434  if (val == 0) { /* not yet visited */
435  SET_DATA_BIT(linem1[y], x + 1); /* mark visited */
436  val = GET_DATA_BIT(lines1[y], x + 1);
437  if (val == 0) { /* bg, not a wall */
438  SET_DATA_BYTE(linep8[y], x + 1, DIR_WEST); /* parent W */
439  el = mazeelCreate(x + 1, y, 0);
440  lqueueAdd(lq, el);
441  }
442  }
443  }
444  if (y < h - 1) { /* check south */
445  val = GET_DATA_BIT(linem1[y + 1], x);
446  if (val == 0) { /* not yet visited */
447  SET_DATA_BIT(linem1[y + 1], x); /* mark visited */
448  val = GET_DATA_BIT(lines1[y + 1], x);
449  if (val == 0) { /* bg, not a wall */
450  SET_DATA_BYTE(linep8[y + 1], x, DIR_NORTH); /* parent N */
451  el = mazeelCreate(x, y + 1, 0);
452  lqueueAdd(lq, el);
453  }
454  }
455  }
456  LEPT_FREE(elp);
457  }
458 
459  lqueueDestroy(&lq, TRUE);
460  pixDestroy(&pixm);
461  LEPT_FREE(linem1);
462 
463  if (ppixd) {
464  pixd = pixUnpackBinary(pixs, 32, 1);
465  *ppixd = pixd;
466  }
467  composeRGBPixel(255, 0, 0, &rpixel); /* start point */
468  composeRGBPixel(0, 255, 0, &gpixel);
469  composeRGBPixel(0, 0, 255, &bpixel); /* end point */
470 
471  if (found) {
472  L_INFO(" Path found\n", procName);
473  pta = ptaCreate(0);
474  x = xf;
475  y = yf;
476  while (1) {
477  ptaAddPt(pta, x, y);
478  if (x == xi && y == yi)
479  break;
480  if (pixd) /* write 'gpixel' onto the path */
481  pixSetPixel(pixd, x, y, gpixel);
482  pixGetPixel(pixp, x, y, &val);
483  if (val == DIR_NORTH)
484  y--;
485  else if (val == DIR_SOUTH)
486  y++;
487  else if (val == DIR_EAST)
488  x++;
489  else if (val == DIR_WEST)
490  x--;
491  }
492  } else {
493  L_INFO(" No path found\n", procName);
494  if (pixd) { /* paint all visited locations */
495  lined32 = pixGetLinePtrs(pixd, NULL);
496  for (i = 0; i < h; i++) {
497  for (j = 0; j < w; j++) {
498  if (GET_DATA_BYTE(linep8[i], j) != 0)
499  SET_DATA_FOUR_BYTES(lined32[i], j, gpixel);
500  }
501  }
502  LEPT_FREE(lined32);
503  }
504  }
505  if (pixd) {
506  pixSetPixel(pixd, xi, yi, rpixel);
507  pixSetPixel(pixd, xf, yf, bpixel);
508  }
509 
510  pixDestroy(&pixp);
511  LEPT_FREE(lines1);
512  LEPT_FREE(linep8);
513  return pta;
514 }
515 
516 
525 static l_int32
527  l_int32 *px,
528  l_int32 *py,
529  l_int32 maxrad)
530 {
531 l_int32 x, y, w, h, r, i, j;
532 l_uint32 val;
533 
534  x = *px;
535  y = *py;
536  pixGetPixel(pix, x, y, &val);
537  if (val == 0) return 0;
538 
539  /* For each value of r, restrict the search to the boundary
540  * pixels in a square centered on (x,y), clipping to the
541  * image boundaries if necessary. */
542  pixGetDimensions(pix, &w, &h, NULL);
543  for (r = 1; r < maxrad; r++) {
544  for (i = -r; i <= r; i++) {
545  if (y + i < 0 || y + i >= h)
546  continue;
547  for (j = -r; j <= r; j++) {
548  if (x + j < 0 || x + j >= w)
549  continue;
550  if (L_ABS(i) != r && L_ABS(j) != r) /* not on "r ring" */
551  continue;
552  pixGetPixel(pix, x + j, y + i, &val);
553  if (val == 0) {
554  *px = x + j;
555  *py = y + i;
556  return 0;
557  }
558  }
559  }
560  }
561  return 1;
562 }
563 
564 
565 
566 /*---------------------------------------------------------------------*
567  * Gray maze search *
568  *---------------------------------------------------------------------*/
722 PTA *
724  l_int32 xi,
725  l_int32 yi,
726  l_int32 xf,
727  l_int32 yf,
728  PIX **ppixd)
729 {
730 l_int32 x, y, w, h, d;
731 l_uint32 val, valr, vals, rpixel, gpixel, bpixel;
732 void **lines8, **liner32, **linep8;
733 l_int32 cost, dist, distparent, sival, sivals;
734 MAZEEL *el, *elp;
735 PIX *pixd; /* optionally plot the path on this RGB version of pixs */
736 PIX *pixr; /* for bookkeeping, to indicate the minimum distance */
737  /* to pixels already visited */
738 PIX *pixp; /* for bookkeeping, to indicate direction to parent */
739 L_HEAP *lh;
740 PTA *pta;
741 
742  PROCNAME("pixSearchGrayMaze");
743 
744  if (ppixd) *ppixd = NULL;
745  if (!pixs)
746  return (PTA *)ERROR_PTR("pixs not defined", procName, NULL);
747  pixGetDimensions(pixs, &w, &h, &d);
748  if (d != 8)
749  return (PTA *)ERROR_PTR("pixs not 8 bpp", procName, NULL);
750  if (xi <= 0 || xi >= w)
751  return (PTA *)ERROR_PTR("xi not valid", procName, NULL);
752  if (yi <= 0 || yi >= h)
753  return (PTA *)ERROR_PTR("yi not valid", procName, NULL);
754  pixd = NULL;
755  pta = NULL;
756 
757  /* Allocate stuff */
758  pixr = pixCreate(w, h, 32);
759  pixSetAll(pixr); /* initialize to max value */
760  pixp = pixCreate(w, h, 8); /* direction to parent stored as enum val */
761  lines8 = pixGetLinePtrs(pixs, NULL);
762  linep8 = pixGetLinePtrs(pixp, NULL);
763  liner32 = pixGetLinePtrs(pixr, NULL);
764  lh = lheapCreate(0, L_SORT_INCREASING); /* always remove closest pixels */
765 
766  /* Prime the heap with the first pixel */
767  pixGetPixel(pixs, xi, yi, &val);
768  el = mazeelCreate(xi, yi, 0); /* don't need direction here */
769  el->distance = 0;
770  pixGetPixel(pixs, xi, yi, &val);
771  el->val = val;
772  pixSetPixel(pixr, xi, yi, 0); /* distance is 0 */
773  lheapAdd(lh, el);
774 
775  /* Breadth-first search with priority queue (implemented by
776  a heap), labeling direction to parents in pixp and minimum
777  distance to visited pixels in pixr. Stop when we pull
778  the destination point (xf, yf) off the queue. */
779  while (lheapGetCount(lh) > 0) {
780  elp = (MAZEEL *)lheapRemove(lh);
781  if (!elp) {
782  L_ERROR("heap broken!!\n", procName);
783  goto cleanup_stuff;
784  }
785  x = elp->x;
786  y = elp->y;
787  if (x == xf && y == yf) { /* exit condition */
788  LEPT_FREE(elp);
789  break;
790  }
791  distparent = (l_int32)elp->distance;
792  val = elp->val;
793  sival = val;
794 
795  if (x > 0) { /* check to west */
796  vals = GET_DATA_BYTE(lines8[y], x - 1);
797  valr = GET_DATA_FOUR_BYTES(liner32[y], x - 1);
798  sivals = (l_int32)vals;
799  cost = 1 + L_ABS(sivals - sival); /* cost to move to this pixel */
800  dist = distparent + cost;
801  if (dist < valr) { /* shortest path so far to this pixel */
802  SET_DATA_FOUR_BYTES(liner32[y], x - 1, dist); /* new dist */
803  SET_DATA_BYTE(linep8[y], x - 1, DIR_EAST); /* parent to E */
804  el = mazeelCreate(x - 1, y, 0);
805  el->val = vals;
806  el->distance = dist;
807  lheapAdd(lh, el);
808  }
809  }
810  if (y > 0) { /* check north */
811  vals = GET_DATA_BYTE(lines8[y - 1], x);
812  valr = GET_DATA_FOUR_BYTES(liner32[y - 1], x);
813  sivals = (l_int32)vals;
814  cost = 1 + L_ABS(sivals - sival); /* cost to move to this pixel */
815  dist = distparent + cost;
816  if (dist < valr) { /* shortest path so far to this pixel */
817  SET_DATA_FOUR_BYTES(liner32[y - 1], x, dist); /* new dist */
818  SET_DATA_BYTE(linep8[y - 1], x, DIR_SOUTH); /* parent to S */
819  el = mazeelCreate(x, y - 1, 0);
820  el->val = vals;
821  el->distance = dist;
822  lheapAdd(lh, el);
823  }
824  }
825  if (x < w - 1) { /* check east */
826  vals = GET_DATA_BYTE(lines8[y], x + 1);
827  valr = GET_DATA_FOUR_BYTES(liner32[y], x + 1);
828  sivals = (l_int32)vals;
829  cost = 1 + L_ABS(sivals - sival); /* cost to move to this pixel */
830  dist = distparent + cost;
831  if (dist < valr) { /* shortest path so far to this pixel */
832  SET_DATA_FOUR_BYTES(liner32[y], x + 1, dist); /* new dist */
833  SET_DATA_BYTE(linep8[y], x + 1, DIR_WEST); /* parent to W */
834  el = mazeelCreate(x + 1, y, 0);
835  el->val = vals;
836  el->distance = dist;
837  lheapAdd(lh, el);
838  }
839  }
840  if (y < h - 1) { /* check south */
841  vals = GET_DATA_BYTE(lines8[y + 1], x);
842  valr = GET_DATA_FOUR_BYTES(liner32[y + 1], x);
843  sivals = (l_int32)vals;
844  cost = 1 + L_ABS(sivals - sival); /* cost to move to this pixel */
845  dist = distparent + cost;
846  if (dist < valr) { /* shortest path so far to this pixel */
847  SET_DATA_FOUR_BYTES(liner32[y + 1], x, dist); /* new dist */
848  SET_DATA_BYTE(linep8[y + 1], x, DIR_NORTH); /* parent to N */
849  el = mazeelCreate(x, y + 1, 0);
850  el->val = vals;
851  el->distance = dist;
852  lheapAdd(lh, el);
853  }
854  }
855  LEPT_FREE(elp);
856  }
857 
858  lheapDestroy(&lh, TRUE);
859 
860  if (ppixd) {
861  pixd = pixConvert8To32(pixs);
862  *ppixd = pixd;
863  }
864  composeRGBPixel(255, 0, 0, &rpixel); /* start point */
865  composeRGBPixel(0, 255, 0, &gpixel);
866  composeRGBPixel(0, 0, 255, &bpixel); /* end point */
867 
868  x = xf;
869  y = yf;
870  pta = ptaCreate(0);
871  while (1) { /* write path onto pixd */
872  ptaAddPt(pta, x, y);
873  if (x == xi && y == yi)
874  break;
875  if (pixd)
876  pixSetPixel(pixd, x, y, gpixel);
877  pixGetPixel(pixp, x, y, &val);
878  if (val == DIR_NORTH)
879  y--;
880  else if (val == DIR_SOUTH)
881  y++;
882  else if (val == DIR_EAST)
883  x++;
884  else if (val == DIR_WEST)
885  x--;
886  pixGetPixel(pixr, x, y, &val);
887 
888 #if DEBUG_PATH
889  fprintf(stderr, "(x,y) = (%d, %d); dist = %d\n", x, y, val);
890 #endif /* DEBUG_PATH */
891 
892  }
893  if (pixd) {
894  pixSetPixel(pixd, xi, yi, rpixel);
895  pixSetPixel(pixd, xf, yf, bpixel);
896  }
897 
898 cleanup_stuff:
899  lheapDestroy(&lh, TRUE);
900  pixDestroy(&pixp);
901  pixDestroy(&pixr);
902  LEPT_FREE(lines8);
903  LEPT_FREE(linep8);
904  LEPT_FREE(liner32);
905  return pta;
906 }
PIX * pixUnpackBinary(PIX *pixs, l_int32 depth, l_int32 invert)
pixUnpackBinary()
Definition: pixconv.c:1878
PTA * pixSearchGrayMaze(PIX *pixs, l_int32 xi, l_int32 yi, l_int32 xf, l_int32 yf, PIX **ppixd)
pixSearchGrayMaze()
Definition: maze.c:723
l_ok lheapAdd(L_HEAP *lh, void *item)
lheapAdd()
Definition: heap.c:186
l_ok ptaAddPt(PTA *pta, l_float32 x, l_float32 y)
ptaAddPt()
Definition: ptabasic.c:342
L_QUEUE * lqueueCreate(l_int32 nalloc)
lqueueCreate()
Definition: queue.c:90
PTA * ptaCreate(l_int32 n)
ptaCreate()
Definition: ptabasic.c:116
PIX * pixConvert8To32(PIX *pixs)
pixConvert8To32()
Definition: pixconv.c:3323
void ** pixGetLinePtrs(PIX *pix, l_int32 *psize)
pixGetLinePtrs()
Definition: pix1.c:1810
#define GET_DATA_FOUR_BYTES(pdata, n)
Definition: arrayaccess.h:231
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition: pix1.c:302
l_ok pixSetAll(PIX *pix)
pixSetAll()
Definition: pix2.c:741
static l_int32 localSearchForBackground(PIX *pix, l_int32 *px, l_int32 *py, l_int32 maxrad)
localSearchForBackground()
Definition: maze.c:526
void lheapDestroy(L_HEAP **plh, l_int32 freeflag)
lheapDestroy()
Definition: heap.c:145
#define GET_DATA_BIT(pdata, n)
Definition: arrayaccess.h:123
l_int32 lheapGetCount(L_HEAP *lh)
lheapGetCount()
Definition: heap.c:271
void * lqueueRemove(L_QUEUE *lq)
lqueueRemove()
Definition: queue.c:254
l_ok pixSetPixel(PIX *pix, l_int32 x, l_int32 y, l_uint32 val)
pixSetPixel()
Definition: pix2.c:253
l_ok lqueueAdd(L_QUEUE *lq, void *item)
lqueueAdd()
Definition: queue.c:187
Definition: queue.h:64
#define SET_DATA_BYTE(pdata, n, val)
Definition: arrayaccess.h:198
L_HEAP * lheapCreate(l_int32 nalloc, l_int32 direction)
lheapCreate()
Definition: heap.c:102
#define GET_DATA_BYTE(pdata, n)
Definition: arrayaccess.h:188
void * lheapRemove(L_HEAP *lh)
lheapRemove()
Definition: heap.c:242
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:543
l_int32 lqueueGetCount(L_QUEUE *lq)
lqueueGetCount()
Definition: queue.c:283
Definition: heap.h:77
PIX * generateBinaryMaze(l_int32 w, l_int32 h, l_int32 xi, l_int32 yi, l_float32 wallps, l_float32 ranis)
generateBinaryMaze()
Definition: maze.c:142
l_ok pixGetPixel(PIX *pix, l_int32 x, l_int32 y, l_uint32 *pval)
pixGetPixel()
Definition: pix2.c:180
l_ok pixGetDimensions(const PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
Definition: pix1.c:1065
#define SET_DATA_FOUR_BYTES(pdata, n, val)
Definition: arrayaccess.h:235
void lqueueDestroy(L_QUEUE **plq, l_int32 freeflag)
lqueueDestroy()
Definition: queue.c:131
Definition: pix.h:134
PTA * pixSearchBinaryMaze(PIX *pixs, l_int32 xi, l_int32 yi, l_int32 xf, l_int32 yf, PIX **ppixd)
pixSearchBinaryMaze()
Definition: maze.c:339
l_ok composeRGBPixel(l_int32 rval, l_int32 gval, l_int32 bval, l_uint32 *ppixel)
composeRGBPixel()
Definition: pix2.c:2671
#define SET_DATA_BIT(pdata, n)
Definition: arrayaccess.h:127
Definition: pix.h:517