Leptonica  1.82.0
Image processing and image analysis suite
pix3.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 
112 #ifdef HAVE_CONFIG_H
113 #include <config_auto.h>
114 #endif /* HAVE_CONFIG_H */
115 
116 #include <string.h>
117 #include <math.h>
118 #include "allheaders.h"
119 
120 static BOXA *findTileRegionsForSearch(BOX *box, l_int32 w, l_int32 h,
121  l_int32 searchdir, l_int32 mindist,
122  l_int32 tsize, l_int32 ntiles);
123 
124 #ifndef NO_CONSOLE_IO
125 #define EQUAL_SIZE_WARNING 0
126 #endif /* ~NO_CONSOLE_IO */
127 
128 /*-------------------------------------------------------------*
129  * Masked operations *
130  *-------------------------------------------------------------*/
162 l_ok
164  PIX *pixm,
165  l_uint32 val)
166 {
167 l_int32 wd, hd, wm, hm, w, h, d, wpld, wplm;
168 l_int32 i, j, rval, gval, bval;
169 l_uint32 *datad, *datam, *lined, *linem;
170 
171  PROCNAME("pixSetMasked");
172 
173  if (!pixd)
174  return ERROR_INT("pixd not defined", procName, 1);
175  if (!pixm) {
176  L_WARNING("no mask; nothing to do\n", procName);
177  return 0;
178  }
179  if (pixGetColormap(pixd)) {
180  extractRGBValues(val, &rval, &gval, &bval);
181  return pixSetMaskedCmap(pixd, pixm, 0, 0, rval, gval, bval);
182  }
183 
184  if (pixGetDepth(pixm) != 1)
185  return ERROR_INT("pixm not 1 bpp", procName, 1);
186  d = pixGetDepth(pixd);
187  if (d == 1)
188  val &= 1;
189  else if (d == 2)
190  val &= 3;
191  else if (d == 4)
192  val &= 0x0f;
193  else if (d == 8)
194  val &= 0xff;
195  else if (d == 16)
196  val &= 0xffff;
197  else if (d != 32)
198  return ERROR_INT("pixd not 1, 2, 4, 8, 16 or 32 bpp", procName, 1);
199  pixGetDimensions(pixm, &wm, &hm, NULL);
200 
201  /* If d == 1, use rasterop; it's about 25x faster */
202  if (d == 1) {
203  if (val == 0) {
204  PIX *pixmi = pixInvert(NULL, pixm);
205  pixRasterop(pixd, 0, 0, wm, hm, PIX_MASK, pixmi, 0, 0);
206  pixDestroy(&pixmi);
207  } else { /* val == 1 */
208  pixRasterop(pixd, 0, 0, wm, hm, PIX_PAINT, pixm, 0, 0);
209  }
210  return 0;
211  }
212 
213  /* For d < 32, use rasterop for val == 0 (black); ~3x faster. */
214  if (d < 32 && val == 0) {
215  PIX *pixmd = pixUnpackBinary(pixm, d, 1);
216  pixRasterop(pixd, 0, 0, wm, hm, PIX_MASK, pixmd, 0, 0);
217  pixDestroy(&pixmd);
218  return 0;
219  }
220 
221  /* For d < 32, use rasterop for val == maxval (white); ~3x faster. */
222  if (d < 32 && val == ((1 << d) - 1)) {
223  PIX *pixmd = pixUnpackBinary(pixm, d, 0);
224  pixRasterop(pixd, 0, 0, wm, hm, PIX_PAINT, pixmd, 0, 0);
225  pixDestroy(&pixmd);
226  return 0;
227  }
228 
229  pixGetDimensions(pixd, &wd, &hd, &d);
230  w = L_MIN(wd, wm);
231  h = L_MIN(hd, hm);
232  if (L_ABS(wd - wm) > 7 || L_ABS(hd - hm) > 7) /* allow a small tolerance */
233  L_WARNING("pixd and pixm sizes differ\n", procName);
234 
235  datad = pixGetData(pixd);
236  datam = pixGetData(pixm);
237  wpld = pixGetWpl(pixd);
238  wplm = pixGetWpl(pixm);
239  for (i = 0; i < h; i++) {
240  lined = datad + i * wpld;
241  linem = datam + i * wplm;
242  for (j = 0; j < w; j++) {
243  if (GET_DATA_BIT(linem, j)) {
244  switch(d)
245  {
246  case 2:
247  SET_DATA_DIBIT(lined, j, val);
248  break;
249  case 4:
250  SET_DATA_QBIT(lined, j, val);
251  break;
252  case 8:
253  SET_DATA_BYTE(lined, j, val);
254  break;
255  case 16:
256  SET_DATA_TWO_BYTES(lined, j, val);
257  break;
258  case 32:
259  *(lined + j) = val;
260  break;
261  default:
262  return ERROR_INT("shouldn't get here", procName, 1);
263  }
264  }
265  }
266  }
267 
268  return 0;
269 }
270 
271 
301 l_ok
303  PIX *pixm,
304  l_uint32 val,
305  l_int32 x,
306  l_int32 y)
307 {
308 l_int32 wm, hm, d;
309 PIX *pixmu, *pixc;
310 
311  PROCNAME("pixSetMaskedGeneral");
312 
313  if (!pixd)
314  return ERROR_INT("pixd not defined", procName, 1);
315  if (!pixm) /* nothing to do */
316  return 0;
317 
318  d = pixGetDepth(pixd);
319  if (d != 8 && d != 16 && d != 32)
320  return ERROR_INT("pixd not 8, 16 or 32 bpp", procName, 1);
321  if (pixGetDepth(pixm) != 1)
322  return ERROR_INT("pixm not 1 bpp", procName, 1);
323 
324  /* Unpack binary to depth d, with inversion: 1 --> 0, 0 --> 0xff... */
325  if ((pixmu = pixUnpackBinary(pixm, d, 1)) == NULL)
326  return ERROR_INT("pixmu not made", procName, 1);
327 
328  /* Clear stenciled pixels in pixd */
329  pixGetDimensions(pixm, &wm, &hm, NULL);
330  pixRasterop(pixd, x, y, wm, hm, PIX_SRC & PIX_DST, pixmu, 0, 0);
331 
332  /* Generate image with requisite color */
333  if ((pixc = pixCreateTemplate(pixmu)) == NULL) {
334  pixDestroy(&pixmu);
335  return ERROR_INT("pixc not made", procName, 1);
336  }
337  pixSetAllArbitrary(pixc, val);
338 
339  /* Invert stencil mask, and paint color color into stencil */
340  pixInvert(pixmu, pixmu);
341  pixAnd(pixmu, pixmu, pixc);
342 
343  /* Finally, repaint stenciled pixels, with val, in pixd */
344  pixRasterop(pixd, x, y, wm, hm, PIX_SRC | PIX_DST, pixmu, 0, 0);
345 
346  pixDestroy(&pixmu);
347  pixDestroy(&pixc);
348  return 0;
349 }
350 
351 
381 l_ok
383  PIX *pixs,
384  PIX *pixm)
385 {
386 l_int32 w, h, d, ws, hs, ds, wm, hm, dm, wmin, hmin;
387 l_int32 wpl, wpls, wplm, i, j, val;
388 l_uint32 *data, *datas, *datam, *line, *lines, *linem;
389 PIX *pixt;
390 
391  PROCNAME("pixCombineMasked");
392 
393  if (!pixm) /* nothing to do */
394  return 0;
395  if (!pixd)
396  return ERROR_INT("pixd not defined", procName, 1);
397  if (!pixs)
398  return ERROR_INT("pixs not defined", procName, 1);
399  pixGetDimensions(pixd, &w, &h, &d);
400  pixGetDimensions(pixs, &ws, &hs, &ds);
401  pixGetDimensions(pixm, &wm, &hm, &dm);
402  if (d != ds)
403  return ERROR_INT("pixs and pixd depths differ", procName, 1);
404  if (dm != 1)
405  return ERROR_INT("pixm not 1 bpp", procName, 1);
406  if (d != 1 && d != 8 && d != 32)
407  return ERROR_INT("pixd not 1, 8 or 32 bpp", procName, 1);
408  if (pixGetColormap(pixd) || pixGetColormap(pixs))
409  return ERROR_INT("pixs and/or pixd is cmapped", procName, 1);
410 
411  /* For d = 1, use rasterop. pixt is the part from pixs, under
412  * the fg of pixm, that is to be combined with pixd. We also
413  * use pixt to remove all fg of pixd that is under the fg of pixm.
414  * Then pixt and pixd are combined by ORing. */
415  wmin = L_MIN(w, L_MIN(ws, wm));
416  hmin = L_MIN(h, L_MIN(hs, hm));
417  if (d == 1) {
418  pixt = pixAnd(NULL, pixs, pixm);
419  pixRasterop(pixd, 0, 0, wmin, hmin, PIX_DST & PIX_NOT(PIX_SRC),
420  pixm, 0, 0);
421  pixRasterop(pixd, 0, 0, wmin, hmin, PIX_SRC | PIX_DST, pixt, 0, 0);
422  pixDestroy(&pixt);
423  return 0;
424  }
425 
426  data = pixGetData(pixd);
427  datas = pixGetData(pixs);
428  datam = pixGetData(pixm);
429  wpl = pixGetWpl(pixd);
430  wpls = pixGetWpl(pixs);
431  wplm = pixGetWpl(pixm);
432  if (d == 8) {
433  for (i = 0; i < hmin; i++) {
434  line = data + i * wpl;
435  lines = datas + i * wpls;
436  linem = datam + i * wplm;
437  for (j = 0; j < wmin; j++) {
438  if (GET_DATA_BIT(linem, j)) {
439  val = GET_DATA_BYTE(lines, j);
440  SET_DATA_BYTE(line, j, val);
441  }
442  }
443  }
444  } else { /* d == 32 */
445  for (i = 0; i < hmin; i++) {
446  line = data + i * wpl;
447  lines = datas + i * wpls;
448  linem = datam + i * wplm;
449  for (j = 0; j < wmin; j++) {
450  if (GET_DATA_BIT(linem, j))
451  line[j] = lines[j];
452  }
453  }
454  }
455 
456  return 0;
457 }
458 
459 
500 l_ok
502  PIX *pixs,
503  PIX *pixm,
504  l_int32 x,
505  l_int32 y)
506 {
507 l_int32 d, w, h, ws, hs, ds, wm, hm, dm, wmin, hmin;
508 l_int32 wpl, wpls, wplm, i, j, val;
509 l_uint32 *data, *datas, *datam, *line, *lines, *linem;
510 PIX *pixt;
511 
512  PROCNAME("pixCombineMaskedGeneral");
513 
514  if (!pixm) /* nothing to do */
515  return 0;
516  if (!pixd)
517  return ERROR_INT("pixd not defined", procName, 1);
518  if (!pixs)
519  return ERROR_INT("pixs not defined", procName, 1);
520  pixGetDimensions(pixd, &w, &h, &d);
521  pixGetDimensions(pixs, &ws, &hs, &ds);
522  pixGetDimensions(pixm, &wm, &hm, &dm);
523  if (d != ds)
524  return ERROR_INT("pixs and pixd depths differ", procName, 1);
525  if (dm != 1)
526  return ERROR_INT("pixm not 1 bpp", procName, 1);
527  if (d != 1 && d != 8 && d != 32)
528  return ERROR_INT("pixd not 1, 8 or 32 bpp", procName, 1);
529  if (pixGetColormap(pixd) || pixGetColormap(pixs))
530  return ERROR_INT("pixs and/or pixd is cmapped", procName, 1);
531 
532  /* For d = 1, use rasterop. pixt is the part from pixs, under
533  * the fg of pixm, that is to be combined with pixd. We also
534  * use pixt to remove all fg of pixd that is under the fg of pixm.
535  * Then pixt and pixd are combined by ORing. */
536  wmin = L_MIN(ws, wm);
537  hmin = L_MIN(hs, hm);
538  if (d == 1) {
539  pixt = pixAnd(NULL, pixs, pixm);
540  pixRasterop(pixd, x, y, wmin, hmin, PIX_DST & PIX_NOT(PIX_SRC),
541  pixm, 0, 0);
542  pixRasterop(pixd, x, y, wmin, hmin, PIX_SRC | PIX_DST, pixt, 0, 0);
543  pixDestroy(&pixt);
544  return 0;
545  }
546 
547  wpl = pixGetWpl(pixd);
548  data = pixGetData(pixd);
549  wpls = pixGetWpl(pixs);
550  datas = pixGetData(pixs);
551  wplm = pixGetWpl(pixm);
552  datam = pixGetData(pixm);
553 
554  for (i = 0; i < hmin; i++) {
555  if (y + i < 0 || y + i >= h) continue;
556  line = data + (y + i) * wpl;
557  lines = datas + i * wpls;
558  linem = datam + i * wplm;
559  for (j = 0; j < wmin; j++) {
560  if (x + j < 0 || x + j >= w) continue;
561  if (GET_DATA_BIT(linem, j)) {
562  switch (d)
563  {
564  case 8:
565  val = GET_DATA_BYTE(lines, j);
566  SET_DATA_BYTE(line, x + j, val);
567  break;
568  case 32:
569  *(line + x + j) = *(lines + j);
570  break;
571  default:
572  return ERROR_INT("shouldn't get here", procName, 1);
573  }
574  }
575  }
576  }
577 
578  return 0;
579 }
580 
581 
625 l_ok
627  PIX *pixm,
628  l_int32 x,
629  l_int32 y,
630  l_uint32 val)
631 {
632 l_int32 d, w, h, wm, hm, wpl, wplm, i, j, rval, gval, bval;
633 l_uint32 *data, *datam, *line, *linem;
634 
635  PROCNAME("pixPaintThroughMask");
636 
637  if (!pixm) /* nothing to do */
638  return 0;
639  if (!pixd)
640  return ERROR_INT("pixd not defined", procName, 1);
641  if (pixGetColormap(pixd)) {
642  extractRGBValues(val, &rval, &gval, &bval);
643  return pixSetMaskedCmap(pixd, pixm, x, y, rval, gval, bval);
644  }
645 
646  if (pixGetDepth(pixm) != 1)
647  return ERROR_INT("pixm not 1 bpp", procName, 1);
648  d = pixGetDepth(pixd);
649  if (d == 1)
650  val &= 1;
651  else if (d == 2)
652  val &= 3;
653  else if (d == 4)
654  val &= 0x0f;
655  else if (d == 8)
656  val &= 0xff;
657  else if (d == 16)
658  val &= 0xffff;
659  else if (d != 32)
660  return ERROR_INT("pixd not 1, 2, 4, 8, 16 or 32 bpp", procName, 1);
661  pixGetDimensions(pixm, &wm, &hm, NULL);
662 
663  /* If d == 1, use rasterop; it's about 25x faster. */
664  if (d == 1) {
665  if (val == 0) {
666  PIX *pixmi = pixInvert(NULL, pixm);
667  pixRasterop(pixd, x, y, wm, hm, PIX_MASK, pixmi, 0, 0);
668  pixDestroy(&pixmi);
669  } else { /* val == 1 */
670  pixRasterop(pixd, x, y, wm, hm, PIX_PAINT, pixm, 0, 0);
671  }
672  return 0;
673  }
674 
675  /* For d < 32, use rasterop if val == 0 (black); ~3x faster. */
676  if (d < 32 && val == 0) {
677  PIX *pixmd = pixUnpackBinary(pixm, d, 1);
678  pixRasterop(pixd, x, y, wm, hm, PIX_MASK, pixmd, 0, 0);
679  pixDestroy(&pixmd);
680  return 0;
681  }
682 
683  /* For d < 32, use rasterop if val == maxval (white); ~3x faster. */
684  if (d < 32 && val == ((1 << d) - 1)) {
685  PIX *pixmd = pixUnpackBinary(pixm, d, 0);
686  pixRasterop(pixd, x, y, wm, hm, PIX_PAINT, pixmd, 0, 0);
687  pixDestroy(&pixmd);
688  return 0;
689  }
690 
691  /* All other cases */
692  pixGetDimensions(pixd, &w, &h, NULL);
693  wpl = pixGetWpl(pixd);
694  data = pixGetData(pixd);
695  wplm = pixGetWpl(pixm);
696  datam = pixGetData(pixm);
697  for (i = 0; i < hm; i++) {
698  if (y + i < 0 || y + i >= h) continue;
699  line = data + (y + i) * wpl;
700  linem = datam + i * wplm;
701  for (j = 0; j < wm; j++) {
702  if (x + j < 0 || x + j >= w) continue;
703  if (GET_DATA_BIT(linem, j)) {
704  switch (d)
705  {
706  case 2:
707  SET_DATA_DIBIT(line, x + j, val);
708  break;
709  case 4:
710  SET_DATA_QBIT(line, x + j, val);
711  break;
712  case 8:
713  SET_DATA_BYTE(line, x + j, val);
714  break;
715  case 16:
716  SET_DATA_TWO_BYTES(line, x + j, val);
717  break;
718  case 32:
719  *(line + x + j) = val;
720  break;
721  default:
722  return ERROR_INT("shouldn't get here", procName, 1);
723  }
724  }
725  }
726  }
727 
728  return 0;
729 }
730 
731 
758 PIX *
760  BOXA *boxa,
761  l_int32 background)
762 {
763 l_int32 i, n, x, y, w, h;
764 PIX *pixd;
765 
766  PROCNAME("pixCopyWithBoxa");
767 
768  if (!pixs)
769  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
770  if (!boxa)
771  return (PIX *)ERROR_PTR("boxa not defined", procName, NULL);
772  if (background != L_SET_WHITE && background != L_SET_BLACK)
773  return (PIX *)ERROR_PTR("invalid background", procName, NULL);
774 
775  pixd = pixCreateTemplate(pixs);
776  pixSetBlackOrWhite(pixd, background);
777  n = boxaGetCount(boxa);
778  for (i = 0; i < n; i++) {
779  boxaGetBoxGeometry(boxa, i, &x, &y, &w, &h);
780  pixRasterop(pixd, x, y, w, h, PIX_SRC, pixs, x, y);
781  }
782  return pixd;
783 }
784 
785 
847 l_ok
849  PIX *pixm,
850  l_int32 x,
851  l_int32 y,
852  l_int32 searchdir,
853  l_int32 mindist,
854  l_int32 tilesize,
855  l_int32 ntiles,
856  l_int32 distblend)
857 {
858 l_int32 w, h, d, wm, hm, dm, i, n, bx, by, bw, bh, edgeblend, retval, minside;
859 l_uint32 pixval;
860 BOX *box, *boxv, *boxh;
861 BOXA *boxa;
862 PIX *pixf, *pixv, *pixh, *pix1, *pix2, *pix3, *pix4, *pix5;
863 PIXA *pixa;
864 
865  PROCNAME("pixPaintSelfThroughMask");
866 
867  if (!pixm) /* nothing to do */
868  return 0;
869  if (!pixd)
870  return ERROR_INT("pixd not defined", procName, 1);
871  if (pixGetColormap(pixd) != NULL)
872  return ERROR_INT("pixd has colormap", procName, 1);
873  pixGetDimensions(pixd, &w, &h, &d);
874  if (d != 8 && d != 32)
875  return ERROR_INT("pixd not 8 or 32 bpp", procName, 1);
876  pixGetDimensions(pixm, &wm, &hm, &dm);
877  if (dm != 1)
878  return ERROR_INT("pixm not 1 bpp", procName, 1);
879  if (x < 0 || y < 0)
880  return ERROR_INT("x and y must be non-negative", procName, 1);
881  if (searchdir != L_HORIZ && searchdir != L_VERT &&
882  searchdir != L_BOTH_DIRECTIONS)
883  return ERROR_INT("invalid searchdir", procName, 1);
884  if (tilesize < 2)
885  return ERROR_INT("tilesize must be >= 2", procName, 1);
886  if (distblend < 0)
887  return ERROR_INT("distblend must be >= 0", procName, 1);
888 
889  /* Embed mask in full sized mask */
890  if (wm < w || hm < h) {
891  pixf = pixCreate(w, h, 1);
892  pixRasterop(pixf, x, y, wm, hm, PIX_SRC, pixm, 0, 0);
893  } else {
894  pixf = pixCopy(NULL, pixm);
895  }
896 
897  /* Get connected components of mask */
898  boxa = pixConnComp(pixf, &pixa, 8);
899  if ((n = pixaGetCount(pixa)) == 0) {
900  L_WARNING("no fg in mask\n", procName);
901  pixDestroy(&pixf);
902  pixaDestroy(&pixa);
903  boxaDestroy(&boxa);
904  return 1;
905  }
906  boxaDestroy(&boxa);
907 
908  /* For each c.c., generate one or two representative tiles for
909  * texturizing and apply through the mask. The input 'tilesize'
910  * is the requested value. Note that if there is exactly one
911  * component, and blending at the edge is requested, an alpha mask
912  * is generated, which is larger than the bounding box of the c.c. */
913  edgeblend = (n == 1 && distblend > 0) ? 1 : 0;
914  if (distblend > 0 && n > 1)
915  L_WARNING("%d components; can not blend at edges\n", procName, n);
916  retval = 0;
917  for (i = 0; i < n; i++) {
918  if (edgeblend) {
919  pix1 = pixMakeAlphaFromMask(pixf, distblend, &box);
920  } else {
921  pix1 = pixaGetPix(pixa, i, L_CLONE);
922  box = pixaGetBox(pixa, i, L_CLONE);
923  }
924  boxGetGeometry(box, &bx, &by, &bw, &bh);
925  minside = L_MIN(bw, bh);
926 
927  boxh = boxv = NULL;
928  if (searchdir == L_HORIZ || searchdir == L_BOTH_DIRECTIONS) {
929  pixFindRepCloseTile(pixd, box, L_HORIZ, mindist,
930  L_MIN(minside, tilesize), ntiles, &boxh, 0);
931  }
932  if (searchdir == L_VERT || searchdir == L_BOTH_DIRECTIONS) {
933  pixFindRepCloseTile(pixd, box, L_VERT, mindist,
934  L_MIN(minside, tilesize), ntiles, &boxv, 0);
935  }
936  if (!boxh && !boxv) {
937  L_WARNING("tile region not selected; paint color near boundary\n",
938  procName);
939  pixDestroy(&pix1);
940  pix1 = pixaGetPix(pixa, i, L_CLONE);
941  pixaGetBoxGeometry(pixa, i, &bx, &by, NULL, NULL);
942  retval = pixGetColorNearMaskBoundary(pixd, pixm, box, distblend,
943  &pixval, 0);
944  pixSetMaskedGeneral(pixd, pix1, pixval, bx, by);
945  pixDestroy(&pix1);
946  boxDestroy(&box);
947  continue;
948  }
949 
950  /* Extract the selected squares from pixd */
951  pixh = (boxh) ? pixClipRectangle(pixd, boxh, NULL) : NULL;
952  pixv = (boxv) ? pixClipRectangle(pixd, boxv, NULL) : NULL;
953  if (pixh && pixv)
954  pix2 = pixBlend(pixh, pixv, 0, 0, 0.5);
955  else if (pixh)
956  pix2 = pixClone(pixh);
957  else /* pixv */
958  pix2 = pixClone(pixv);
959  pixDestroy(&pixh);
960  pixDestroy(&pixv);
961  boxDestroy(&boxh);
962  boxDestroy(&boxv);
963 
964  /* Generate an image the size of the b.b. of the c.c.,
965  * possibly extended by the blending distance, which
966  * is then either painted through the c.c. mask or
967  * blended using the alpha mask for that c.c. */
968  pix3 = pixMirroredTiling(pix2, bw, bh);
969  if (edgeblend) {
970  pix4 = pixClipRectangle(pixd, box, NULL);
971  pix5 = pixBlendWithGrayMask(pix4, pix3, pix1, 0, 0);
972  pixRasterop(pixd, bx, by, bw, bh, PIX_SRC, pix5, 0, 0);
973  pixDestroy(&pix4);
974  pixDestroy(&pix5);
975  } else {
976  pixCombineMaskedGeneral(pixd, pix3, pix1, bx, by);
977  }
978  pixDestroy(&pix1);
979  pixDestroy(&pix2);
980  pixDestroy(&pix3);
981  boxDestroy(&box);
982  }
983 
984  pixaDestroy(&pixa);
985  pixDestroy(&pixf);
986  return retval;
987 }
988 
989 
1004 PIX *
1006  l_int32 val)
1007 {
1008 l_int32 w, h, d, i, j, sval, wpls, wpld;
1009 l_uint32 *datas, *datad, *lines, *lined;
1010 PIX *pixd;
1011 
1012  PROCNAME("pixMakeMaskFromVal");
1013 
1014  if (!pixs)
1015  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1016  pixGetDimensions(pixs, &w, &h, &d);
1017  if (d != 2 && d != 4 && d != 8)
1018  return (PIX *)ERROR_PTR("pix not 2, 4 or 8 bpp", procName, NULL);
1019 
1020  pixd = pixCreate(w, h, 1);
1021  pixCopyResolution(pixd, pixs);
1022  pixCopyInputFormat(pixd, pixs);
1023  datas = pixGetData(pixs);
1024  datad = pixGetData(pixd);
1025  wpls = pixGetWpl(pixs);
1026  wpld = pixGetWpl(pixd);
1027  for (i = 0; i < h; i++) {
1028  lines = datas + i * wpls;
1029  lined = datad + i * wpld;
1030  for (j = 0; j < w; j++) {
1031  if (d == 2)
1032  sval = GET_DATA_DIBIT(lines, j);
1033  else if (d == 4)
1034  sval = GET_DATA_QBIT(lines, j);
1035  else /* d == 8 */
1036  sval = GET_DATA_BYTE(lines, j);
1037  if (sval == val)
1038  SET_DATA_BIT(lined, j);
1039  }
1040  }
1041 
1042  return pixd;
1043 }
1044 
1045 
1061 PIX *
1063  l_int32 *tab)
1064 {
1065 l_int32 w, h, d, i, j, val, wpls, wpld;
1066 l_uint32 *datas, *datad, *lines, *lined;
1067 PIX *pixd;
1068 
1069  PROCNAME("pixMakeMaskFromLUT");
1070 
1071  if (!pixs)
1072  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1073  if (!tab)
1074  return (PIX *)ERROR_PTR("tab not defined", procName, NULL);
1075  pixGetDimensions(pixs, &w, &h, &d);
1076  if (d != 2 && d != 4 && d != 8)
1077  return (PIX *)ERROR_PTR("pix not 2, 4 or 8 bpp", procName, NULL);
1078 
1079  pixd = pixCreate(w, h, 1);
1080  pixCopyResolution(pixd, pixs);
1081  pixCopyInputFormat(pixd, pixs);
1082  datas = pixGetData(pixs);
1083  datad = pixGetData(pixd);
1084  wpls = pixGetWpl(pixs);
1085  wpld = pixGetWpl(pixd);
1086  for (i = 0; i < h; i++) {
1087  lines = datas + i * wpls;
1088  lined = datad + i * wpld;
1089  for (j = 0; j < w; j++) {
1090  if (d == 2)
1091  val = GET_DATA_DIBIT(lines, j);
1092  else if (d == 4)
1093  val = GET_DATA_QBIT(lines, j);
1094  else /* d == 8 */
1095  val = GET_DATA_BYTE(lines, j);
1096  if (tab[val] == 1)
1097  SET_DATA_BIT(lined, j);
1098  }
1099  }
1100 
1101  return pixd;
1102 }
1103 
1104 
1130 PIX *
1132  l_float32 rc,
1133  l_float32 gc,
1134  l_float32 bc,
1135  l_float32 thresh)
1136 {
1137 PIX *pix1, *pix2;
1138 
1139  PROCNAME("pixMakeArbMaskFromRGB");
1140 
1141  if (!pixs || pixGetDepth(pixs) != 32)
1142  return (PIX *)ERROR_PTR("pixs undefined or not 32 bpp", procName, NULL);
1143  if (thresh >= 255.0) thresh = 254.0; /* avoid 8 bit overflow */
1144 
1145  if ((pix1 = pixConvertRGBToGrayArb(pixs, rc, gc, bc)) == NULL)
1146  return (PIX *)ERROR_PTR("pix1 not made", procName, NULL);
1147  pix2 = pixThresholdToBinary(pix1, thresh + 1);
1148  pixInvert(pix2, pix2);
1149  pixDestroy(&pix1);
1150  return pix2;
1151 }
1152 
1153 
1207 PIX *
1209  l_uint32 val,
1210  l_int32 debug)
1211 {
1212 PIX *pixg, *pixm, *pixt, *pixd;
1213 
1214  PROCNAME("pixSetUnderTransparency");
1215 
1216  if (!pixs || pixGetDepth(pixs) != 32)
1217  return (PIX *)ERROR_PTR("pixs not defined or not 32 bpp",
1218  procName, NULL);
1219 
1220  if (pixGetSpp(pixs) != 4) {
1221  L_WARNING("no alpha channel; returning a copy\n", procName);
1222  return pixCopy(NULL, pixs);
1223  }
1224 
1225  /* Make a mask from the alpha component with ON pixels
1226  * wherever the alpha component is fully transparent (0).
1227  * The hard way:
1228  * l_int32 *lut = (l_int32 *)LEPT_CALLOC(256, sizeof(l_int32));
1229  * lut[0] = 1;
1230  * pixg = pixGetRGBComponent(pixs, L_ALPHA_CHANNEL);
1231  * pixm = pixMakeMaskFromLUT(pixg, lut);
1232  * LEPT_FREE(lut);
1233  * But there's an easier way to set pixels in a mask where
1234  * the alpha component is 0 ... */
1235  pixg = pixGetRGBComponent(pixs, L_ALPHA_CHANNEL);
1236  pixm = pixThresholdToBinary(pixg, 1);
1237 
1238  if (debug) {
1239  pixt = pixDisplayLayersRGBA(pixs, 0xffffff00, 600);
1240  pixDisplay(pixt, 0, 0);
1241  pixDestroy(&pixt);
1242  }
1243 
1244  pixd = pixCopy(NULL, pixs);
1245  pixSetMasked(pixd, pixm, (val & 0xffffff00));
1246  pixDestroy(&pixg);
1247  pixDestroy(&pixm);
1248  return pixd;
1249 }
1250 
1251 
1283 PIX *
1285  l_int32 dist,
1286  BOX **pbox)
1287 {
1288 l_int32 w, h;
1289 BOX *box1, *box2;
1290 PIX *pix1, *pixd;
1291 
1292  PROCNAME("pixMakeAlphaFromMask");
1293 
1294  if (pbox) *pbox = NULL;
1295  if (!pixs || pixGetDepth(pixs) != 1)
1296  return (PIX *)ERROR_PTR("pixs undefined or not 1 bpp", procName, NULL);
1297  if (dist < 0)
1298  return (PIX *)ERROR_PTR("dist must be >= 0", procName, NULL);
1299 
1300  /* If requested, extract just the region to be affected by the mask */
1301  if (pbox) {
1302  pixClipToForeground(pixs, NULL, &box1);
1303  if (!box1) {
1304  L_WARNING("no ON pixels in mask\n", procName);
1305  return pixCreateTemplate(pixs); /* all background (0) */
1306  }
1307 
1308  boxAdjustSides(box1, box1, -dist, dist, -dist, dist);
1309  pixGetDimensions(pixs, &w, &h, NULL);
1310  box2 = boxClipToRectangle(box1, w, h);
1311  *pbox = box2;
1312  pix1 = pixClipRectangle(pixs, box2, NULL);
1313  boxDestroy(&box1);
1314  } else {
1315  pix1 = pixCopy(NULL, pixs);
1316  }
1317 
1318  if (dist == 0) {
1319  pixd = pixConvert1To8(NULL, pix1, 0, 255);
1320  pixDestroy(&pix1);
1321  return pixd;
1322  }
1323 
1324  /* Blur the boundary of the input mask */
1325  pixInvert(pix1, pix1);
1326  pixd = pixDistanceFunction(pix1, 8, 8, L_BOUNDARY_FG);
1327  pixMultConstantGray(pixd, 256.0 / dist);
1328  pixInvert(pixd, pixd);
1329  pixDestroy(&pix1);
1330  return pixd;
1331 }
1332 
1333 
1352 l_ok
1354  PIX *pixm,
1355  BOX *box,
1356  l_int32 dist,
1357  l_uint32 *pval,
1358  l_int32 debug)
1359 {
1360 char op[64];
1361 l_int32 empty, bx, by;
1362 l_float32 rval, gval, bval;
1363 BOX *box1, *box2;
1364 PIX *pix1, *pix2, *pix3;
1365 
1366  PROCNAME("pixGetColorNearMaskBoundary");
1367 
1368  if (!pval)
1369  return ERROR_INT("&pval not defined", procName, 1);
1370  *pval = 0xffffff00; /* white */
1371  if (!pixs || pixGetDepth(pixs) != 32)
1372  return ERROR_INT("pixs undefined or not 32 bpp", procName, 1);
1373  if (!pixm || pixGetDepth(pixm) != 1)
1374  return ERROR_INT("pixm undefined or not 1 bpp", procName, 1);
1375  if (!box)
1376  return ERROR_INT("box not defined", procName, 1);
1377  if (dist < 0)
1378  return ERROR_INT("dist must be >= 0", procName, 1);
1379 
1380  /* Clip mask piece, expanded beyond %box by (%dist + 5) on each side.
1381  * box1 is the region requested; box2 is the actual region retrieved,
1382  * which is clipped to %pixm */
1383  box1 = boxAdjustSides(NULL, box, -dist - 5, dist + 5, -dist - 5, dist + 5);
1384  pix1 = pixClipRectangle(pixm, box1, &box2);
1385 
1386  /* Expand FG by %dist into the BG */
1387  if (dist == 0) {
1388  pix2 = pixCopy(NULL, pix1);
1389  } else {
1390  snprintf(op, sizeof(op), "d%d.%d", 2 * dist, 2 * dist);
1391  pix2 = pixMorphSequence(pix1, op, 0);
1392  }
1393 
1394  /* Expand again by 5 pixels on all sides (dilate 11x11) and XOR,
1395  * getting the annulus of FG pixels between %dist and %dist + 5 */
1396  pix3 = pixCopy(NULL, pix2);
1397  pixDilateBrick(pix3, pix3, 11, 11);
1398  pixXor(pix3, pix3, pix2);
1399  pixZero(pix3, &empty);
1400  if (!empty) {
1401  /* Scan the same region in %pixs, to get average under FG in pix3 */
1402  boxGetGeometry(box2, &bx, &by, NULL, NULL);
1403  pixGetAverageMaskedRGB(pixs, pix3, bx, by, 1, L_MEAN_ABSVAL,
1404  &rval, &gval, &bval);
1405  composeRGBPixel((l_int32)(rval + 0.5), (l_int32)(gval + 0.5),
1406  (l_int32)(bval + 0.5), pval);
1407  } else {
1408  L_WARNING("no pixels found\n", procName);
1409  }
1410 
1411  if (debug) {
1412  lept_rmdir("masknear"); /* erase previous images */
1413  lept_mkdir("masknear");
1414  pixWriteDebug("/tmp/masknear/input.png", pix1, IFF_PNG);
1415  pixWriteDebug("/tmp/masknear/adjusted.png", pix2, IFF_PNG);
1416  pixWriteDebug("/tmp/masknear/outerfive.png", pix3, IFF_PNG);
1417  lept_stderr("Input box; with adjusted sides; clipped\n");
1418  boxPrintStreamInfo(stderr, box);
1419  boxPrintStreamInfo(stderr, box1);
1420  boxPrintStreamInfo(stderr, box2);
1421  }
1422 
1423  pixDestroy(&pix1);
1424  pixDestroy(&pix2);
1425  pixDestroy(&pix3);
1426  boxDestroy(&box1);
1427  boxDestroy(&box2);
1428  return 0;
1429 }
1430 
1431 
1452 PIX *
1454  PIX *pixm,
1455  SEL *sel,
1456  l_uint32 val)
1457 {
1458 l_int32 w, h;
1459 PIX *pix1, *pix2;
1460 
1461  PROCNAME("pixDisplaySelectedPixels");
1462 
1463  if (!pixm || pixGetDepth(pixm) != 1)
1464  return (PIX *)ERROR_PTR("pixm undefined or not 1 bpp", procName, NULL);
1465 
1466  if (pixs) {
1467  pix1 = pixConvertTo32(pixs);
1468  } else {
1469  pixGetDimensions(pixm, &w, &h, NULL);
1470  pix1 = pixCreate(w, h, 32);
1471  pixSetAll(pix1);
1472  }
1473 
1474  if (sel)
1475  pix2 = pixDilate(NULL, pixm, sel);
1476  else
1477  pix2 = pixClone(pixm);
1478  pixSetMasked(pix1, pix2, val);
1479  pixDestroy(&pix2);
1480  return pix1;
1481 }
1482 
1483 
1484 /*-------------------------------------------------------------*
1485  * One and two-image boolean ops on arbitrary depth images *
1486  *-------------------------------------------------------------*/
1508 PIX *
1510  PIX *pixs)
1511 {
1512  PROCNAME("pixInvert");
1513 
1514  if (!pixs)
1515  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1516 
1517  /* Prepare pixd for in-place operation */
1518  if ((pixd = pixCopy(pixd, pixs)) == NULL)
1519  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
1520 
1521  pixRasterop(pixd, 0, 0, pixGetWidth(pixd), pixGetHeight(pixd),
1522  PIX_NOT(PIX_DST), NULL, 0, 0); /* invert pixd */
1523 
1524  return pixd;
1525 }
1526 
1527 
1559 PIX *
1560 pixOr(PIX *pixd,
1561  PIX *pixs1,
1562  PIX *pixs2)
1563 {
1564  PROCNAME("pixOr");
1565 
1566  if (!pixs1)
1567  return (PIX *)ERROR_PTR("pixs1 not defined", procName, pixd);
1568  if (!pixs2)
1569  return (PIX *)ERROR_PTR("pixs2 not defined", procName, pixd);
1570  if (pixd == pixs2)
1571  return (PIX *)ERROR_PTR("cannot have pixs2 == pixd", procName, pixd);
1572  if (pixGetDepth(pixs1) != pixGetDepth(pixs2))
1573  return (PIX *)ERROR_PTR("depths of pixs* unequal", procName, pixd);
1574 
1575 #if EQUAL_SIZE_WARNING
1576  if (!pixSizesEqual(pixs1, pixs2))
1577  L_WARNING("pixs1 and pixs2 not equal sizes\n", procName);
1578 #endif /* EQUAL_SIZE_WARNING */
1579 
1580  /* Prepare pixd to be a copy of pixs1 */
1581  if ((pixd = pixCopy(pixd, pixs1)) == NULL)
1582  return (PIX *)ERROR_PTR("pixd not made", procName, pixd);
1583 
1584  /* src1 | src2 --> dest */
1585  pixRasterop(pixd, 0, 0, pixGetWidth(pixd), pixGetHeight(pixd),
1586  PIX_SRC | PIX_DST, pixs2, 0, 0);
1587 
1588  return pixd;
1589 }
1590 
1591 
1623 PIX *
1624 pixAnd(PIX *pixd,
1625  PIX *pixs1,
1626  PIX *pixs2)
1627 {
1628  PROCNAME("pixAnd");
1629 
1630  if (!pixs1)
1631  return (PIX *)ERROR_PTR("pixs1 not defined", procName, pixd);
1632  if (!pixs2)
1633  return (PIX *)ERROR_PTR("pixs2 not defined", procName, pixd);
1634  if (pixd == pixs2)
1635  return (PIX *)ERROR_PTR("cannot have pixs2 == pixd", procName, pixd);
1636  if (pixGetDepth(pixs1) != pixGetDepth(pixs2))
1637  return (PIX *)ERROR_PTR("depths of pixs* unequal", procName, pixd);
1638 
1639 #if EQUAL_SIZE_WARNING
1640  if (!pixSizesEqual(pixs1, pixs2))
1641  L_WARNING("pixs1 and pixs2 not equal sizes\n", procName);
1642 #endif /* EQUAL_SIZE_WARNING */
1643 
1644  /* Prepare pixd to be a copy of pixs1 */
1645  if ((pixd = pixCopy(pixd, pixs1)) == NULL)
1646  return (PIX *)ERROR_PTR("pixd not made", procName, pixd);
1647 
1648  /* src1 & src2 --> dest */
1649  pixRasterop(pixd, 0, 0, pixGetWidth(pixd), pixGetHeight(pixd),
1650  PIX_SRC & PIX_DST, pixs2, 0, 0);
1651 
1652  return pixd;
1653 }
1654 
1655 
1687 PIX *
1688 pixXor(PIX *pixd,
1689  PIX *pixs1,
1690  PIX *pixs2)
1691 {
1692  PROCNAME("pixXor");
1693 
1694  if (!pixs1)
1695  return (PIX *)ERROR_PTR("pixs1 not defined", procName, pixd);
1696  if (!pixs2)
1697  return (PIX *)ERROR_PTR("pixs2 not defined", procName, pixd);
1698  if (pixd == pixs2)
1699  return (PIX *)ERROR_PTR("cannot have pixs2 == pixd", procName, pixd);
1700  if (pixGetDepth(pixs1) != pixGetDepth(pixs2))
1701  return (PIX *)ERROR_PTR("depths of pixs* unequal", procName, pixd);
1702 
1703 #if EQUAL_SIZE_WARNING
1704  if (!pixSizesEqual(pixs1, pixs2))
1705  L_WARNING("pixs1 and pixs2 not equal sizes\n", procName);
1706 #endif /* EQUAL_SIZE_WARNING */
1707 
1708  /* Prepare pixd to be a copy of pixs1 */
1709  if ((pixd = pixCopy(pixd, pixs1)) == NULL)
1710  return (PIX *)ERROR_PTR("pixd not made", procName, pixd);
1711 
1712  /* src1 ^ src2 --> dest */
1713  pixRasterop(pixd, 0, 0, pixGetWidth(pixd), pixGetHeight(pixd),
1714  PIX_SRC ^ PIX_DST, pixs2, 0, 0);
1715 
1716  return pixd;
1717 }
1718 
1719 
1752 PIX *
1754  PIX *pixs1,
1755  PIX *pixs2)
1756 {
1757 l_int32 w, h;
1758 
1759  PROCNAME("pixSubtract");
1760 
1761  if (!pixs1)
1762  return (PIX *)ERROR_PTR("pixs1 not defined", procName, pixd);
1763  if (!pixs2)
1764  return (PIX *)ERROR_PTR("pixs2 not defined", procName, pixd);
1765  if (pixGetDepth(pixs1) != pixGetDepth(pixs2))
1766  return (PIX *)ERROR_PTR("depths of pixs* unequal", procName, pixd);
1767 
1768 #if EQUAL_SIZE_WARNING
1769  if (!pixSizesEqual(pixs1, pixs2))
1770  L_WARNING("pixs1 and pixs2 not equal sizes\n", procName);
1771 #endif /* EQUAL_SIZE_WARNING */
1772 
1773  pixGetDimensions(pixs1, &w, &h, NULL);
1774  if (!pixd) {
1775  pixd = pixCopy(NULL, pixs1);
1776  pixRasterop(pixd, 0, 0, w, h, PIX_DST & PIX_NOT(PIX_SRC),
1777  pixs2, 0, 0); /* src1 & (~src2) */
1778  } else if (pixd == pixs1) {
1779  pixRasterop(pixd, 0, 0, w, h, PIX_DST & PIX_NOT(PIX_SRC),
1780  pixs2, 0, 0); /* src1 & (~src2) */
1781  } else if (pixd == pixs2) {
1782  pixRasterop(pixd, 0, 0, w, h, PIX_NOT(PIX_DST) & PIX_SRC,
1783  pixs1, 0, 0); /* src1 & (~src2) */
1784  } else { /* pixd != pixs1 && pixd != pixs2 */
1785  pixCopy(pixd, pixs1); /* sizes pixd to pixs1 if unequal */
1786  pixRasterop(pixd, 0, 0, w, h, PIX_DST & PIX_NOT(PIX_SRC),
1787  pixs2, 0, 0); /* src1 & (~src2) */
1788  }
1789 
1790  return pixd;
1791 }
1792 
1793 
1794 /*-------------------------------------------------------------*
1795  * Pixel counting *
1796  *-------------------------------------------------------------*/
1814 l_ok
1816  l_int32 *pempty)
1817 {
1818 l_int32 w, h, wpl, i, j, fullwords, endbits;
1819 l_uint32 endmask;
1820 l_uint32 *data, *line;
1821 
1822  PROCNAME("pixZero");
1823 
1824  if (!pempty)
1825  return ERROR_INT("&empty not defined", procName, 1);
1826  *pempty = 1;
1827  if (!pix)
1828  return ERROR_INT("pix not defined", procName, 1);
1829 
1830  w = pixGetWidth(pix) * pixGetDepth(pix); /* in bits */
1831  h = pixGetHeight(pix);
1832  wpl = pixGetWpl(pix);
1833  data = pixGetData(pix);
1834  fullwords = w / 32;
1835  endbits = w & 31;
1836  endmask = (endbits == 0) ? 0 : (0xffffffffU << (32 - endbits));
1837 
1838  for (i = 0; i < h; i++) {
1839  line = data + wpl * i;
1840  for (j = 0; j < fullwords; j++)
1841  if (*line++) {
1842  *pempty = 0;
1843  return 0;
1844  }
1845  if (endbits) {
1846  if (*line & endmask) {
1847  *pempty = 0;
1848  return 0;
1849  }
1850  }
1851  }
1852 
1853  return 0;
1854 }
1855 
1856 
1864 l_ok
1866  l_float32 *pfract)
1867 {
1868 l_int32 w, h, count;
1869 
1870  PROCNAME("pixForegroundFraction");
1871 
1872  if (!pfract)
1873  return ERROR_INT("&fract not defined", procName, 1);
1874  *pfract = 0.0;
1875  if (!pix || pixGetDepth(pix) != 1)
1876  return ERROR_INT("pix not defined or not 1 bpp", procName, 1);
1877 
1878  pixCountPixels(pix, &count, NULL);
1879  pixGetDimensions(pix, &w, &h, NULL);
1880  *pfract = (l_float32)count / (l_float32)(w * h);
1881  return 0;
1882 }
1883 
1884 
1891 NUMA *
1893 {
1894 l_int32 d, i, n, count;
1895 l_int32 *tab;
1896 NUMA *na;
1897 PIX *pix;
1898 
1899  PROCNAME("pixaCountPixels");
1900 
1901  if (!pixa)
1902  return (NUMA *)ERROR_PTR("pix not defined", procName, NULL);
1903 
1904  if ((n = pixaGetCount(pixa)) == 0)
1905  return numaCreate(1);
1906 
1907  pix = pixaGetPix(pixa, 0, L_CLONE);
1908  d = pixGetDepth(pix);
1909  pixDestroy(&pix);
1910  if (d != 1)
1911  return (NUMA *)ERROR_PTR("pixa not 1 bpp", procName, NULL);
1912 
1913  if ((na = numaCreate(n)) == NULL)
1914  return (NUMA *)ERROR_PTR("na not made", procName, NULL);
1915  tab = makePixelSumTab8();
1916  for (i = 0; i < n; i++) {
1917  pix = pixaGetPix(pixa, i, L_CLONE);
1918  pixCountPixels(pix, &count, tab);
1919  numaAddNumber(na, count);
1920  pixDestroy(&pix);
1921  }
1922 
1923  LEPT_FREE(tab);
1924  return na;
1925 }
1926 
1927 
1936 l_ok
1938  l_int32 *pcount,
1939  l_int32 *tab8)
1940 {
1941 l_uint32 endmask;
1942 l_int32 w, h, wpl, i, j;
1943 l_int32 fullwords, endbits, sum;
1944 l_int32 *tab;
1945 l_uint32 *data;
1946 
1947  PROCNAME("pixCountPixels");
1948 
1949  if (!pcount)
1950  return ERROR_INT("&count not defined", procName, 1);
1951  *pcount = 0;
1952  if (!pixs || pixGetDepth(pixs) != 1)
1953  return ERROR_INT("pixs not defined or not 1 bpp", procName, 1);
1954 
1955  tab = (tab8) ? tab8 : makePixelSumTab8();
1956  pixGetDimensions(pixs, &w, &h, NULL);
1957  wpl = pixGetWpl(pixs);
1958  data = pixGetData(pixs);
1959  fullwords = w >> 5;
1960  endbits = w & 31;
1961  endmask = (endbits == 0) ? 0 : (0xffffffffU << (32 - endbits));
1962 
1963  sum = 0;
1964  for (i = 0; i < h; i++, data += wpl) {
1965  for (j = 0; j < fullwords; j++) {
1966  l_uint32 word = data[j];
1967  if (word) {
1968  sum += tab[word & 0xff] +
1969  tab[(word >> 8) & 0xff] +
1970  tab[(word >> 16) & 0xff] +
1971  tab[(word >> 24) & 0xff];
1972  }
1973  }
1974  if (endbits) {
1975  l_uint32 word = data[j] & endmask;
1976  if (word) {
1977  sum += tab[word & 0xff] +
1978  tab[(word >> 8) & 0xff] +
1979  tab[(word >> 16) & 0xff] +
1980  tab[(word >> 24) & 0xff];
1981  }
1982  }
1983  }
1984  *pcount = sum;
1985 
1986  if (!tab8) LEPT_FREE(tab);
1987  return 0;
1988 }
1989 
1990 
2000 l_ok
2002  BOX *box,
2003  l_int32 *pcount,
2004  l_int32 *tab8)
2005 {
2006 l_int32 bx, by, bw, bh;
2007 PIX *pix1;
2008 
2009  PROCNAME("pixCountPixelsInRect");
2010 
2011  if (!pcount)
2012  return ERROR_INT("&count not defined", procName, 1);
2013  *pcount = 0;
2014  if (!pixs || pixGetDepth(pixs) != 1)
2015  return ERROR_INT("pixs not defined or not 1 bpp", procName, 1);
2016 
2017  if (box) {
2018  boxGetGeometry(box, &bx, &by, &bw, &bh);
2019  pix1 = pixCreate(bw, bh, 1);
2020  pixRasterop(pix1, 0, 0, bw, bh, PIX_SRC, pixs, bx, by);
2021  pixCountPixels(pix1, pcount, tab8);
2022  pixDestroy(&pix1);
2023  } else {
2024  pixCountPixels(pixs, pcount, tab8);
2025  }
2026 
2027  return 0;
2028 }
2029 
2030 
2044 NUMA *
2046  BOX *box)
2047 {
2048 l_int32 i, j, w, h, wpl, count, xstart, xend, ystart, yend, bw, bh;
2049 l_uint32 *line, *data;
2050 NUMA *na;
2051 
2052  PROCNAME("pixCountByRow");
2053 
2054  if (!pix || pixGetDepth(pix) != 1)
2055  return (NUMA *)ERROR_PTR("pix undefined or not 1 bpp", procName, NULL);
2056  if (!box)
2057  return pixCountPixelsByRow(pix, NULL);
2058 
2059  pixGetDimensions(pix, &w, &h, NULL);
2060  if (boxClipToRectangleParams(box, w, h, &xstart, &ystart, &xend, &yend,
2061  &bw, &bh) == 1)
2062  return (NUMA *)ERROR_PTR("invalid clipping box", procName, NULL);
2063 
2064  if ((na = numaCreate(bh)) == NULL)
2065  return (NUMA *)ERROR_PTR("na not made", procName, NULL);
2066  numaSetParameters(na, ystart, 1);
2067  data = pixGetData(pix);
2068  wpl = pixGetWpl(pix);
2069  for (i = ystart; i < yend; i++) {
2070  count = 0;
2071  line = data + i * wpl;
2072  for (j = xstart; j < xend; j++) {
2073  if (GET_DATA_BIT(line, j))
2074  count++;
2075  }
2076  numaAddNumber(na, count);
2077  }
2078 
2079  return na;
2080 }
2081 
2082 
2096 NUMA *
2098  BOX *box)
2099 {
2100 l_int32 i, j, w, h, wpl, count, xstart, xend, ystart, yend, bw, bh;
2101 l_uint32 *line, *data;
2102 NUMA *na;
2103 
2104  PROCNAME("pixCountByColumn");
2105 
2106  if (!pix || pixGetDepth(pix) != 1)
2107  return (NUMA *)ERROR_PTR("pix undefined or not 1 bpp", procName, NULL);
2108  if (!box)
2109  return pixCountPixelsByColumn(pix);
2110 
2111  pixGetDimensions(pix, &w, &h, NULL);
2112  if (boxClipToRectangleParams(box, w, h, &xstart, &ystart, &xend, &yend,
2113  &bw, &bh) == 1)
2114  return (NUMA *)ERROR_PTR("invalid clipping box", procName, NULL);
2115 
2116  if ((na = numaCreate(bw)) == NULL)
2117  return (NUMA *)ERROR_PTR("na not made", procName, NULL);
2118  numaSetParameters(na, xstart, 1);
2119  data = pixGetData(pix);
2120  wpl = pixGetWpl(pix);
2121  for (j = xstart; j < xend; j++) {
2122  count = 0;
2123  for (i = ystart; i < yend; i++) {
2124  line = data + i * wpl;
2125  if (GET_DATA_BIT(line, j))
2126  count++;
2127  }
2128  numaAddNumber(na, count);
2129  }
2130 
2131  return na;
2132 }
2133 
2134 
2142 NUMA *
2144  l_int32 *tab8)
2145 {
2146 l_int32 h, i, count;
2147 l_int32 *tab;
2148 NUMA *na;
2149 
2150  PROCNAME("pixCountPixelsByRow");
2151 
2152  if (!pix || pixGetDepth(pix) != 1)
2153  return (NUMA *)ERROR_PTR("pix undefined or not 1 bpp", procName, NULL);
2154 
2155  h = pixGetHeight(pix);
2156  if ((na = numaCreate(h)) == NULL)
2157  return (NUMA *)ERROR_PTR("na not made", procName, NULL);
2158 
2159  tab = (tab8) ? tab8 : makePixelSumTab8();
2160  for (i = 0; i < h; i++) {
2161  pixCountPixelsInRow(pix, i, &count, tab);
2162  numaAddNumber(na, count);
2163  }
2164 
2165  if (!tab8) LEPT_FREE(tab);
2166  return na;
2167 }
2168 
2169 
2176 NUMA *
2178 {
2179 l_int32 i, j, w, h, wpl;
2180 l_uint32 *line, *data;
2181 l_float32 *array;
2182 NUMA *na;
2183 
2184  PROCNAME("pixCountPixelsByColumn");
2185 
2186  if (!pix || pixGetDepth(pix) != 1)
2187  return (NUMA *)ERROR_PTR("pix undefined or not 1 bpp", procName, NULL);
2188 
2189  pixGetDimensions(pix, &w, &h, NULL);
2190  if ((na = numaCreate(w)) == NULL)
2191  return (NUMA *)ERROR_PTR("na not made", procName, NULL);
2192  numaSetCount(na, w);
2193  array = numaGetFArray(na, L_NOCOPY);
2194  data = pixGetData(pix);
2195  wpl = pixGetWpl(pix);
2196  for (i = 0; i < h; i++) {
2197  line = data + wpl * i;
2198  for (j = 0; j < w; j++) {
2199  if (GET_DATA_BIT(line, j))
2200  array[j] += 1.0;
2201  }
2202  }
2203 
2204  return na;
2205 }
2206 
2207 
2217 l_ok
2219  l_int32 row,
2220  l_int32 *pcount,
2221  l_int32 *tab8)
2222 {
2223 l_uint32 word, endmask;
2224 l_int32 j, w, h, wpl;
2225 l_int32 fullwords, endbits, sum;
2226 l_int32 *tab;
2227 l_uint32 *line;
2228 
2229  PROCNAME("pixCountPixelsInRow");
2230 
2231  if (!pcount)
2232  return ERROR_INT("&count not defined", procName, 1);
2233  *pcount = 0;
2234  if (!pix || pixGetDepth(pix) != 1)
2235  return ERROR_INT("pix not defined or not 1 bpp", procName, 1);
2236 
2237  pixGetDimensions(pix, &w, &h, NULL);
2238  if (row < 0 || row >= h)
2239  return ERROR_INT("row out of bounds", procName, 1);
2240  wpl = pixGetWpl(pix);
2241  line = pixGetData(pix) + row * wpl;
2242  fullwords = w >> 5;
2243  endbits = w & 31;
2244  endmask = (endbits == 0) ? 0 : (0xffffffffU << (32 - endbits));
2245 
2246  tab = (tab8) ? tab8 : makePixelSumTab8();
2247  sum = 0;
2248  for (j = 0; j < fullwords; j++) {
2249  word = line[j];
2250  if (word) {
2251  sum += tab[word & 0xff] +
2252  tab[(word >> 8) & 0xff] +
2253  tab[(word >> 16) & 0xff] +
2254  tab[(word >> 24) & 0xff];
2255  }
2256  }
2257  if (endbits) {
2258  word = line[j] & endmask;
2259  if (word) {
2260  sum += tab[word & 0xff] +
2261  tab[(word >> 8) & 0xff] +
2262  tab[(word >> 16) & 0xff] +
2263  tab[(word >> 24) & 0xff];
2264  }
2265  }
2266  *pcount = sum;
2267 
2268  if (!tab8) LEPT_FREE(tab);
2269  return 0;
2270 }
2271 
2272 
2280 NUMA *
2282  l_int32 order)
2283 {
2284 l_int32 i, j, w, h, wpl;
2285 l_uint32 *line, *data;
2286 l_float32 *array;
2287 NUMA *na;
2288 
2289  PROCNAME("pixGetMomentByColumn");
2290 
2291  if (!pix || pixGetDepth(pix) != 1)
2292  return (NUMA *)ERROR_PTR("pix undefined or not 1 bpp", procName, NULL);
2293  if (order != 1 && order != 2)
2294  return (NUMA *)ERROR_PTR("order of moment not 1 or 2", procName, NULL);
2295 
2296  pixGetDimensions(pix, &w, &h, NULL);
2297  if ((na = numaCreate(w)) == NULL)
2298  return (NUMA *)ERROR_PTR("na not made", procName, NULL);
2299  numaSetCount(na, w);
2300  array = numaGetFArray(na, L_NOCOPY);
2301  data = pixGetData(pix);
2302  wpl = pixGetWpl(pix);
2303  for (i = 0; i < h; i++) {
2304  line = data + wpl * i;
2305  for (j = 0; j < w; j++) {
2306  if (GET_DATA_BIT(line, j)) {
2307  if (order == 1)
2308  array[j] += i;
2309  else /* order == 2 */
2310  array[j] += i * i;
2311  }
2312  }
2313  }
2314 
2315  return na;
2316 }
2317 
2318 
2338 l_ok
2340  l_int32 thresh,
2341  l_int32 *pabove,
2342  l_int32 *tab8)
2343 {
2344 l_uint32 word, endmask;
2345 l_int32 *tab;
2346 l_int32 w, h, wpl, i, j;
2347 l_int32 fullwords, endbits, sum;
2348 l_uint32 *line, *data;
2349 
2350  PROCNAME("pixThresholdPixelSum");
2351 
2352  if (!pabove)
2353  return ERROR_INT("&above not defined", procName, 1);
2354  *pabove = 0;
2355  if (!pix || pixGetDepth(pix) != 1)
2356  return ERROR_INT("pix not defined or not 1 bpp", procName, 1);
2357 
2358  tab = (tab8) ? tab8 : makePixelSumTab8();
2359  pixGetDimensions(pix, &w, &h, NULL);
2360  wpl = pixGetWpl(pix);
2361  data = pixGetData(pix);
2362  fullwords = w >> 5;
2363  endbits = w & 31;
2364  endmask = 0xffffffff << (32 - endbits);
2365 
2366  sum = 0;
2367  for (i = 0; i < h; i++) {
2368  line = data + wpl * i;
2369  for (j = 0; j < fullwords; j++) {
2370  word = line[j];
2371  if (word) {
2372  sum += tab[word & 0xff] +
2373  tab[(word >> 8) & 0xff] +
2374  tab[(word >> 16) & 0xff] +
2375  tab[(word >> 24) & 0xff];
2376  }
2377  }
2378  if (endbits) {
2379  word = line[j] & endmask;
2380  if (word) {
2381  sum += tab[word & 0xff] +
2382  tab[(word >> 8) & 0xff] +
2383  tab[(word >> 16) & 0xff] +
2384  tab[(word >> 24) & 0xff];
2385  }
2386  }
2387  if (sum > thresh) {
2388  *pabove = 1;
2389  if (!tab8) LEPT_FREE(tab);
2390  return 0;
2391  }
2392  }
2393 
2394  if (!tab8) LEPT_FREE(tab);
2395  return 0;
2396 }
2397 
2398 
2410 l_int32 *
2412 {
2413 l_uint8 byte;
2414 l_int32 i;
2415 l_int32 *tab;
2416 
2417  tab = (l_int32 *)LEPT_CALLOC(256, sizeof(l_int32));
2418  for (i = 0; i < 256; i++) {
2419  byte = (l_uint8)i;
2420  tab[i] = (byte & 0x1) +
2421  ((byte >> 1) & 0x1) +
2422  ((byte >> 2) & 0x1) +
2423  ((byte >> 3) & 0x1) +
2424  ((byte >> 4) & 0x1) +
2425  ((byte >> 5) & 0x1) +
2426  ((byte >> 6) & 0x1) +
2427  ((byte >> 7) & 0x1);
2428  }
2429  return tab;
2430 }
2431 
2432 
2450 l_int32 *
2452 {
2453 l_int32 i;
2454 l_int32 *tab;
2455 
2456  tab = (l_int32 *)LEPT_CALLOC(256, sizeof(l_int32));
2457  tab[0] = 0;
2458  tab[1] = 7;
2459  for (i = 2; i < 4; i++) {
2460  tab[i] = tab[i - 2] + 6;
2461  }
2462  for (i = 4; i < 8; i++) {
2463  tab[i] = tab[i - 4] + 5;
2464  }
2465  for (i = 8; i < 16; i++) {
2466  tab[i] = tab[i - 8] + 4;
2467  }
2468  for (i = 16; i < 32; i++) {
2469  tab[i] = tab[i - 16] + 3;
2470  }
2471  for (i = 32; i < 64; i++) {
2472  tab[i] = tab[i - 32] + 2;
2473  }
2474  for (i = 64; i < 128; i++) {
2475  tab[i] = tab[i - 64] + 1;
2476  }
2477  for (i = 128; i < 256; i++) {
2478  tab[i] = tab[i - 128];
2479  }
2480  return tab;
2481 }
2482 
2483 
2484 /*-------------------------------------------------------------*
2485  * Average of pixel values in gray images *
2486  *-------------------------------------------------------------*/
2503 NUMA *
2505  BOX *box,
2506  l_int32 type)
2507 {
2508 l_int32 i, j, w, h, d, wpl, xstart, xend, ystart, yend, bw, bh;
2509 l_uint32 *line, *data;
2510 l_float64 norm, sum;
2511 NUMA *na;
2512 
2513  PROCNAME("pixAverageByRow");
2514 
2515  if (!pix)
2516  return (NUMA *)ERROR_PTR("pix not defined", procName, NULL);
2517  pixGetDimensions(pix, &w, &h, &d);
2518  if (d != 8 && d != 16)
2519  return (NUMA *)ERROR_PTR("pix not 8 or 16 bpp", procName, NULL);
2520  if (type != L_WHITE_IS_MAX && type != L_BLACK_IS_MAX)
2521  return (NUMA *)ERROR_PTR("invalid type", procName, NULL);
2522  if (pixGetColormap(pix) != NULL)
2523  return (NUMA *)ERROR_PTR("pix colormapped", procName, NULL);
2524 
2525  if (boxClipToRectangleParams(box, w, h, &xstart, &ystart, &xend, &yend,
2526  &bw, &bh) == 1)
2527  return (NUMA *)ERROR_PTR("invalid clipping box", procName, NULL);
2528 
2529  norm = 1. / (l_float32)bw;
2530  if ((na = numaCreate(bh)) == NULL)
2531  return (NUMA *)ERROR_PTR("na not made", procName, NULL);
2532  numaSetParameters(na, ystart, 1);
2533  data = pixGetData(pix);
2534  wpl = pixGetWpl(pix);
2535  for (i = ystart; i < yend; i++) {
2536  sum = 0.0;
2537  line = data + i * wpl;
2538  if (d == 8) {
2539  for (j = xstart; j < xend; j++)
2540  sum += GET_DATA_BYTE(line, j);
2541  if (type == L_BLACK_IS_MAX)
2542  sum = bw * 255 - sum;
2543  } else { /* d == 16 */
2544  for (j = xstart; j < xend; j++)
2545  sum += GET_DATA_TWO_BYTES(line, j);
2546  if (type == L_BLACK_IS_MAX)
2547  sum = bw * 0xffff - sum;
2548  }
2549  numaAddNumber(na, (l_float32)(norm * sum));
2550  }
2551 
2552  return na;
2553 }
2554 
2555 
2572 NUMA *
2574  BOX *box,
2575  l_int32 type)
2576 {
2577 l_int32 i, j, w, h, d, wpl, xstart, xend, ystart, yend, bw, bh;
2578 l_uint32 *line, *data;
2579 l_float32 norm, sum;
2580 NUMA *na;
2581 
2582  PROCNAME("pixAverageByColumn");
2583 
2584  if (!pix)
2585  return (NUMA *)ERROR_PTR("pix not defined", procName, NULL);
2586  pixGetDimensions(pix, &w, &h, &d);
2587 
2588  if (d != 8 && d != 16)
2589  return (NUMA *)ERROR_PTR("pix not 8 or 16 bpp", procName, NULL);
2590  if (type != L_WHITE_IS_MAX && type != L_BLACK_IS_MAX)
2591  return (NUMA *)ERROR_PTR("invalid type", procName, NULL);
2592  if (pixGetColormap(pix) != NULL)
2593  return (NUMA *)ERROR_PTR("pix colormapped", procName, NULL);
2594 
2595  if (boxClipToRectangleParams(box, w, h, &xstart, &ystart, &xend, &yend,
2596  &bw, &bh) == 1)
2597  return (NUMA *)ERROR_PTR("invalid clipping box", procName, NULL);
2598 
2599  if ((na = numaCreate(bw)) == NULL)
2600  return (NUMA *)ERROR_PTR("na not made", procName, NULL);
2601  numaSetParameters(na, xstart, 1);
2602  norm = 1. / (l_float32)bh;
2603  data = pixGetData(pix);
2604  wpl = pixGetWpl(pix);
2605  for (j = xstart; j < xend; j++) {
2606  sum = 0.0;
2607  if (d == 8) {
2608  for (i = ystart; i < yend; i++) {
2609  line = data + i * wpl;
2610  sum += GET_DATA_BYTE(line, j);
2611  }
2612  if (type == L_BLACK_IS_MAX)
2613  sum = bh * 255 - sum;
2614  } else { /* d == 16 */
2615  for (i = ystart; i < yend; i++) {
2616  line = data + i * wpl;
2617  sum += GET_DATA_TWO_BYTES(line, j);
2618  }
2619  if (type == L_BLACK_IS_MAX)
2620  sum = bh * 0xffff - sum;
2621  }
2622  numaAddNumber(na, (l_float32)(norm * sum));
2623  }
2624 
2625  return na;
2626 }
2627 
2628 
2659 l_ok
2661  PIX *pixm,
2662  BOX *box,
2663  l_int32 minval,
2664  l_int32 maxval,
2665  l_int32 subsamp,
2666  l_float32 *pave)
2667 {
2668 l_int32 w, h, d, wpls, wm, hm, dm, wplm, val, count;
2669 l_int32 i, j, xstart, xend, ystart, yend;
2670 l_uint32 *datas, *datam, *lines, *linem;
2671 l_float64 sum;
2672 
2673  PROCNAME("pixAverageInRect");
2674 
2675  if (!pave)
2676  return ERROR_INT("&ave not defined", procName, 1);
2677  *pave = 0;
2678  if (!pixs)
2679  return ERROR_INT("pixs not defined", procName, 1);
2680  if (pixGetColormap(pixs) != NULL)
2681  return ERROR_INT("pixs is colormapped", procName, 1);
2682  pixGetDimensions(pixs, &w, &h, &d);
2683  if (d != 1 && d != 2 && d != 4 && d != 8)
2684  return ERROR_INT("pixs not 1, 2, 4 or 8 bpp", procName, 1);
2685  if (pixm) {
2686  pixGetDimensions(pixm, &wm, &hm, &dm);
2687  if (dm != 1)
2688  return ERROR_INT("pixm not 1 bpp", procName, 1);
2689  w = L_MIN(w, wm);
2690  h = L_MIN(h, hm);
2691  }
2692  if (subsamp < 1)
2693  return ERROR_INT("subsamp must be >= 1", procName, 1);
2694 
2695  if (boxClipToRectangleParams(box, w, h, &xstart, &ystart, &xend, &yend,
2696  NULL, NULL) == 1)
2697  return ERROR_INT("invalid clipping box", procName, 1);
2698 
2699  datas = pixGetData(pixs);
2700  wpls = pixGetWpl(pixs);
2701  if (pixm) {
2702  datam = pixGetData(pixm);
2703  wplm = pixGetWpl(pixm);
2704  }
2705  sum = 0.0;
2706  count = 0;
2707  for (i = ystart; i < yend; i += subsamp) {
2708  lines = datas + i * wpls;
2709  if (pixm)
2710  linem = datam + i * wplm;
2711  for (j = xstart; j < xend; j += subsamp) {
2712  if (pixm && (GET_DATA_BIT(linem, j) == 1))
2713  continue;
2714  if (d == 1)
2715  val = GET_DATA_BIT(lines, j);
2716  else if (d == 2)
2717  val = GET_DATA_DIBIT(lines, j);
2718  else if (d == 4)
2719  val = GET_DATA_QBIT(lines, j);
2720  else /* d == 8 */
2721  val = GET_DATA_BYTE(lines, j);
2722  if (val >= minval && val <= maxval) {
2723  sum += val;
2724  count++;
2725  }
2726  }
2727  }
2728 
2729  if (count == 0)
2730  return 2; /* not an error; don't use the average value (0.0) */
2731  *pave = sum / (l_float32)count;
2732  return 0;
2733 }
2734 
2735 
2736 /*-------------------------------------------------------------*
2737  * Average of pixel values in RGB images *
2738  *-------------------------------------------------------------*/
2766 l_ok
2768  PIX *pixm,
2769  BOX *box,
2770  l_int32 subsamp,
2771  l_uint32 *pave)
2772 {
2773 l_int32 w, h, wpls, wm, hm, dm, wplm, i, j, xstart, xend, ystart, yend;
2774 l_int32 rval, gval, bval, rave, gave, bave, count;
2775 l_uint32 *datas, *datam, *lines, *linem;
2776 l_uint32 pixel;
2777 l_float64 rsum, gsum, bsum;
2778 
2779  PROCNAME("pixAverageInRectRGB");
2780 
2781  if (!pave)
2782  return ERROR_INT("&ave not defined", procName, 1);
2783  *pave = 0;
2784  if (!pixs || pixGetDepth(pixs) != 32)
2785  return ERROR_INT("pixs undefined or not 32 bpp", procName, 1);
2786  pixGetDimensions(pixs, &w, &h, NULL);
2787  if (pixm) {
2788  pixGetDimensions(pixm, &wm, &hm, &dm);
2789  if (dm != 1)
2790  return ERROR_INT("pixm not 1 bpp", procName, 1);
2791  w = L_MIN(w, wm);
2792  h = L_MIN(h, hm);
2793  }
2794  if (subsamp < 1)
2795  return ERROR_INT("subsamp must be >= 1", procName, 1);
2796 
2797  if (boxClipToRectangleParams(box, w, h, &xstart, &ystart, &xend, &yend,
2798  NULL, NULL) == 1)
2799  return ERROR_INT("invalid clipping box", procName, 1);
2800 
2801  datas = pixGetData(pixs);
2802  wpls = pixGetWpl(pixs);
2803  if (pixm) {
2804  datam = pixGetData(pixm);
2805  wplm = pixGetWpl(pixm);
2806  }
2807  rsum = gsum = bsum = 0.0;
2808  count = 0;
2809  for (i = ystart; i < yend; i += subsamp) {
2810  lines = datas + i * wpls;
2811  if (pixm)
2812  linem = datam + i * wplm;
2813  for (j = xstart; j < xend; j += subsamp) {
2814  if (pixm && (GET_DATA_BIT(linem, j) == 1))
2815  continue;
2816  pixel = *(lines + j);
2817  extractRGBValues(pixel, &rval, &gval, &bval);
2818  rsum += rval;
2819  gsum += gval;
2820  bsum += bval;
2821  count++;
2822  }
2823  }
2824 
2825  if (count == 0)
2826  return 2; /* not an error */
2827  rave = (l_uint32)(rsum / (l_float64)count);
2828  gave = (l_uint32)(gsum / (l_float64)count);
2829  bave = (l_uint32)(bsum / (l_float64)count);
2830  composeRGBPixel(rave, gave, bave, pave);
2831  return 0;
2832 }
2833 
2834 
2835 /*------------------------------------------------------------------*
2836  * Variance of pixel values in gray images *
2837  *------------------------------------------------------------------*/
2853 NUMA *
2855  BOX *box)
2856 {
2857 l_int32 i, j, w, h, d, wpl, xstart, xend, ystart, yend, bw, bh, val;
2858 l_uint32 *line, *data;
2859 l_float64 sum1, sum2, norm, ave, var, rootvar;
2860 NUMA *na;
2861 
2862  PROCNAME("pixVarianceByRow");
2863 
2864  if (!pix)
2865  return (NUMA *)ERROR_PTR("pix not defined", procName, NULL);
2866  pixGetDimensions(pix, &w, &h, &d);
2867  if (d != 8 && d != 16)
2868  return (NUMA *)ERROR_PTR("pix not 8 or 16 bpp", procName, NULL);
2869  if (pixGetColormap(pix) != NULL)
2870  return (NUMA *)ERROR_PTR("pix colormapped", procName, NULL);
2871 
2872  if (boxClipToRectangleParams(box, w, h, &xstart, &ystart, &xend, &yend,
2873  &bw, &bh) == 1)
2874  return (NUMA *)ERROR_PTR("invalid clipping box", procName, NULL);
2875 
2876  if ((na = numaCreate(bh)) == NULL)
2877  return (NUMA *)ERROR_PTR("na not made", procName, NULL);
2878  numaSetParameters(na, ystart, 1);
2879  norm = 1. / (l_float32)bw;
2880  data = pixGetData(pix);
2881  wpl = pixGetWpl(pix);
2882  for (i = ystart; i < yend; i++) {
2883  sum1 = sum2 = 0.0;
2884  line = data + i * wpl;
2885  for (j = xstart; j < xend; j++) {
2886  if (d == 8)
2887  val = GET_DATA_BYTE(line, j);
2888  else /* d == 16 */
2889  val = GET_DATA_TWO_BYTES(line, j);
2890  sum1 += val;
2891  sum2 += (l_float64)(val) * val;
2892  }
2893  ave = norm * sum1;
2894  var = norm * sum2 - ave * ave;
2895  rootvar = sqrt(var);
2896  numaAddNumber(na, (l_float32)rootvar);
2897  }
2898 
2899  return na;
2900 }
2901 
2902 
2918 NUMA *
2920  BOX *box)
2921 {
2922 l_int32 i, j, w, h, d, wpl, xstart, xend, ystart, yend, bw, bh, val;
2923 l_uint32 *line, *data;
2924 l_float64 sum1, sum2, norm, ave, var, rootvar;
2925 NUMA *na;
2926 
2927  PROCNAME("pixVarianceByColumn");
2928 
2929  if (!pix)
2930  return (NUMA *)ERROR_PTR("pix not defined", procName, NULL);
2931  pixGetDimensions(pix, &w, &h, &d);
2932  if (d != 8 && d != 16)
2933  return (NUMA *)ERROR_PTR("pix not 8 or 16 bpp", procName, NULL);
2934  if (pixGetColormap(pix) != NULL)
2935  return (NUMA *)ERROR_PTR("pix colormapped", procName, NULL);
2936 
2937  if (boxClipToRectangleParams(box, w, h, &xstart, &ystart, &xend, &yend,
2938  &bw, &bh) == 1)
2939  return (NUMA *)ERROR_PTR("invalid clipping box", procName, NULL);
2940 
2941  if ((na = numaCreate(bw)) == NULL)
2942  return (NUMA *)ERROR_PTR("na not made", procName, NULL);
2943  numaSetParameters(na, xstart, 1);
2944  norm = 1. / (l_float32)bh;
2945  data = pixGetData(pix);
2946  wpl = pixGetWpl(pix);
2947  for (j = xstart; j < xend; j++) {
2948  sum1 = sum2 = 0.0;
2949  for (i = ystart; i < yend; i++) {
2950  line = data + wpl * i;
2951  if (d == 8)
2952  val = GET_DATA_BYTE(line, j);
2953  else /* d == 16 */
2954  val = GET_DATA_TWO_BYTES(line, j);
2955  sum1 += val;
2956  sum2 += (l_float64)(val) * val;
2957  }
2958  ave = norm * sum1;
2959  var = norm * sum2 - ave * ave;
2960  rootvar = sqrt(var);
2961  numaAddNumber(na, (l_float32)rootvar);
2962  }
2963 
2964  return na;
2965 }
2966 
2967 
2976 l_ok
2978  BOX *box,
2979  l_float32 *prootvar)
2980 {
2981 l_int32 w, h, d, wpl, i, j, xstart, xend, ystart, yend, bw, bh, val;
2982 l_uint32 *data, *line;
2983 l_float64 sum1, sum2, norm, ave, var;
2984 
2985  PROCNAME("pixVarianceInRect");
2986 
2987  if (!prootvar)
2988  return ERROR_INT("&rootvar not defined", procName, 1);
2989  *prootvar = 0.0;
2990  if (!pix)
2991  return ERROR_INT("pix not defined", procName, 1);
2992  pixGetDimensions(pix, &w, &h, &d);
2993  if (d != 1 && d != 2 && d != 4 && d != 8)
2994  return ERROR_INT("pix not 1, 2, 4 or 8 bpp", procName, 1);
2995  if (pixGetColormap(pix) != NULL)
2996  return ERROR_INT("pix is colormapped", procName, 1);
2997 
2998  if (boxClipToRectangleParams(box, w, h, &xstart, &ystart, &xend, &yend,
2999  &bw, &bh) == 1)
3000  return ERROR_INT("invalid clipping box", procName, 1);
3001 
3002  wpl = pixGetWpl(pix);
3003  data = pixGetData(pix);
3004  sum1 = sum2 = 0.0;
3005  for (i = ystart; i < yend; i++) {
3006  line = data + i * wpl;
3007  for (j = xstart; j < xend; j++) {
3008  if (d == 1) {
3009  val = GET_DATA_BIT(line, j);
3010  sum1 += val;
3011  sum2 += (l_float64)(val) * val;
3012  } else if (d == 2) {
3013  val = GET_DATA_DIBIT(line, j);
3014  sum1 += val;
3015  sum2 += (l_float64)(val) * val;
3016  } else if (d == 4) {
3017  val = GET_DATA_QBIT(line, j);
3018  sum1 += val;
3019  sum2 += (l_float64)(val) * val;
3020  } else { /* d == 8 */
3021  val = GET_DATA_BYTE(line, j);
3022  sum1 += val;
3023  sum2 += (l_float64)(val) * val;
3024  }
3025  }
3026  }
3027  norm = 1.0 / ((l_float64)(bw) * bh);
3028  ave = norm * sum1;
3029  var = norm * sum2 - ave * ave;
3030  *prootvar = (l_float32)sqrt(var);
3031  return 0;
3032 }
3033 
3034 
3035 /*---------------------------------------------------------------------*
3036  * Average of absolute value of pixel differences in gray images *
3037  *---------------------------------------------------------------------*/
3053 NUMA *
3055  BOX *box)
3056 {
3057 l_int32 i, j, w, h, wpl, xstart, xend, ystart, yend, bw, bh, val0, val1;
3058 l_uint32 *line, *data;
3059 l_float64 norm, sum;
3060 NUMA *na;
3061 
3062  PROCNAME("pixAbsDiffByRow");
3063 
3064  if (!pix || pixGetDepth(pix) != 8)
3065  return (NUMA *)ERROR_PTR("pix undefined or not 8 bpp", procName, NULL);
3066  if (pixGetColormap(pix) != NULL)
3067  return (NUMA *)ERROR_PTR("pix colormapped", procName, NULL);
3068 
3069  pixGetDimensions(pix, &w, &h, NULL);
3070  if (boxClipToRectangleParams(box, w, h, &xstart, &ystart, &xend, &yend,
3071  &bw, &bh) == 1)
3072  return (NUMA *)ERROR_PTR("invalid clipping box", procName, NULL);
3073  if (bw < 2)
3074  return (NUMA *)ERROR_PTR("row width must be >= 2", procName, NULL);
3075 
3076  norm = 1. / (l_float32)(bw - 1);
3077  if ((na = numaCreate(bh)) == NULL)
3078  return (NUMA *)ERROR_PTR("na not made", procName, NULL);
3079  numaSetParameters(na, ystart, 1);
3080  data = pixGetData(pix);
3081  wpl = pixGetWpl(pix);
3082  for (i = ystart; i < yend; i++) {
3083  sum = 0.0;
3084  line = data + i * wpl;
3085  val0 = GET_DATA_BYTE(line, xstart);
3086  for (j = xstart + 1; j < xend; j++) {
3087  val1 = GET_DATA_BYTE(line, j);
3088  sum += L_ABS(val1 - val0);
3089  val0 = val1;
3090  }
3091  numaAddNumber(na, (l_float32)(norm * sum));
3092  }
3093 
3094  return na;
3095 }
3096 
3097 
3114 NUMA *
3116  BOX *box)
3117 {
3118 l_int32 i, j, w, h, wpl, xstart, xend, ystart, yend, bw, bh, val0, val1;
3119 l_uint32 *line, *data;
3120 l_float64 norm, sum;
3121 NUMA *na;
3122 
3123  PROCNAME("pixAbsDiffByColumn");
3124 
3125  if (!pix || pixGetDepth(pix) != 8)
3126  return (NUMA *)ERROR_PTR("pix undefined or not 8 bpp", procName, NULL);
3127  if (pixGetColormap(pix) != NULL)
3128  return (NUMA *)ERROR_PTR("pix colormapped", procName, NULL);
3129 
3130  pixGetDimensions(pix, &w, &h, NULL);
3131  if (boxClipToRectangleParams(box, w, h, &xstart, &ystart, &xend, &yend,
3132  &bw, &bh) == 1)
3133  return (NUMA *)ERROR_PTR("invalid clipping box", procName, NULL);
3134  if (bh < 2)
3135  return (NUMA *)ERROR_PTR("column height must be >= 2", procName, NULL);
3136 
3137  norm = 1. / (l_float32)(bh - 1);
3138  if ((na = numaCreate(bw)) == NULL)
3139  return (NUMA *)ERROR_PTR("na not made", procName, NULL);
3140  numaSetParameters(na, xstart, 1);
3141  data = pixGetData(pix);
3142  wpl = pixGetWpl(pix);
3143  for (j = xstart; j < xend; j++) {
3144  sum = 0.0;
3145  line = data + ystart * wpl;
3146  val0 = GET_DATA_BYTE(line, j);
3147  for (i = ystart + 1; i < yend; i++) {
3148  line = data + i * wpl;
3149  val1 = GET_DATA_BYTE(line, j);
3150  sum += L_ABS(val1 - val0);
3151  val0 = val1;
3152  }
3153  numaAddNumber(na, (l_float32)(norm * sum));
3154  }
3155 
3156  return na;
3157 }
3158 
3159 
3177 l_ok
3179  BOX *box,
3180  l_int32 dir,
3181  l_float32 *pabsdiff)
3182 {
3183 l_int32 w, h, wpl, i, j, xstart, xend, ystart, yend, bw, bh, val0, val1;
3184 l_uint32 *data, *line;
3185 l_float64 norm, sum;
3186 
3187  PROCNAME("pixAbsDiffInRect");
3188 
3189  if (!pabsdiff)
3190  return ERROR_INT("&absdiff not defined", procName, 1);
3191  *pabsdiff = 0.0;
3192  if (!pix || pixGetDepth(pix) != 8)
3193  return ERROR_INT("pix undefined or not 8 bpp", procName, 1);
3194  if (dir != L_HORIZONTAL_LINE && dir != L_VERTICAL_LINE)
3195  return ERROR_INT("invalid direction", procName, 1);
3196  if (pixGetColormap(pix) != NULL)
3197  return ERROR_INT("pix is colormapped", procName, 1);
3198 
3199  pixGetDimensions(pix, &w, &h, NULL);
3200  if (boxClipToRectangleParams(box, w, h, &xstart, &ystart, &xend, &yend,
3201  &bw, &bh) == 1)
3202  return ERROR_INT("invalid clipping box", procName, 1);
3203 
3204  wpl = pixGetWpl(pix);
3205  data = pixGetData(pix);
3206  if (dir == L_HORIZONTAL_LINE) {
3207  norm = 1. / (l_float32)(bh * (bw - 1));
3208  sum = 0.0;
3209  for (i = ystart; i < yend; i++) {
3210  line = data + i * wpl;
3211  val0 = GET_DATA_BYTE(line, xstart);
3212  for (j = xstart + 1; j < xend; j++) {
3213  val1 = GET_DATA_BYTE(line, j);
3214  sum += L_ABS(val1 - val0);
3215  val0 = val1;
3216  }
3217  }
3218  } else { /* vertical line */
3219  norm = 1. / (l_float32)(bw * (bh - 1));
3220  sum = 0.0;
3221  for (j = xstart; j < xend; j++) {
3222  line = data + ystart * wpl;
3223  val0 = GET_DATA_BYTE(line, j);
3224  for (i = ystart + 1; i < yend; i++) {
3225  line = data + i * wpl;
3226  val1 = GET_DATA_BYTE(line, j);
3227  sum += L_ABS(val1 - val0);
3228  val0 = val1;
3229  }
3230  }
3231  }
3232  *pabsdiff = (l_float32)(norm * sum);
3233  return 0;
3234 }
3235 
3236 
3254 l_ok
3256  l_int32 x1,
3257  l_int32 y1,
3258  l_int32 x2,
3259  l_int32 y2,
3260  l_float32 *pabsdiff)
3261 {
3262 l_int32 w, h, i, j, dir, size, sum;
3263 l_uint32 val0, val1;
3264 
3265  PROCNAME("pixAbsDiffOnLine");
3266 
3267  if (!pabsdiff)
3268  return ERROR_INT("&absdiff not defined", procName, 1);
3269  *pabsdiff = 0.0;
3270  if (!pix || pixGetDepth(pix) != 8)
3271  return ERROR_INT("pix undefined or not 8 bpp", procName, 1);
3272  if (y1 == y2) {
3273  dir = L_HORIZONTAL_LINE;
3274  } else if (x1 == x2) {
3275  dir = L_VERTICAL_LINE;
3276  } else {
3277  return ERROR_INT("line is neither horiz nor vert", procName, 1);
3278  }
3279  if (pixGetColormap(pix) != NULL)
3280  return ERROR_INT("pix is colormapped", procName, 1);
3281 
3282  pixGetDimensions(pix, &w, &h, NULL);
3283  sum = 0;
3284  if (dir == L_HORIZONTAL_LINE) {
3285  x1 = L_MAX(x1, 0);
3286  x2 = L_MIN(x2, w - 1);
3287  if (x1 >= x2)
3288  return ERROR_INT("x1 >= x2", procName, 1);
3289  size = x2 - x1;
3290  pixGetPixel(pix, x1, y1, &val0);
3291  for (j = x1 + 1; j <= x2; j++) {
3292  pixGetPixel(pix, j, y1, &val1);
3293  sum += L_ABS((l_int32)val1 - (l_int32)val0);
3294  val0 = val1;
3295  }
3296  } else { /* vertical */
3297  y1 = L_MAX(y1, 0);
3298  y2 = L_MIN(y2, h - 1);
3299  if (y1 >= y2)
3300  return ERROR_INT("y1 >= y2", procName, 1);
3301  size = y2 - y1;
3302  pixGetPixel(pix, x1, y1, &val0);
3303  for (i = y1 + 1; i <= y2; i++) {
3304  pixGetPixel(pix, x1, i, &val1);
3305  sum += L_ABS((l_int32)val1 - (l_int32)val0);
3306  val0 = val1;
3307  }
3308  }
3309  *pabsdiff = (l_float32)sum / (l_float32)size;
3310  return 0;
3311 }
3312 
3313 
3314 /*-------------------------------------------------------------*
3315  * Count of pixels with specific value *
3316  *-------------------------------------------------------------*/
3336 l_int32
3338  BOX *box,
3339  l_int32 val,
3340  l_int32 factor,
3341  l_int32 *pcount)
3342 {
3343 l_int32 i, j, bx, by, bw, bh, w, h, wpl, pixval;
3344 l_uint32 *data, *line;
3345 
3346  PROCNAME("pixCountArbInRect");
3347 
3348  if (!pcount)
3349  return ERROR_INT("&count not defined", procName, 1);
3350  *pcount = 0;
3351  if (!pixs)
3352  return ERROR_INT("pixs not defined", procName, 1);
3353  if (pixGetDepth(pixs) != 8 && !pixGetColormap(pixs))
3354  return ERROR_INT("pixs neither 8 bpp nor colormapped",
3355  procName, 1);
3356  if (factor < 1)
3357  return ERROR_INT("sampling factor < 1", procName, 1);
3358 
3359  pixGetDimensions(pixs, &w, &h, NULL);
3360  data = pixGetData(pixs);
3361  wpl = pixGetWpl(pixs);
3362 
3363  if (!box) {
3364  for (i = 0; i < h; i += factor) {
3365  line = data + i * wpl;
3366  for (j = 0; j < w; j += factor) {
3367  pixval = GET_DATA_BYTE(line, j);
3368  if (pixval == val) (*pcount)++;
3369  }
3370  }
3371  } else {
3372  boxGetGeometry(box, &bx, &by, &bw, &bh);
3373  for (i = 0; i < bh; i += factor) {
3374  if (by + i < 0 || by + i >= h) continue;
3375  line = data + (by + i) * wpl;
3376  for (j = 0; j < bw; j += factor) {
3377  if (bx + j < 0 || bx + j >= w) continue;
3378  pixval = GET_DATA_BYTE(line, bx + j);
3379  if (pixval == val) (*pcount)++;
3380  }
3381  }
3382  }
3383 
3384  if (factor > 1) /* assume pixel color is randomly distributed */
3385  *pcount = *pcount * factor * factor;
3386  return 0;
3387 }
3388 
3389 
3390 /*-------------------------------------------------------------*
3391  * Mirrored tiling of a smaller image *
3392  *-------------------------------------------------------------*/
3414 PIX *
3416  l_int32 w,
3417  l_int32 h)
3418 {
3419 l_int32 wt, ht, d, i, j, nx, ny;
3420 PIX *pixd, *pixsfx, *pixsfy, *pixsfxy, *pix;
3421 
3422  PROCNAME("pixMirroredTiling");
3423 
3424  if (!pixs)
3425  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
3426  pixGetDimensions(pixs, &wt, &ht, &d);
3427  if (wt <= 0 || ht <= 0)
3428  return (PIX *)ERROR_PTR("pixs size illegal", procName, NULL);
3429  if (d != 8 && d != 32)
3430  return (PIX *)ERROR_PTR("depth not 32 bpp", procName, NULL);
3431 
3432  if ((pixd = pixCreate(w, h, d)) == NULL)
3433  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
3434  pixCopySpp(pixd, pixs);
3435 
3436  nx = (w + wt - 1) / wt;
3437  ny = (h + ht - 1) / ht;
3438  pixsfx = pixFlipLR(NULL, pixs);
3439  pixsfy = pixFlipTB(NULL, pixs);
3440  pixsfxy = pixFlipTB(NULL, pixsfx);
3441  for (i = 0; i < ny; i++) {
3442  for (j = 0; j < nx; j++) {
3443  pix = pixs;
3444  if ((i & 1) && !(j & 1))
3445  pix = pixsfy;
3446  else if (!(i & 1) && (j & 1))
3447  pix = pixsfx;
3448  else if ((i & 1) && (j & 1))
3449  pix = pixsfxy;
3450  pixRasterop(pixd, j * wt, i * ht, wt, ht, PIX_SRC, pix, 0, 0);
3451  }
3452  }
3453 
3454  pixDestroy(&pixsfx);
3455  pixDestroy(&pixsfy);
3456  pixDestroy(&pixsfxy);
3457  return pixd;
3458 }
3459 
3460 
3489 l_ok
3491  BOX *box,
3492  l_int32 searchdir,
3493  l_int32 mindist,
3494  l_int32 tsize,
3495  l_int32 ntiles,
3496  BOX **pboxtile,
3497  l_int32 debug)
3498 {
3499 l_int32 w, h, i, n, bestindex;
3500 l_float32 var_of_mean, median_of_mean, median_of_stdev, mean_val, stdev_val;
3501 l_float32 mindels, bestdelm, delm, dels, mean, stdev;
3502 BOXA *boxa;
3503 NUMA *namean, *nastdev;
3504 PIX *pix, *pixg;
3505 PIXA *pixa;
3506 
3507  PROCNAME("pixFindRepCloseTile");
3508 
3509  if (!pboxtile)
3510  return ERROR_INT("&boxtile not defined", procName, 1);
3511  *pboxtile = NULL;
3512  if (!pixs)
3513  return ERROR_INT("pixs not defined", procName, 1);
3514  if (!box)
3515  return ERROR_INT("box not defined", procName, 1);
3516  if (searchdir != L_HORIZ && searchdir != L_VERT)
3517  return ERROR_INT("invalid searchdir", procName, 1);
3518  if (mindist < 0)
3519  return ERROR_INT("mindist must be >= 0", procName, 1);
3520  if (tsize < 2)
3521  return ERROR_INT("tsize must be > 1", procName, 1);
3522  if (ntiles > 7) {
3523  L_WARNING("ntiles = %d; larger than suggested max of 7\n",
3524  procName, ntiles);
3525  }
3526 
3527  /* Locate tile regions */
3528  pixGetDimensions(pixs, &w, &h, NULL);
3529  boxa = findTileRegionsForSearch(box, w, h, searchdir, mindist,
3530  tsize, ntiles);
3531  if (!boxa)
3532  return ERROR_INT("no tiles found", procName, 1);
3533 
3534  /* Generate the tiles and the mean and stdev of intensity */
3535  pixa = pixClipRectangles(pixs, boxa);
3536  n = pixaGetCount(pixa);
3537  namean = numaCreate(n);
3538  nastdev = numaCreate(n);
3539  for (i = 0; i < n; i++) {
3540  pix = pixaGetPix(pixa, i, L_CLONE);
3541  pixg = pixConvertRGBToGray(pix, 0.33, 0.34, 0.33);
3542  pixGetAverageMasked(pixg, NULL, 0, 0, 1, L_MEAN_ABSVAL, &mean);
3543  pixGetAverageMasked(pixg, NULL, 0, 0, 1, L_STANDARD_DEVIATION, &stdev);
3544  numaAddNumber(namean, mean);
3545  numaAddNumber(nastdev, stdev);
3546  pixDestroy(&pix);
3547  pixDestroy(&pixg);
3548  }
3549 
3550  /* Find the median and variance of the averages. We require
3551  * the best tile to have a mean pixel intensity within a standard
3552  * deviation of the median of mean intensities, and choose the
3553  * tile in that set with the smallest stdev of pixel intensities
3554  * (as a proxy for the tile with least visible structure).
3555  * The median of the stdev is used, for debugging, as a normalizing
3556  * factor for the stdev of intensities within a tile. */
3557  numaGetStatsUsingHistogram(namean, 256, NULL, NULL, NULL, &var_of_mean,
3558  &median_of_mean, 0.0, NULL, NULL);
3559  numaGetStatsUsingHistogram(nastdev, 256, NULL, NULL, NULL, NULL,
3560  &median_of_stdev, 0.0, NULL, NULL);
3561  mindels = 1000.0;
3562  bestdelm = 1000.0;
3563  bestindex = 0;
3564  for (i = 0; i < n; i++) {
3565  numaGetFValue(namean, i, &mean_val);
3566  numaGetFValue(nastdev, i, &stdev_val);
3567  if (var_of_mean == 0.0) { /* uniform color; any box will do */
3568  delm = 0.0; /* any value < 1.01 */
3569  dels = 1.0; /* n'importe quoi */
3570  } else {
3571  delm = L_ABS(mean_val - median_of_mean) / sqrt(var_of_mean);
3572  dels = stdev_val / median_of_stdev;
3573  }
3574  if (delm < 1.01) {
3575  if (dels < mindels) {
3576  if (debug) {
3577  lept_stderr("i = %d, mean = %7.3f, delm = %7.3f,"
3578  " stdev = %7.3f, dels = %7.3f\n",
3579  i, mean_val, delm, stdev_val, dels);
3580  }
3581  mindels = dels;
3582  bestdelm = delm;
3583  bestindex = i;
3584  }
3585  }
3586  }
3587  *pboxtile = boxaGetBox(boxa, bestindex, L_COPY);
3588 
3589  if (debug) {
3590  L_INFO("median of mean = %7.3f\n", procName, median_of_mean);
3591  L_INFO("standard dev of mean = %7.3f\n", procName, sqrt(var_of_mean));
3592  L_INFO("median of stdev = %7.3f\n", procName, median_of_stdev);
3593  L_INFO("best tile: index = %d\n", procName, bestindex);
3594  L_INFO("delta from median in units of stdev = %5.3f\n",
3595  procName, bestdelm);
3596  L_INFO("stdev as fraction of median stdev = %5.3f\n",
3597  procName, mindels);
3598  }
3599 
3600  numaDestroy(&namean);
3601  numaDestroy(&nastdev);
3602  pixaDestroy(&pixa);
3603  boxaDestroy(&boxa);
3604  return 0;
3605 }
3606 
3607 
3624 static BOXA *
3626  l_int32 w,
3627  l_int32 h,
3628  l_int32 searchdir,
3629  l_int32 mindist,
3630  l_int32 tsize,
3631  l_int32 ntiles)
3632 {
3633 l_int32 bx, by, bw, bh, left, right, top, bot, i, j, nrows, ncols;
3634 l_int32 x0, y0, x, y, w_avail, w_needed, h_avail, h_needed, t_avail;
3635 BOX *box1;
3636 BOXA *boxa;
3637 
3638  PROCNAME("findTileRegionsForSearch");
3639 
3640  if (!box)
3641  return (BOXA *)ERROR_PTR("box not defined", procName, NULL);
3642  if (ntiles == 0)
3643  return (BOXA *)ERROR_PTR("no tiles requested", procName, NULL);
3644 
3645  boxGetGeometry(box, &bx, &by, &bw, &bh);
3646  if (searchdir == L_HORIZ) {
3647  /* Find the tile parameters for the search. Note that the
3648  * tiles are overlapping by 50% in each direction. */
3649  left = bx; /* distance to left of box */
3650  right = w - bx - bw + 1; /* distance to right of box */
3651  w_avail = L_MAX(left, right) - mindist;
3652  if (tsize & 1) tsize++; /* be sure it's even */
3653  if (w_avail < tsize) {
3654  L_ERROR("tsize = %d, w_avail = %d\n", procName, tsize, w_avail);
3655  return NULL;
3656  }
3657  w_needed = tsize + (ntiles - 1) * (tsize / 2);
3658  if (w_needed > w_avail) {
3659  t_avail = 1 + 2 * (w_avail - tsize) / tsize;
3660  L_WARNING("ntiles = %d; room for only %d\n", procName,
3661  ntiles, t_avail);
3662  ntiles = t_avail;
3663  w_needed = tsize + (ntiles - 1) * (tsize / 2);
3664  }
3665  nrows = L_MAX(1, 1 + 2 * (bh - tsize) / tsize);
3666 
3667  /* Generate the tile regions to search */
3668  boxa = boxaCreate(0);
3669  if (left > right) /* search to left */
3670  x0 = bx - w_needed;
3671  else /* search to right */
3672  x0 = bx + bw + mindist;
3673  for (i = 0; i < nrows; i++) {
3674  y = by + i * tsize / 2;
3675  for (j = 0; j < ntiles; j++) {
3676  x = x0 + j * tsize / 2;
3677  box1 = boxCreate(x, y, tsize, tsize);
3678  boxaAddBox(boxa, box1, L_INSERT);
3679  }
3680  }
3681  } else { /* L_VERT */
3682  /* Find the tile parameters for the search */
3683  top = by; /* distance above box */
3684  bot = h - by - bh + 1; /* distance below box */
3685  h_avail = L_MAX(top, bot) - mindist;
3686  if (h_avail < tsize) {
3687  L_ERROR("tsize = %d, h_avail = %d\n", procName, tsize, h_avail);
3688  return NULL;
3689  }
3690  h_needed = tsize + (ntiles - 1) * (tsize / 2);
3691  if (h_needed > h_avail) {
3692  t_avail = 1 + 2 * (h_avail - tsize) / tsize;
3693  L_WARNING("ntiles = %d; room for only %d\n", procName,
3694  ntiles, t_avail);
3695  ntiles = t_avail;
3696  h_needed = tsize + (ntiles - 1) * (tsize / 2);
3697  }
3698  ncols = L_MAX(1, 1 + 2 * (bw - tsize) / tsize);
3699 
3700  /* Generate the tile regions to search */
3701  boxa = boxaCreate(0);
3702  if (top > bot) /* search above */
3703  y0 = by - h_needed;
3704  else /* search below */
3705  y0 = by + bh + mindist;
3706  for (j = 0; j < ncols; j++) {
3707  x = bx + j * tsize / 2;
3708  for (i = 0; i < ntiles; i++) {
3709  y = y0 + i * tsize / 2;
3710  box1 = boxCreate(x, y, tsize, tsize);
3711  boxaAddBox(boxa, box1, L_INSERT);
3712  }
3713  }
3714  }
3715  return boxa;
3716 }
#define GET_DATA_QBIT(pdata, n)
Definition: arrayaccess.h:164
#define GET_DATA_TWO_BYTES(pdata, n)
Definition: arrayaccess.h:212
#define SET_DATA_BIT(pdata, n)
Definition: arrayaccess.h:127
#define SET_DATA_DIBIT(pdata, n, val)
Definition: arrayaccess.h:149
#define SET_DATA_TWO_BYTES(pdata, n, val)
Definition: arrayaccess.h:222
#define GET_DATA_BYTE(pdata, n)
Definition: arrayaccess.h:188
#define GET_DATA_DIBIT(pdata, n)
Definition: arrayaccess.h:145
#define SET_DATA_BYTE(pdata, n, val)
Definition: arrayaccess.h:198
#define GET_DATA_BIT(pdata, n)
Definition: arrayaccess.h:123
#define SET_DATA_QBIT(pdata, n, val)
Definition: arrayaccess.h:168
PIX * pixBlendWithGrayMask(PIX *pixs1, PIX *pixs2, PIX *pixg, l_int32 x, l_int32 y)
pixBlendWithGrayMask()
Definition: blend.c:1712
PIX * pixBlend(PIX *pixs1, PIX *pixs2, l_int32 x, l_int32 y, l_float32 fract)
pixBlend()
Definition: blend.c:176
void boxDestroy(BOX **pbox)
boxDestroy()
Definition: boxbasic.c:282
l_ok boxaGetBoxGeometry(BOXA *boxa, l_int32 index, l_int32 *px, l_int32 *py, l_int32 *pw, l_int32 *ph)
boxaGetBoxGeometry()
Definition: boxbasic.c:879
l_int32 boxaGetCount(BOXA *boxa)
boxaGetCount()
Definition: boxbasic.c:734
l_ok boxGetGeometry(BOX *box, l_int32 *px, l_int32 *py, l_int32 *pw, l_int32 *ph)
boxGetGeometry()
Definition: boxbasic.c:313
l_ok boxaAddBox(BOXA *boxa, BOX *box, l_int32 copyflag)
boxaAddBox()
Definition: boxbasic.c:620
void boxaDestroy(BOXA **pboxa)
boxaDestroy()
Definition: boxbasic.c:583
BOX * boxaGetBox(BOXA *boxa, l_int32 index, l_int32 accessflag)
boxaGetBox()
Definition: boxbasic.c:779
BOX * boxCreate(l_int32 x, l_int32 y, l_int32 w, l_int32 h)
boxCreate()
Definition: boxbasic.c:172
BOXA * boxaCreate(l_int32 n)
boxaCreate()
Definition: boxbasic.c:502
l_ok boxPrintStreamInfo(FILE *fp, BOX *box)
boxPrintStreamInfo()
Definition: boxbasic.c:2431
BOX * boxClipToRectangle(BOX *box, l_int32 wi, l_int32 hi)
boxClipToRectangle()
Definition: boxfunc1.c:1728
BOX * boxAdjustSides(BOX *boxd, BOX *boxs, l_int32 delleft, l_int32 delright, l_int32 deltop, l_int32 delbot)
boxAdjustSides()
Definition: boxfunc1.c:1991
l_ok boxClipToRectangleParams(BOX *box, l_int32 w, l_int32 h, l_int32 *pxstart, l_int32 *pystart, l_int32 *pxend, l_int32 *pyend, l_int32 *pbw, l_int32 *pbh)
boxClipToRectangleParams()
Definition: boxfunc1.c:1785
BOXA * pixConnComp(PIX *pixs, PIXA **ppixa, l_int32 connectivity)
pixConnComp()
Definition: conncomp.c:151
PIX * pixThresholdToBinary(PIX *pixs, l_int32 thresh)
pixThresholdToBinary()
Definition: grayquant.c:447
PIX * pixDilate(PIX *pixd, PIX *pixs, SEL *sel)
pixDilate()
Definition: morph.c:213
PIX * pixDilateBrick(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixDilateBrick()
Definition: morph.c:688
PIX * pixMorphSequence(PIX *pixs, const char *sequence, l_int32 dispsep)
pixMorphSequence()
Definition: morphseq.c:137
l_ok numaAddNumber(NUMA *na, l_float32 val)
numaAddNumber()
Definition: numabasic.c:478
l_ok numaGetFValue(NUMA *na, l_int32 index, l_float32 *pval)
numaGetFValue()
Definition: numabasic.c:719
NUMA * numaCreate(l_int32 n)
numaCreate()
Definition: numabasic.c:194
l_ok numaSetCount(NUMA *na, l_int32 newcount)
numaSetCount()
Definition: numabasic.c:685
void numaDestroy(NUMA **pna)
numaDestroy()
Definition: numabasic.c:366
l_ok numaSetParameters(NUMA *na, l_float32 startx, l_float32 delx)
numaSetParameters()
Definition: numabasic.c:993
l_float32 * numaGetFArray(NUMA *na, l_int32 copyflag)
numaGetFArray()
Definition: numabasic.c:892
l_ok numaGetStatsUsingHistogram(NUMA *na, l_int32 maxbins, l_float32 *pmin, l_float32 *pmax, l_float32 *pmean, l_float32 *pvariance, l_float32 *pmedian, l_float32 rank, l_float32 *prval, NUMA **phisto)
numaGetStatsUsingHistogram()
Definition: numafunc2.c:1261
l_ok pixSetMaskedCmap(PIX *pixs, PIX *pixm, l_int32 x, l_int32 y, l_int32 rval, l_int32 gval, l_int32 bval)
pixSetMaskedCmap()
Definition: paintcmap.c:698
l_uint32 * pixGetData(PIX *pix)
pixGetData()
Definition: pix1.c:1763
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:621
l_ok pixGetDimensions(const PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
Definition: pix1.c:1113
l_int32 pixSizesEqual(const PIX *pix1, const PIX *pix2)
pixSizesEqual()
Definition: pix1.c:1985
l_ok pixCopySpp(PIX *pixd, const PIX *pixs)
pixCopySpp()
Definition: pix1.c:1236
PIX * pixCopy(PIX *pixd, const PIX *pixs)
pixCopy()
Definition: pix1.c:705
PIX * pixCreateTemplate(const PIX *pixs)
pixCreateTemplate()
Definition: pix1.c:383
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition: pix1.c:315
PIX * pixClone(PIX *pixs)
pixClone()
Definition: pix1.c:593
PIX * pixGetRGBComponent(PIX *pixs, l_int32 comp)
pixGetRGBComponent()
Definition: pix2.c:2479
PIX * pixDisplayLayersRGBA(PIX *pixs, l_uint32 val, l_int32 maxw)
pixDisplayLayersRGBA()
Definition: pix2.c:2351
l_ok pixGetPixel(PIX *pix, l_int32 x, l_int32 y, l_uint32 *pval)
pixGetPixel()
Definition: pix2.c:190
l_ok pixSetAll(PIX *pix)
pixSetAll()
Definition: pix2.c:817
l_ok composeRGBPixel(l_int32 rval, l_int32 gval, l_int32 bval, l_uint32 *ppixel)
composeRGBPixel()
Definition: pix2.c:2751
void extractRGBValues(l_uint32 pixel, l_int32 *prval, l_int32 *pgval, l_int32 *pbval)
extractRGBValues()
Definition: pix2.c:2820
l_ok pixSetBlackOrWhite(PIX *pixs, l_int32 op)
pixSetBlackOrWhite()
Definition: pix2.c:1021
l_ok pixSetAllArbitrary(PIX *pix, l_uint32 val)
pixSetAllArbitrary()
Definition: pix2.c:951
NUMA * pixVarianceByRow(PIX *pix, BOX *box)
pixVarianceByRow()
Definition: pix3.c:2854
l_ok pixGetColorNearMaskBoundary(PIX *pixs, PIX *pixm, BOX *box, l_int32 dist, l_uint32 *pval, l_int32 debug)
pixGetColorNearMaskBoundary()
Definition: pix3.c:1353
PIX * pixMirroredTiling(PIX *pixs, l_int32 w, l_int32 h)
pixMirroredTiling()
Definition: pix3.c:3415
NUMA * pixVarianceByColumn(PIX *pix, BOX *box)
pixVarianceByColumn()
Definition: pix3.c:2919
NUMA * pixCountByColumn(PIX *pix, BOX *box)
pixCountByColumn()
Definition: pix3.c:2097
l_ok pixCombineMaskedGeneral(PIX *pixd, PIX *pixs, PIX *pixm, l_int32 x, l_int32 y)
pixCombineMaskedGeneral()
Definition: pix3.c:501
l_int32 pixCountArbInRect(PIX *pixs, BOX *box, l_int32 val, l_int32 factor, l_int32 *pcount)
pixCountArbInRect()
Definition: pix3.c:3337
l_ok pixZero(PIX *pix, l_int32 *pempty)
pixZero()
Definition: pix3.c:1815
NUMA * pixaCountPixels(PIXA *pixa)
pixaCountPixels()
Definition: pix3.c:1892
NUMA * pixAverageByColumn(PIX *pix, BOX *box, l_int32 type)
pixAverageByColumn()
Definition: pix3.c:2573
PIX * pixInvert(PIX *pixd, PIX *pixs)
pixInvert()
Definition: pix3.c:1509
PIX * pixCopyWithBoxa(PIX *pixs, BOXA *boxa, l_int32 background)
pixCopyWithBoxa()
Definition: pix3.c:759
l_ok pixPaintThroughMask(PIX *pixd, PIX *pixm, l_int32 x, l_int32 y, l_uint32 val)
pixPaintThroughMask()
Definition: pix3.c:626
l_ok pixCountPixels(PIX *pixs, l_int32 *pcount, l_int32 *tab8)
pixCountPixels()
Definition: pix3.c:1937
NUMA * pixAbsDiffByColumn(PIX *pix, BOX *box)
pixAbsDiffByColumn()
Definition: pix3.c:3115
PIX * pixSetUnderTransparency(PIX *pixs, l_uint32 val, l_int32 debug)
pixSetUnderTransparency()
Definition: pix3.c:1208
PIX * pixMakeAlphaFromMask(PIX *pixs, l_int32 dist, BOX **pbox)
pixMakeAlphaFromMask()
Definition: pix3.c:1284
PIX * pixDisplaySelectedPixels(PIX *pixs, PIX *pixm, SEL *sel, l_uint32 val)
pixDisplaySelectedPixels()
Definition: pix3.c:1453
PIX * pixOr(PIX *pixd, PIX *pixs1, PIX *pixs2)
pixOr()
Definition: pix3.c:1560
NUMA * pixCountPixelsByColumn(PIX *pix)
pixCountPixelsByColumn()
Definition: pix3.c:2177
PIX * pixAnd(PIX *pixd, PIX *pixs1, PIX *pixs2)
pixAnd()
Definition: pix3.c:1624
static BOXA * findTileRegionsForSearch(BOX *box, l_int32 w, l_int32 h, l_int32 searchdir, l_int32 mindist, l_int32 tsize, l_int32 ntiles)
findTileRegionsForSearch()
Definition: pix3.c:3625
l_ok pixCountPixelsInRect(PIX *pixs, BOX *box, l_int32 *pcount, l_int32 *tab8)
pixCountPixelsInRect()
Definition: pix3.c:2001
l_ok pixSetMaskedGeneral(PIX *pixd, PIX *pixm, l_uint32 val, l_int32 x, l_int32 y)
pixSetMaskedGeneral()
Definition: pix3.c:302
l_ok pixAbsDiffInRect(PIX *pix, BOX *box, l_int32 dir, l_float32 *pabsdiff)
pixAbsDiffInRect()
Definition: pix3.c:3178
l_ok pixPaintSelfThroughMask(PIX *pixd, PIX *pixm, l_int32 x, l_int32 y, l_int32 searchdir, l_int32 mindist, l_int32 tilesize, l_int32 ntiles, l_int32 distblend)
pixPaintSelfThroughMask()
Definition: pix3.c:848
l_ok pixAverageInRectRGB(PIX *pixs, PIX *pixm, BOX *box, l_int32 subsamp, l_uint32 *pave)
pixAverageInRectRGB()
Definition: pix3.c:2767
l_ok pixCountPixelsInRow(PIX *pix, l_int32 row, l_int32 *pcount, l_int32 *tab8)
pixCountPixelsInRow()
Definition: pix3.c:2218
l_ok pixAverageInRect(PIX *pixs, PIX *pixm, BOX *box, l_int32 minval, l_int32 maxval, l_int32 subsamp, l_float32 *pave)
pixAverageInRect()
Definition: pix3.c:2660
l_ok pixSetMasked(PIX *pixd, PIX *pixm, l_uint32 val)
pixSetMasked()
Definition: pix3.c:163
NUMA * pixGetMomentByColumn(PIX *pix, l_int32 order)
pixGetMomentByColumn()
Definition: pix3.c:2281
l_int32 * makePixelSumTab8(void)
makePixelSumTab8()
Definition: pix3.c:2411
PIX * pixXor(PIX *pixd, PIX *pixs1, PIX *pixs2)
pixXor()
Definition: pix3.c:1688
l_int32 * makePixelCentroidTab8(void)
makePixelCentroidTab8()
Definition: pix3.c:2451
PIX * pixMakeMaskFromVal(PIX *pixs, l_int32 val)
pixMakeMaskFromVal()
Definition: pix3.c:1005
l_ok pixForegroundFraction(PIX *pix, l_float32 *pfract)
pixForegroundFraction()
Definition: pix3.c:1865
l_ok pixCombineMasked(PIX *pixd, PIX *pixs, PIX *pixm)
pixCombineMasked()
Definition: pix3.c:382
NUMA * pixCountPixelsByRow(PIX *pix, l_int32 *tab8)
pixCountPixelsByRow()
Definition: pix3.c:2143
NUMA * pixCountByRow(PIX *pix, BOX *box)
pixCountByRow()
Definition: pix3.c:2045
PIX * pixSubtract(PIX *pixd, PIX *pixs1, PIX *pixs2)
pixSubtract()
Definition: pix3.c:1753
l_ok pixVarianceInRect(PIX *pix, BOX *box, l_float32 *prootvar)
pixVarianceInRect()
Definition: pix3.c:2977
l_ok pixThresholdPixelSum(PIX *pix, l_int32 thresh, l_int32 *pabove, l_int32 *tab8)
pixThresholdPixelSum()
Definition: pix3.c:2339
PIX * pixMakeMaskFromLUT(PIX *pixs, l_int32 *tab)
pixMakeMaskFromLUT()
Definition: pix3.c:1062
l_ok pixFindRepCloseTile(PIX *pixs, BOX *box, l_int32 searchdir, l_int32 mindist, l_int32 tsize, l_int32 ntiles, BOX **pboxtile, l_int32 debug)
pixFindRepCloseTile()
Definition: pix3.c:3490
PIX * pixMakeArbMaskFromRGB(PIX *pixs, l_float32 rc, l_float32 gc, l_float32 bc, l_float32 thresh)
pixMakeArbMaskFromRGB()
Definition: pix3.c:1131
NUMA * pixAbsDiffByRow(PIX *pix, BOX *box)
pixAbsDiffByRow()
Definition: pix3.c:3054
NUMA * pixAverageByRow(PIX *pix, BOX *box, l_int32 type)
pixAverageByRow()
Definition: pix3.c:2504
l_ok pixAbsDiffOnLine(PIX *pix, l_int32 x1, l_int32 y1, l_int32 x2, l_int32 y2, l_float32 *pabsdiff)
pixAbsDiffOnLine()
Definition: pix3.c:3255
l_ok pixGetAverageMasked(PIX *pixs, PIX *pixm, l_int32 x, l_int32 y, l_int32 factor, l_int32 type, l_float32 *pval)
pixGetAverageMasked()
Definition: pix4.c:1526
l_ok pixGetAverageMaskedRGB(PIX *pixs, PIX *pixm, l_int32 x, l_int32 y, l_int32 factor, l_int32 type, l_float32 *prval, l_float32 *pgval, l_float32 *pbval)
pixGetAverageMaskedRGB()
Definition: pix4.c:1424
PIX * pixClipRectangle(PIX *pixs, BOX *box, BOX **pboxc)
pixClipRectangle()
Definition: pix5.c:1026
l_ok pixClipToForeground(PIX *pixs, PIX **ppixd, BOX **pbox)
pixClipToForeground()
Definition: pix5.c:1784
PIXA * pixClipRectangles(PIX *pixs, BOXA *boxa)
pixClipRectangles()
Definition: pix5.c:960
#define PIX_MASK
Definition: pix.h:337
#define PIX_DST
Definition: pix.h:331
@ L_ALPHA_CHANNEL
Definition: pix.h:207
@ L_HORIZONTAL_LINE
Definition: pix.h:1013
@ L_VERTICAL_LINE
Definition: pix.h:1015
@ L_COPY
Definition: pix.h:712
@ L_CLONE
Definition: pix.h:713
@ L_NOCOPY
Definition: pix.h:710
@ L_INSERT
Definition: pix.h:711
#define PIX_PAINT
Definition: pix.h:336
@ L_SET_WHITE
Definition: pix.h:906
@ L_SET_BLACK
Definition: pix.h:907
@ L_BLACK_IS_MAX
Definition: pix.h:925
@ L_WHITE_IS_MAX
Definition: pix.h:924
#define PIX_SRC
Definition: pix.h:330
#define PIX_NOT(op)
Definition: pix.h:332
@ L_MEAN_ABSVAL
Definition: pix.h:968
@ L_STANDARD_DEVIATION
Definition: pix.h:973
void pixaDestroy(PIXA **ppixa)
pixaDestroy()
Definition: pixabasic.c:412
BOX * pixaGetBox(PIXA *pixa, l_int32 index, l_int32 accesstype)
pixaGetBox()
Definition: pixabasic.c:816
l_int32 pixaGetCount(PIXA *pixa)
pixaGetCount()
Definition: pixabasic.c:650
l_ok pixaGetBoxGeometry(PIXA *pixa, l_int32 index, l_int32 *px, l_int32 *py, l_int32 *pw, l_int32 *ph)
pixaGetBoxGeometry()
Definition: pixabasic.c:854
PIX * pixaGetPix(PIXA *pixa, l_int32 index, l_int32 accesstype)
pixaGetPix()
Definition: pixabasic.c:691
l_ok pixMultConstantGray(PIX *pixs, l_float32 val)
pixMultConstantGray()
Definition: pixarith.c:190
PIX * pixUnpackBinary(PIX *pixs, l_int32 depth, l_int32 invert)
pixUnpackBinary()
Definition: pixconv.c:1913
PIX * pixConvertRGBToGray(PIX *pixs, l_float32 rwt, l_float32 gwt, l_float32 bwt)
pixConvertRGBToGray()
Definition: pixconv.c:827
PIX * pixConvert1To8(PIX *pixd, PIX *pixs, l_uint8 val0, l_uint8 val1)
pixConvert1To8()
Definition: pixconv.c:2401
PIX * pixConvertRGBToGrayArb(PIX *pixs, l_float32 rc, l_float32 gc, l_float32 bc)
pixConvertRGBToGrayArb()
Definition: pixconv.c:1128
PIX * pixConvertTo32(PIX *pixs)
pixConvertTo32()
Definition: pixconv.c:3332
l_ok pixRasterop(PIX *pixd, l_int32 dx, l_int32 dy, l_int32 dw, l_int32 dh, l_int32 op, PIX *pixs, l_int32 sx, l_int32 sy)
pixRasterop()
Definition: rop.c:204
PIX * pixFlipLR(PIX *pixd, PIX *pixs)
pixFlipLR()
Definition: rotateorth.c:427
PIX * pixFlipTB(PIX *pixd, PIX *pixs)
pixFlipTB()
Definition: rotateorth.c:605
PIX * pixDistanceFunction(PIX *pixs, l_int32 connectivity, l_int32 outdepth, l_int32 boundcond)
pixDistanceFunction()
Definition: seedfill.c:2535
Definition: pix.h:481
Definition: pix.h:492
Definition: array.h:71
Definition: pix.h:139
Definition: pix.h:456
void lept_stderr(const char *fmt,...)
lept_stderr()
Definition: utils1.c:306
l_int32 lept_rmdir(const char *subdir)
lept_rmdir()
Definition: utils2.c:2295
l_int32 lept_mkdir(const char *subdir)
lept_mkdir()
Definition: utils2.c:2218