Leptonica  1.77.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 
107 #include <string.h>
108 #include <math.h>
109 #include "allheaders.h"
110 
111 static BOXA *findTileRegionsForSearch(BOX *box, l_int32 w, l_int32 h,
112  l_int32 searchdir, l_int32 mindist,
113  l_int32 tsize, l_int32 ntiles);
114 
115 #ifndef NO_CONSOLE_IO
116 #define EQUAL_SIZE_WARNING 0
117 #endif /* ~NO_CONSOLE_IO */
118 
119 
120 /*-------------------------------------------------------------*
121  * Masked operations *
122  *-------------------------------------------------------------*/
154 l_ok
156  PIX *pixm,
157  l_uint32 val)
158 {
159 l_int32 wd, hd, wm, hm, w, h, d, wpld, wplm;
160 l_int32 i, j, rval, gval, bval;
161 l_uint32 *datad, *datam, *lined, *linem;
162 
163  PROCNAME("pixSetMasked");
164 
165  if (!pixd)
166  return ERROR_INT("pixd not defined", procName, 1);
167  if (!pixm) {
168  L_WARNING("no mask; nothing to do\n", procName);
169  return 0;
170  }
171  if (pixGetColormap(pixd)) {
172  extractRGBValues(val, &rval, &gval, &bval);
173  return pixSetMaskedCmap(pixd, pixm, 0, 0, rval, gval, bval);
174  }
175 
176  if (pixGetDepth(pixm) != 1)
177  return ERROR_INT("pixm not 1 bpp", procName, 1);
178  d = pixGetDepth(pixd);
179  if (d == 1)
180  val &= 1;
181  else if (d == 2)
182  val &= 3;
183  else if (d == 4)
184  val &= 0x0f;
185  else if (d == 8)
186  val &= 0xff;
187  else if (d == 16)
188  val &= 0xffff;
189  else if (d != 32)
190  return ERROR_INT("pixd not 1, 2, 4, 8, 16 or 32 bpp", procName, 1);
191  pixGetDimensions(pixm, &wm, &hm, NULL);
192 
193  /* If d == 1, use rasterop; it's about 25x faster */
194  if (d == 1) {
195  if (val == 0) {
196  PIX *pixmi = pixInvert(NULL, pixm);
197  pixRasterop(pixd, 0, 0, wm, hm, PIX_MASK, pixmi, 0, 0);
198  pixDestroy(&pixmi);
199  } else { /* val == 1 */
200  pixRasterop(pixd, 0, 0, wm, hm, PIX_PAINT, pixm, 0, 0);
201  }
202  return 0;
203  }
204 
205  /* For d < 32, use rasterop for val == 0 (black); ~3x faster. */
206  if (d < 32 && val == 0) {
207  PIX *pixmd = pixUnpackBinary(pixm, d, 1);
208  pixRasterop(pixd, 0, 0, wm, hm, PIX_MASK, pixmd, 0, 0);
209  pixDestroy(&pixmd);
210  return 0;
211  }
212 
213  /* For d < 32, use rasterop for val == maxval (white); ~3x faster. */
214  if (d < 32 && val == ((1 << d) - 1)) {
215  PIX *pixmd = pixUnpackBinary(pixm, d, 0);
216  pixRasterop(pixd, 0, 0, wm, hm, PIX_PAINT, pixmd, 0, 0);
217  pixDestroy(&pixmd);
218  return 0;
219  }
220 
221  pixGetDimensions(pixd, &wd, &hd, &d);
222  w = L_MIN(wd, wm);
223  h = L_MIN(hd, hm);
224  if (L_ABS(wd - wm) > 7 || L_ABS(hd - hm) > 7) /* allow a small tolerance */
225  L_WARNING("pixd and pixm sizes differ\n", procName);
226 
227  datad = pixGetData(pixd);
228  datam = pixGetData(pixm);
229  wpld = pixGetWpl(pixd);
230  wplm = pixGetWpl(pixm);
231  for (i = 0; i < h; i++) {
232  lined = datad + i * wpld;
233  linem = datam + i * wplm;
234  for (j = 0; j < w; j++) {
235  if (GET_DATA_BIT(linem, j)) {
236  switch(d)
237  {
238  case 2:
239  SET_DATA_DIBIT(lined, j, val);
240  break;
241  case 4:
242  SET_DATA_QBIT(lined, j, val);
243  break;
244  case 8:
245  SET_DATA_BYTE(lined, j, val);
246  break;
247  case 16:
248  SET_DATA_TWO_BYTES(lined, j, val);
249  break;
250  case 32:
251  *(lined + j) = val;
252  break;
253  default:
254  return ERROR_INT("shouldn't get here", procName, 1);
255  }
256  }
257  }
258  }
259 
260  return 0;
261 }
262 
263 
293 l_ok
295  PIX *pixm,
296  l_uint32 val,
297  l_int32 x,
298  l_int32 y)
299 {
300 l_int32 wm, hm, d;
301 PIX *pixmu, *pixc;
302 
303  PROCNAME("pixSetMaskedGeneral");
304 
305  if (!pixd)
306  return ERROR_INT("pixd not defined", procName, 1);
307  if (!pixm) /* nothing to do */
308  return 0;
309 
310  d = pixGetDepth(pixd);
311  if (d != 8 && d != 16 && d != 32)
312  return ERROR_INT("pixd not 8, 16 or 32 bpp", procName, 1);
313  if (pixGetDepth(pixm) != 1)
314  return ERROR_INT("pixm not 1 bpp", procName, 1);
315 
316  /* Unpack binary to depth d, with inversion: 1 --> 0, 0 --> 0xff... */
317  if ((pixmu = pixUnpackBinary(pixm, d, 1)) == NULL)
318  return ERROR_INT("pixmu not made", procName, 1);
319 
320  /* Clear stenciled pixels in pixd */
321  pixGetDimensions(pixm, &wm, &hm, NULL);
322  pixRasterop(pixd, x, y, wm, hm, PIX_SRC & PIX_DST, pixmu, 0, 0);
323 
324  /* Generate image with requisite color */
325  if ((pixc = pixCreateTemplate(pixmu)) == NULL) {
326  pixDestroy(&pixmu);
327  return ERROR_INT("pixc not made", procName, 1);
328  }
329  pixSetAllArbitrary(pixc, val);
330 
331  /* Invert stencil mask, and paint color color into stencil */
332  pixInvert(pixmu, pixmu);
333  pixAnd(pixmu, pixmu, pixc);
334 
335  /* Finally, repaint stenciled pixels, with val, in pixd */
336  pixRasterop(pixd, x, y, wm, hm, PIX_SRC | PIX_DST, pixmu, 0, 0);
337 
338  pixDestroy(&pixmu);
339  pixDestroy(&pixc);
340  return 0;
341 }
342 
343 
373 l_ok
375  PIX *pixs,
376  PIX *pixm)
377 {
378 l_int32 w, h, d, ws, hs, ds, wm, hm, dm, wmin, hmin;
379 l_int32 wpl, wpls, wplm, i, j, val;
380 l_uint32 *data, *datas, *datam, *line, *lines, *linem;
381 PIX *pixt;
382 
383  PROCNAME("pixCombineMasked");
384 
385  if (!pixm) /* nothing to do */
386  return 0;
387  if (!pixd)
388  return ERROR_INT("pixd not defined", procName, 1);
389  if (!pixs)
390  return ERROR_INT("pixs not defined", procName, 1);
391  pixGetDimensions(pixd, &w, &h, &d);
392  pixGetDimensions(pixs, &ws, &hs, &ds);
393  pixGetDimensions(pixm, &wm, &hm, &dm);
394  if (d != ds)
395  return ERROR_INT("pixs and pixd depths differ", procName, 1);
396  if (dm != 1)
397  return ERROR_INT("pixm not 1 bpp", procName, 1);
398  if (d != 1 && d != 8 && d != 32)
399  return ERROR_INT("pixd not 1, 8 or 32 bpp", procName, 1);
400  if (pixGetColormap(pixd) || pixGetColormap(pixs))
401  return ERROR_INT("pixs and/or pixd is cmapped", procName, 1);
402 
403  /* For d = 1, use rasterop. pixt is the part from pixs, under
404  * the fg of pixm, that is to be combined with pixd. We also
405  * use pixt to remove all fg of pixd that is under the fg of pixm.
406  * Then pixt and pixd are combined by ORing. */
407  wmin = L_MIN(w, L_MIN(ws, wm));
408  hmin = L_MIN(h, L_MIN(hs, hm));
409  if (d == 1) {
410  pixt = pixAnd(NULL, pixs, pixm);
411  pixRasterop(pixd, 0, 0, wmin, hmin, PIX_DST & PIX_NOT(PIX_SRC),
412  pixm, 0, 0);
413  pixRasterop(pixd, 0, 0, wmin, hmin, PIX_SRC | PIX_DST, pixt, 0, 0);
414  pixDestroy(&pixt);
415  return 0;
416  }
417 
418  data = pixGetData(pixd);
419  datas = pixGetData(pixs);
420  datam = pixGetData(pixm);
421  wpl = pixGetWpl(pixd);
422  wpls = pixGetWpl(pixs);
423  wplm = pixGetWpl(pixm);
424  if (d == 8) {
425  for (i = 0; i < hmin; i++) {
426  line = data + i * wpl;
427  lines = datas + i * wpls;
428  linem = datam + i * wplm;
429  for (j = 0; j < wmin; j++) {
430  if (GET_DATA_BIT(linem, j)) {
431  val = GET_DATA_BYTE(lines, j);
432  SET_DATA_BYTE(line, j, val);
433  }
434  }
435  }
436  } else { /* d == 32 */
437  for (i = 0; i < hmin; i++) {
438  line = data + i * wpl;
439  lines = datas + i * wpls;
440  linem = datam + i * wplm;
441  for (j = 0; j < wmin; j++) {
442  if (GET_DATA_BIT(linem, j))
443  line[j] = lines[j];
444  }
445  }
446  }
447 
448  return 0;
449 }
450 
451 
492 l_ok
494  PIX *pixs,
495  PIX *pixm,
496  l_int32 x,
497  l_int32 y)
498 {
499 l_int32 d, w, h, ws, hs, ds, wm, hm, dm, wmin, hmin;
500 l_int32 wpl, wpls, wplm, i, j, val;
501 l_uint32 *data, *datas, *datam, *line, *lines, *linem;
502 PIX *pixt;
503 
504  PROCNAME("pixCombineMaskedGeneral");
505 
506  if (!pixm) /* nothing to do */
507  return 0;
508  if (!pixd)
509  return ERROR_INT("pixd not defined", procName, 1);
510  if (!pixs)
511  return ERROR_INT("pixs not defined", procName, 1);
512  pixGetDimensions(pixd, &w, &h, &d);
513  pixGetDimensions(pixs, &ws, &hs, &ds);
514  pixGetDimensions(pixm, &wm, &hm, &dm);
515  if (d != ds)
516  return ERROR_INT("pixs and pixd depths differ", procName, 1);
517  if (dm != 1)
518  return ERROR_INT("pixm not 1 bpp", procName, 1);
519  if (d != 1 && d != 8 && d != 32)
520  return ERROR_INT("pixd not 1, 8 or 32 bpp", procName, 1);
521  if (pixGetColormap(pixd) || pixGetColormap(pixs))
522  return ERROR_INT("pixs and/or pixd is cmapped", procName, 1);
523 
524  /* For d = 1, use rasterop. pixt is the part from pixs, under
525  * the fg of pixm, that is to be combined with pixd. We also
526  * use pixt to remove all fg of pixd that is under the fg of pixm.
527  * Then pixt and pixd are combined by ORing. */
528  wmin = L_MIN(ws, wm);
529  hmin = L_MIN(hs, hm);
530  if (d == 1) {
531  pixt = pixAnd(NULL, pixs, pixm);
532  pixRasterop(pixd, x, y, wmin, hmin, PIX_DST & PIX_NOT(PIX_SRC),
533  pixm, 0, 0);
534  pixRasterop(pixd, x, y, wmin, hmin, PIX_SRC | PIX_DST, pixt, 0, 0);
535  pixDestroy(&pixt);
536  return 0;
537  }
538 
539  wpl = pixGetWpl(pixd);
540  data = pixGetData(pixd);
541  wpls = pixGetWpl(pixs);
542  datas = pixGetData(pixs);
543  wplm = pixGetWpl(pixm);
544  datam = pixGetData(pixm);
545 
546  for (i = 0; i < hmin; i++) {
547  if (y + i < 0 || y + i >= h) continue;
548  line = data + (y + i) * wpl;
549  lines = datas + i * wpls;
550  linem = datam + i * wplm;
551  for (j = 0; j < wmin; j++) {
552  if (x + j < 0 || x + j >= w) continue;
553  if (GET_DATA_BIT(linem, j)) {
554  switch (d)
555  {
556  case 8:
557  val = GET_DATA_BYTE(lines, j);
558  SET_DATA_BYTE(line, x + j, val);
559  break;
560  case 32:
561  *(line + x + j) = *(lines + j);
562  break;
563  default:
564  return ERROR_INT("shouldn't get here", procName, 1);
565  }
566  }
567  }
568  }
569 
570  return 0;
571 }
572 
573 
617 l_ok
619  PIX *pixm,
620  l_int32 x,
621  l_int32 y,
622  l_uint32 val)
623 {
624 l_int32 d, w, h, wm, hm, wpl, wplm, i, j, rval, gval, bval;
625 l_uint32 *data, *datam, *line, *linem;
626 
627  PROCNAME("pixPaintThroughMask");
628 
629  if (!pixm) /* nothing to do */
630  return 0;
631  if (!pixd)
632  return ERROR_INT("pixd not defined", procName, 1);
633  if (pixGetColormap(pixd)) {
634  extractRGBValues(val, &rval, &gval, &bval);
635  return pixSetMaskedCmap(pixd, pixm, x, y, rval, gval, bval);
636  }
637 
638  if (pixGetDepth(pixm) != 1)
639  return ERROR_INT("pixm not 1 bpp", procName, 1);
640  d = pixGetDepth(pixd);
641  if (d == 1)
642  val &= 1;
643  else if (d == 2)
644  val &= 3;
645  else if (d == 4)
646  val &= 0x0f;
647  else if (d == 8)
648  val &= 0xff;
649  else if (d == 16)
650  val &= 0xffff;
651  else if (d != 32)
652  return ERROR_INT("pixd not 1, 2, 4, 8, 16 or 32 bpp", procName, 1);
653  pixGetDimensions(pixm, &wm, &hm, NULL);
654 
655  /* If d == 1, use rasterop; it's about 25x faster. */
656  if (d == 1) {
657  if (val == 0) {
658  PIX *pixmi = pixInvert(NULL, pixm);
659  pixRasterop(pixd, x, y, wm, hm, PIX_MASK, pixmi, 0, 0);
660  pixDestroy(&pixmi);
661  } else { /* val == 1 */
662  pixRasterop(pixd, x, y, wm, hm, PIX_PAINT, pixm, 0, 0);
663  }
664  return 0;
665  }
666 
667  /* For d < 32, use rasterop if val == 0 (black); ~3x faster. */
668  if (d < 32 && val == 0) {
669  PIX *pixmd = pixUnpackBinary(pixm, d, 1);
670  pixRasterop(pixd, x, y, wm, hm, PIX_MASK, pixmd, 0, 0);
671  pixDestroy(&pixmd);
672  return 0;
673  }
674 
675  /* For d < 32, use rasterop if val == maxval (white); ~3x faster. */
676  if (d < 32 && val == ((1 << d) - 1)) {
677  PIX *pixmd = pixUnpackBinary(pixm, d, 0);
678  pixRasterop(pixd, x, y, wm, hm, PIX_PAINT, pixmd, 0, 0);
679  pixDestroy(&pixmd);
680  return 0;
681  }
682 
683  /* All other cases */
684  pixGetDimensions(pixd, &w, &h, NULL);
685  wpl = pixGetWpl(pixd);
686  data = pixGetData(pixd);
687  wplm = pixGetWpl(pixm);
688  datam = pixGetData(pixm);
689  for (i = 0; i < hm; i++) {
690  if (y + i < 0 || y + i >= h) continue;
691  line = data + (y + i) * wpl;
692  linem = datam + i * wplm;
693  for (j = 0; j < wm; j++) {
694  if (x + j < 0 || x + j >= w) continue;
695  if (GET_DATA_BIT(linem, j)) {
696  switch (d)
697  {
698  case 2:
699  SET_DATA_DIBIT(line, x + j, val);
700  break;
701  case 4:
702  SET_DATA_QBIT(line, x + j, val);
703  break;
704  case 8:
705  SET_DATA_BYTE(line, x + j, val);
706  break;
707  case 16:
708  SET_DATA_TWO_BYTES(line, x + j, val);
709  break;
710  case 32:
711  *(line + x + j) = val;
712  break;
713  default:
714  return ERROR_INT("shouldn't get here", procName, 1);
715  }
716  }
717  }
718  }
719 
720  return 0;
721 }
722 
723 
785 l_ok
787  PIX *pixm,
788  l_int32 x,
789  l_int32 y,
790  l_int32 searchdir,
791  l_int32 mindist,
792  l_int32 tilesize,
793  l_int32 ntiles,
794  l_int32 distblend)
795 {
796 l_int32 w, h, d, wm, hm, dm, i, n, bx, by, bw, bh, edgeblend, retval, minside;
797 l_uint32 pixval;
798 BOX *box, *boxv, *boxh;
799 BOXA *boxa;
800 PIX *pixf, *pixv, *pixh, *pix1, *pix2, *pix3, *pix4, *pix5;
801 PIXA *pixa;
802 
803  PROCNAME("pixPaintSelfThroughMask");
804 
805  if (!pixm) /* nothing to do */
806  return 0;
807  if (!pixd)
808  return ERROR_INT("pixd not defined", procName, 1);
809  if (pixGetColormap(pixd) != NULL)
810  return ERROR_INT("pixd has colormap", procName, 1);
811  pixGetDimensions(pixd, &w, &h, &d);
812  if (d != 8 && d != 32)
813  return ERROR_INT("pixd not 8 or 32 bpp", procName, 1);
814  pixGetDimensions(pixm, &wm, &hm, &dm);
815  if (dm != 1)
816  return ERROR_INT("pixm not 1 bpp", procName, 1);
817  if (x < 0 || y < 0)
818  return ERROR_INT("x and y must be non-negative", procName, 1);
819  if (searchdir != L_HORIZ && searchdir != L_VERT &&
820  searchdir != L_BOTH_DIRECTIONS)
821  return ERROR_INT("invalid searchdir", procName, 1);
822  if (tilesize < 2)
823  return ERROR_INT("tilesize must be >= 2", procName, 1);
824  if (distblend < 0)
825  return ERROR_INT("distblend must be >= 0", procName, 1);
826 
827  /* Embed mask in full sized mask */
828  if (wm < w || hm < h) {
829  pixf = pixCreate(w, h, 1);
830  pixRasterop(pixf, x, y, wm, hm, PIX_SRC, pixm, 0, 0);
831  } else {
832  pixf = pixCopy(NULL, pixm);
833  }
834 
835  /* Get connected components of mask */
836  boxa = pixConnComp(pixf, &pixa, 8);
837  if ((n = pixaGetCount(pixa)) == 0) {
838  L_WARNING("no fg in mask\n", procName);
839  pixDestroy(&pixf);
840  pixaDestroy(&pixa);
841  boxaDestroy(&boxa);
842  return 1;
843  }
844  boxaDestroy(&boxa);
845 
846  /* For each c.c., generate one or two representative tiles for
847  * texturizing and apply through the mask. The input 'tilesize'
848  * is the requested value. Note that if there is exactly one
849  * component, and blending at the edge is requested, an alpha mask
850  * is generated, which is larger than the bounding box of the c.c. */
851  edgeblend = (n == 1 && distblend > 0) ? 1 : 0;
852  if (distblend > 0 && n > 1)
853  L_WARNING("%d components; can not blend at edges\n", procName, n);
854  retval = 0;
855  for (i = 0; i < n; i++) {
856  if (edgeblend) {
857  pix1 = pixMakeAlphaFromMask(pixf, distblend, &box);
858  } else {
859  pix1 = pixaGetPix(pixa, i, L_CLONE);
860  box = pixaGetBox(pixa, i, L_CLONE);
861  }
862  boxGetGeometry(box, &bx, &by, &bw, &bh);
863  minside = L_MIN(bw, bh);
864 
865  boxh = boxv = NULL;
866  if (searchdir == L_HORIZ || searchdir == L_BOTH_DIRECTIONS) {
867  pixFindRepCloseTile(pixd, box, L_HORIZ, mindist,
868  L_MIN(minside, tilesize), ntiles, &boxh, 0);
869  }
870  if (searchdir == L_VERT || searchdir == L_BOTH_DIRECTIONS) {
871  pixFindRepCloseTile(pixd, box, L_VERT, mindist,
872  L_MIN(minside, tilesize), ntiles, &boxv, 0);
873  }
874  if (!boxh && !boxv) {
875  L_WARNING("tile region not selected; paint color near boundary\n",
876  procName);
877  pixDestroy(&pix1);
878  pix1 = pixaGetPix(pixa, i, L_CLONE);
879  pixaGetBoxGeometry(pixa, i, &bx, &by, NULL, NULL);
880  retval = pixGetColorNearMaskBoundary(pixd, pixm, box, distblend,
881  &pixval, 0);
882  pixSetMaskedGeneral(pixd, pix1, pixval, bx, by);
883  pixDestroy(&pix1);
884  boxDestroy(&box);
885  continue;
886  }
887 
888  /* Extract the selected squares from pixd */
889  pixh = (boxh) ? pixClipRectangle(pixd, boxh, NULL) : NULL;
890  pixv = (boxv) ? pixClipRectangle(pixd, boxv, NULL) : NULL;
891  if (pixh && pixv)
892  pix2 = pixBlend(pixh, pixv, 0, 0, 0.5);
893  else if (pixh)
894  pix2 = pixClone(pixh);
895  else /* pixv */
896  pix2 = pixClone(pixv);
897  pixDestroy(&pixh);
898  pixDestroy(&pixv);
899  boxDestroy(&boxh);
900  boxDestroy(&boxv);
901 
902  /* Generate an image the size of the b.b. of the c.c.,
903  * possibly extended by the blending distance, which
904  * is then either painted through the c.c. mask or
905  * blended using the alpha mask for that c.c. */
906  pix3 = pixMirroredTiling(pix2, bw, bh);
907  if (edgeblend) {
908  pix4 = pixClipRectangle(pixd, box, NULL);
909  pix5 = pixBlendWithGrayMask(pix4, pix3, pix1, 0, 0);
910  pixRasterop(pixd, bx, by, bw, bh, PIX_SRC, pix5, 0, 0);
911  pixDestroy(&pix4);
912  pixDestroy(&pix5);
913  } else {
914  pixCombineMaskedGeneral(pixd, pix3, pix1, bx, by);
915  }
916  pixDestroy(&pix1);
917  pixDestroy(&pix2);
918  pixDestroy(&pix3);
919  boxDestroy(&box);
920  }
921 
922  pixaDestroy(&pixa);
923  pixDestroy(&pixf);
924  return retval;
925 }
926 
927 
942 PIX *
944  l_int32 val)
945 {
946 l_int32 w, h, d, i, j, sval, wpls, wpld;
947 l_uint32 *datas, *datad, *lines, *lined;
948 PIX *pixd;
949 
950  PROCNAME("pixMakeMaskFromVal");
951 
952  if (!pixs)
953  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
954  pixGetDimensions(pixs, &w, &h, &d);
955  if (d != 2 && d != 4 && d != 8)
956  return (PIX *)ERROR_PTR("pix not 2, 4 or 8 bpp", procName, NULL);
957 
958  pixd = pixCreate(w, h, 1);
959  pixCopyResolution(pixd, pixs);
960  pixCopyInputFormat(pixd, pixs);
961  datas = pixGetData(pixs);
962  datad = pixGetData(pixd);
963  wpls = pixGetWpl(pixs);
964  wpld = pixGetWpl(pixd);
965  for (i = 0; i < h; i++) {
966  lines = datas + i * wpls;
967  lined = datad + i * wpld;
968  for (j = 0; j < w; j++) {
969  if (d == 2)
970  sval = GET_DATA_DIBIT(lines, j);
971  else if (d == 4)
972  sval = GET_DATA_QBIT(lines, j);
973  else /* d == 8 */
974  sval = GET_DATA_BYTE(lines, j);
975  if (sval == val)
976  SET_DATA_BIT(lined, j);
977  }
978  }
979 
980  return pixd;
981 }
982 
983 
999 PIX *
1001  l_int32 *tab)
1002 {
1003 l_int32 w, h, d, i, j, val, wpls, wpld;
1004 l_uint32 *datas, *datad, *lines, *lined;
1005 PIX *pixd;
1006 
1007  PROCNAME("pixMakeMaskFromLUT");
1008 
1009  if (!pixs)
1010  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1011  if (!tab)
1012  return (PIX *)ERROR_PTR("tab not defined", procName, NULL);
1013  pixGetDimensions(pixs, &w, &h, &d);
1014  if (d != 2 && d != 4 && d != 8)
1015  return (PIX *)ERROR_PTR("pix not 2, 4 or 8 bpp", procName, NULL);
1016 
1017  pixd = pixCreate(w, h, 1);
1018  pixCopyResolution(pixd, pixs);
1019  pixCopyInputFormat(pixd, pixs);
1020  datas = pixGetData(pixs);
1021  datad = pixGetData(pixd);
1022  wpls = pixGetWpl(pixs);
1023  wpld = pixGetWpl(pixd);
1024  for (i = 0; i < h; i++) {
1025  lines = datas + i * wpls;
1026  lined = datad + i * wpld;
1027  for (j = 0; j < w; j++) {
1028  if (d == 2)
1029  val = GET_DATA_DIBIT(lines, j);
1030  else if (d == 4)
1031  val = GET_DATA_QBIT(lines, j);
1032  else /* d == 8 */
1033  val = GET_DATA_BYTE(lines, j);
1034  if (tab[val] == 1)
1035  SET_DATA_BIT(lined, j);
1036  }
1037  }
1038 
1039  return pixd;
1040 }
1041 
1042 
1068 PIX *
1070  l_float32 rc,
1071  l_float32 gc,
1072  l_float32 bc,
1073  l_float32 thresh)
1074 {
1075 PIX *pix1, *pix2;
1076 
1077  PROCNAME("pixMakeArbMaskFromRGB");
1078 
1079  if (!pixs || pixGetDepth(pixs) != 32)
1080  return (PIX *)ERROR_PTR("pixs undefined or not 32 bpp", procName, NULL);
1081  if (thresh >= 255.0) thresh = 254.0; /* avoid 8 bit overflow */
1082 
1083  if ((pix1 = pixConvertRGBToGrayArb(pixs, rc, gc, bc)) == NULL)
1084  return (PIX *)ERROR_PTR("pix1 not made", procName, NULL);
1085  pix2 = pixThresholdToBinary(pix1, thresh + 1);
1086  pixInvert(pix2, pix2);
1087  pixDestroy(&pix1);
1088  return pix2;
1089 }
1090 
1091 
1145 PIX *
1147  l_uint32 val,
1148  l_int32 debug)
1149 {
1150 PIX *pixg, *pixm, *pixt, *pixd;
1151 
1152  PROCNAME("pixSetUnderTransparency");
1153 
1154  if (!pixs || pixGetDepth(pixs) != 32)
1155  return (PIX *)ERROR_PTR("pixs not defined or not 32 bpp",
1156  procName, NULL);
1157 
1158  if (pixGetSpp(pixs) != 4) {
1159  L_WARNING("no alpha channel; returning a copy\n", procName);
1160  return pixCopy(NULL, pixs);
1161  }
1162 
1163  /* Make a mask from the alpha component with ON pixels
1164  * wherever the alpha component is fully transparent (0).
1165  * The hard way:
1166  * l_int32 *lut = (l_int32 *)LEPT_CALLOC(256, sizeof(l_int32));
1167  * lut[0] = 1;
1168  * pixg = pixGetRGBComponent(pixs, L_ALPHA_CHANNEL);
1169  * pixm = pixMakeMaskFromLUT(pixg, lut);
1170  * LEPT_FREE(lut);
1171  * But there's an easier way to set pixels in a mask where
1172  * the alpha component is 0 ... */
1173  pixg = pixGetRGBComponent(pixs, L_ALPHA_CHANNEL);
1174  pixm = pixThresholdToBinary(pixg, 1);
1175 
1176  if (debug) {
1177  pixt = pixDisplayLayersRGBA(pixs, 0xffffff00, 600);
1178  pixDisplay(pixt, 0, 0);
1179  pixDestroy(&pixt);
1180  }
1181 
1182  pixd = pixCopy(NULL, pixs);
1183  pixSetMasked(pixd, pixm, (val & 0xffffff00));
1184  pixDestroy(&pixg);
1185  pixDestroy(&pixm);
1186  return pixd;
1187 }
1188 
1189 
1221 PIX *
1223  l_int32 dist,
1224  BOX **pbox)
1225 {
1226 l_int32 w, h;
1227 BOX *box1, *box2;
1228 PIX *pix1, *pixd;
1229 
1230  PROCNAME("pixMakeAlphaFromMask");
1231 
1232  if (pbox) *pbox = NULL;
1233  if (!pixs || pixGetDepth(pixs) != 1)
1234  return (PIX *)ERROR_PTR("pixs undefined or not 1 bpp", procName, NULL);
1235  if (dist < 0)
1236  return (PIX *)ERROR_PTR("dist must be >= 0", procName, NULL);
1237 
1238  /* If requested, extract just the region to be affected by the mask */
1239  if (pbox) {
1240  pixClipToForeground(pixs, NULL, &box1);
1241  if (!box1) {
1242  L_WARNING("no ON pixels in mask\n", procName);
1243  return pixCreateTemplate(pixs); /* all background (0) */
1244  }
1245 
1246  boxAdjustSides(box1, box1, -dist, dist, -dist, dist);
1247  pixGetDimensions(pixs, &w, &h, NULL);
1248  box2 = boxClipToRectangle(box1, w, h);
1249  *pbox = box2;
1250  pix1 = pixClipRectangle(pixs, box2, NULL);
1251  boxDestroy(&box1);
1252  } else {
1253  pix1 = pixCopy(NULL, pixs);
1254  }
1255 
1256  if (dist == 0) {
1257  pixd = pixConvert1To8(NULL, pix1, 0, 255);
1258  pixDestroy(&pix1);
1259  return pixd;
1260  }
1261 
1262  /* Blur the boundary of the input mask */
1263  pixInvert(pix1, pix1);
1264  pixd = pixDistanceFunction(pix1, 8, 8, L_BOUNDARY_FG);
1265  pixMultConstantGray(pixd, 256.0 / dist);
1266  pixInvert(pixd, pixd);
1267  pixDestroy(&pix1);
1268  return pixd;
1269 }
1270 
1271 
1290 l_ok
1292  PIX *pixm,
1293  BOX *box,
1294  l_int32 dist,
1295  l_uint32 *pval,
1296  l_int32 debug)
1297 {
1298 char op[64];
1299 l_int32 empty, bx, by;
1300 l_float32 rval, gval, bval;
1301 BOX *box1, *box2;
1302 PIX *pix1, *pix2, *pix3;
1303 
1304  PROCNAME("pixGetColorNearMaskBoundary");
1305 
1306  if (!pval)
1307  return ERROR_INT("&pval not defined", procName, 1);
1308  *pval = 0xffffff00; /* white */
1309  if (!pixs || pixGetDepth(pixs) != 32)
1310  return ERROR_INT("pixs undefined or not 32 bpp", procName, 1);
1311  if (!pixm || pixGetDepth(pixm) != 1)
1312  return ERROR_INT("pixm undefined or not 1 bpp", procName, 1);
1313  if (!box)
1314  return ERROR_INT("box not defined", procName, 1);
1315  if (dist < 0)
1316  return ERROR_INT("dist must be >= 0", procName, 1);
1317 
1318  /* Clip mask piece, expanded beyond %box by (%dist + 5) on each side.
1319  * box1 is the region requested; box2 is the actual region retrieved,
1320  * which is clipped to %pixm */
1321  box1 = boxAdjustSides(NULL, box, -dist - 5, dist + 5, -dist - 5, dist + 5);
1322  pix1 = pixClipRectangle(pixm, box1, &box2);
1323 
1324  /* Expand FG by %dist into the BG */
1325  if (dist == 0) {
1326  pix2 = pixCopy(NULL, pix1);
1327  } else {
1328  snprintf(op, sizeof(op), "d%d.%d", 2 * dist, 2 * dist);
1329  pix2 = pixMorphSequence(pix1, op, 0);
1330  }
1331 
1332  /* Expand again by 5 pixels on all sides (dilate 11x11) and XOR,
1333  * getting the annulus of FG pixels between %dist and %dist + 5 */
1334  pix3 = pixCopy(NULL, pix2);
1335  pixDilateBrick(pix3, pix3, 11, 11);
1336  pixXor(pix3, pix3, pix2);
1337  pixZero(pix3, &empty);
1338  if (!empty) {
1339  /* Scan the same region in %pixs, to get average under FG in pix3 */
1340  boxGetGeometry(box2, &bx, &by, NULL, NULL);
1341  pixGetAverageMaskedRGB(pixs, pix3, bx, by, 1, L_MEAN_ABSVAL,
1342  &rval, &gval, &bval);
1343  composeRGBPixel((l_int32)(rval + 0.5), (l_int32)(gval + 0.5),
1344  (l_int32)(bval + 0.5), pval);
1345  } else {
1346  L_WARNING("no pixels found\n", procName);
1347  }
1348 
1349  if (debug) {
1350  lept_rmdir("masknear"); /* erase previous images */
1351  lept_mkdir("masknear");
1352  pixWriteDebug("/tmp/masknear/input.png", pix1, IFF_PNG);
1353  pixWriteDebug("/tmp/masknear/adjusted.png", pix2, IFF_PNG);
1354  pixWriteDebug("/tmp/masknear/outerfive.png", pix3, IFF_PNG);
1355  fprintf(stderr, "Input box; with adjusted sides; clipped\n");
1356  boxPrintStreamInfo(stderr, box);
1357  boxPrintStreamInfo(stderr, box1);
1358  boxPrintStreamInfo(stderr, box2);
1359  }
1360 
1361  pixDestroy(&pix1);
1362  pixDestroy(&pix2);
1363  pixDestroy(&pix3);
1364  boxDestroy(&box1);
1365  boxDestroy(&box2);
1366  return 0;
1367 }
1368 
1369 
1370 /*-------------------------------------------------------------*
1371  * One and two-image boolean ops on arbitrary depth images *
1372  *-------------------------------------------------------------*/
1394 PIX *
1396  PIX *pixs)
1397 {
1398  PROCNAME("pixInvert");
1399 
1400  if (!pixs)
1401  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1402 
1403  /* Prepare pixd for in-place operation */
1404  if ((pixd = pixCopy(pixd, pixs)) == NULL)
1405  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
1406 
1407  pixRasterop(pixd, 0, 0, pixGetWidth(pixd), pixGetHeight(pixd),
1408  PIX_NOT(PIX_DST), NULL, 0, 0); /* invert pixd */
1409 
1410  return pixd;
1411 }
1412 
1413 
1445 PIX *
1446 pixOr(PIX *pixd,
1447  PIX *pixs1,
1448  PIX *pixs2)
1449 {
1450  PROCNAME("pixOr");
1451 
1452  if (!pixs1)
1453  return (PIX *)ERROR_PTR("pixs1 not defined", procName, pixd);
1454  if (!pixs2)
1455  return (PIX *)ERROR_PTR("pixs2 not defined", procName, pixd);
1456  if (pixd == pixs2)
1457  return (PIX *)ERROR_PTR("cannot have pixs2 == pixd", procName, pixd);
1458  if (pixGetDepth(pixs1) != pixGetDepth(pixs2))
1459  return (PIX *)ERROR_PTR("depths of pixs* unequal", procName, pixd);
1460 
1461 #if EQUAL_SIZE_WARNING
1462  if (!pixSizesEqual(pixs1, pixs2))
1463  L_WARNING("pixs1 and pixs2 not equal sizes\n", procName);
1464 #endif /* EQUAL_SIZE_WARNING */
1465 
1466  /* Prepare pixd to be a copy of pixs1 */
1467  if ((pixd = pixCopy(pixd, pixs1)) == NULL)
1468  return (PIX *)ERROR_PTR("pixd not made", procName, pixd);
1469 
1470  /* src1 | src2 --> dest */
1471  pixRasterop(pixd, 0, 0, pixGetWidth(pixd), pixGetHeight(pixd),
1472  PIX_SRC | PIX_DST, pixs2, 0, 0);
1473 
1474  return pixd;
1475 }
1476 
1477 
1509 PIX *
1510 pixAnd(PIX *pixd,
1511  PIX *pixs1,
1512  PIX *pixs2)
1513 {
1514  PROCNAME("pixAnd");
1515 
1516  if (!pixs1)
1517  return (PIX *)ERROR_PTR("pixs1 not defined", procName, pixd);
1518  if (!pixs2)
1519  return (PIX *)ERROR_PTR("pixs2 not defined", procName, pixd);
1520  if (pixd == pixs2)
1521  return (PIX *)ERROR_PTR("cannot have pixs2 == pixd", procName, pixd);
1522  if (pixGetDepth(pixs1) != pixGetDepth(pixs2))
1523  return (PIX *)ERROR_PTR("depths of pixs* unequal", procName, pixd);
1524 
1525 #if EQUAL_SIZE_WARNING
1526  if (!pixSizesEqual(pixs1, pixs2))
1527  L_WARNING("pixs1 and pixs2 not equal sizes\n", procName);
1528 #endif /* EQUAL_SIZE_WARNING */
1529 
1530  /* Prepare pixd to be a copy of pixs1 */
1531  if ((pixd = pixCopy(pixd, pixs1)) == NULL)
1532  return (PIX *)ERROR_PTR("pixd not made", procName, pixd);
1533 
1534  /* src1 & src2 --> dest */
1535  pixRasterop(pixd, 0, 0, pixGetWidth(pixd), pixGetHeight(pixd),
1536  PIX_SRC & PIX_DST, pixs2, 0, 0);
1537 
1538  return pixd;
1539 }
1540 
1541 
1573 PIX *
1574 pixXor(PIX *pixd,
1575  PIX *pixs1,
1576  PIX *pixs2)
1577 {
1578  PROCNAME("pixXor");
1579 
1580  if (!pixs1)
1581  return (PIX *)ERROR_PTR("pixs1 not defined", procName, pixd);
1582  if (!pixs2)
1583  return (PIX *)ERROR_PTR("pixs2 not defined", procName, pixd);
1584  if (pixd == pixs2)
1585  return (PIX *)ERROR_PTR("cannot have pixs2 == pixd", procName, pixd);
1586  if (pixGetDepth(pixs1) != pixGetDepth(pixs2))
1587  return (PIX *)ERROR_PTR("depths of pixs* unequal", procName, pixd);
1588 
1589 #if EQUAL_SIZE_WARNING
1590  if (!pixSizesEqual(pixs1, pixs2))
1591  L_WARNING("pixs1 and pixs2 not equal sizes\n", procName);
1592 #endif /* EQUAL_SIZE_WARNING */
1593 
1594  /* Prepare pixd to be a copy of pixs1 */
1595  if ((pixd = pixCopy(pixd, pixs1)) == NULL)
1596  return (PIX *)ERROR_PTR("pixd not made", procName, pixd);
1597 
1598  /* src1 ^ src2 --> dest */
1599  pixRasterop(pixd, 0, 0, pixGetWidth(pixd), pixGetHeight(pixd),
1600  PIX_SRC ^ PIX_DST, pixs2, 0, 0);
1601 
1602  return pixd;
1603 }
1604 
1605 
1638 PIX *
1640  PIX *pixs1,
1641  PIX *pixs2)
1642 {
1643 l_int32 w, h;
1644 
1645  PROCNAME("pixSubtract");
1646 
1647  if (!pixs1)
1648  return (PIX *)ERROR_PTR("pixs1 not defined", procName, pixd);
1649  if (!pixs2)
1650  return (PIX *)ERROR_PTR("pixs2 not defined", procName, pixd);
1651  if (pixGetDepth(pixs1) != pixGetDepth(pixs2))
1652  return (PIX *)ERROR_PTR("depths of pixs* unequal", procName, pixd);
1653 
1654 #if EQUAL_SIZE_WARNING
1655  if (!pixSizesEqual(pixs1, pixs2))
1656  L_WARNING("pixs1 and pixs2 not equal sizes\n", procName);
1657 #endif /* EQUAL_SIZE_WARNING */
1658 
1659  pixGetDimensions(pixs1, &w, &h, NULL);
1660  if (!pixd) {
1661  pixd = pixCopy(NULL, pixs1);
1662  pixRasterop(pixd, 0, 0, w, h, PIX_DST & PIX_NOT(PIX_SRC),
1663  pixs2, 0, 0); /* src1 & (~src2) */
1664  } else if (pixd == pixs1) {
1665  pixRasterop(pixd, 0, 0, w, h, PIX_DST & PIX_NOT(PIX_SRC),
1666  pixs2, 0, 0); /* src1 & (~src2) */
1667  } else if (pixd == pixs2) {
1668  pixRasterop(pixd, 0, 0, w, h, PIX_NOT(PIX_DST) & PIX_SRC,
1669  pixs1, 0, 0); /* src1 & (~src2) */
1670  } else { /* pixd != pixs1 && pixd != pixs2 */
1671  pixCopy(pixd, pixs1); /* sizes pixd to pixs1 if unequal */
1672  pixRasterop(pixd, 0, 0, w, h, PIX_DST & PIX_NOT(PIX_SRC),
1673  pixs2, 0, 0); /* src1 & (~src2) */
1674  }
1675 
1676  return pixd;
1677 }
1678 
1679 
1680 /*-------------------------------------------------------------*
1681  * Pixel counting *
1682  *-------------------------------------------------------------*/
1700 l_ok
1702  l_int32 *pempty)
1703 {
1704 l_int32 w, h, wpl, i, j, fullwords, endbits;
1705 l_uint32 endmask;
1706 l_uint32 *data, *line;
1707 
1708  PROCNAME("pixZero");
1709 
1710  if (!pempty)
1711  return ERROR_INT("&empty not defined", procName, 1);
1712  *pempty = 1;
1713  if (!pix)
1714  return ERROR_INT("pix not defined", procName, 1);
1715 
1716  w = pixGetWidth(pix) * pixGetDepth(pix); /* in bits */
1717  h = pixGetHeight(pix);
1718  wpl = pixGetWpl(pix);
1719  data = pixGetData(pix);
1720  fullwords = w / 32;
1721  endbits = w & 31;
1722  endmask = (endbits == 0) ? 0 : (0xffffffffU << (32 - endbits));
1723 
1724  for (i = 0; i < h; i++) {
1725  line = data + wpl * i;
1726  for (j = 0; j < fullwords; j++)
1727  if (*line++) {
1728  *pempty = 0;
1729  return 0;
1730  }
1731  if (endbits) {
1732  if (*line & endmask) {
1733  *pempty = 0;
1734  return 0;
1735  }
1736  }
1737  }
1738 
1739  return 0;
1740 }
1741 
1742 
1750 l_ok
1752  l_float32 *pfract)
1753 {
1754 l_int32 w, h, count;
1755 
1756  PROCNAME("pixForegroundFraction");
1757 
1758  if (!pfract)
1759  return ERROR_INT("&fract not defined", procName, 1);
1760  *pfract = 0.0;
1761  if (!pix || pixGetDepth(pix) != 1)
1762  return ERROR_INT("pix not defined or not 1 bpp", procName, 1);
1763 
1764  pixCountPixels(pix, &count, NULL);
1765  pixGetDimensions(pix, &w, &h, NULL);
1766  *pfract = (l_float32)count / (l_float32)(w * h);
1767  return 0;
1768 }
1769 
1770 
1777 NUMA *
1779 {
1780 l_int32 d, i, n, count;
1781 l_int32 *tab;
1782 NUMA *na;
1783 PIX *pix;
1784 
1785  PROCNAME("pixaCountPixels");
1786 
1787  if (!pixa)
1788  return (NUMA *)ERROR_PTR("pix not defined", procName, NULL);
1789 
1790  if ((n = pixaGetCount(pixa)) == 0)
1791  return numaCreate(1);
1792 
1793  pix = pixaGetPix(pixa, 0, L_CLONE);
1794  d = pixGetDepth(pix);
1795  pixDestroy(&pix);
1796  if (d != 1)
1797  return (NUMA *)ERROR_PTR("pixa not 1 bpp", procName, NULL);
1798 
1799  if ((na = numaCreate(n)) == NULL)
1800  return (NUMA *)ERROR_PTR("na not made", procName, NULL);
1801  tab = makePixelSumTab8();
1802  for (i = 0; i < n; i++) {
1803  pix = pixaGetPix(pixa, i, L_CLONE);
1804  pixCountPixels(pix, &count, tab);
1805  numaAddNumber(na, count);
1806  pixDestroy(&pix);
1807  }
1808 
1809  LEPT_FREE(tab);
1810  return na;
1811 }
1812 
1813 
1822 l_ok
1824  l_int32 *pcount,
1825  l_int32 *tab8)
1826 {
1827 l_uint32 endmask;
1828 l_int32 w, h, wpl, i, j;
1829 l_int32 fullwords, endbits, sum;
1830 l_int32 *tab;
1831 l_uint32 *data;
1832 
1833  PROCNAME("pixCountPixels");
1834 
1835  if (!pcount)
1836  return ERROR_INT("&count not defined", procName, 1);
1837  *pcount = 0;
1838  if (!pixs || pixGetDepth(pixs) != 1)
1839  return ERROR_INT("pixs not defined or not 1 bpp", procName, 1);
1840 
1841  tab = (tab8) ? tab8 : makePixelSumTab8();
1842  pixGetDimensions(pixs, &w, &h, NULL);
1843  wpl = pixGetWpl(pixs);
1844  data = pixGetData(pixs);
1845  fullwords = w >> 5;
1846  endbits = w & 31;
1847  endmask = (endbits == 0) ? 0 : (0xffffffffU << (32 - endbits));
1848 
1849  sum = 0;
1850  for (i = 0; i < h; i++, data += wpl) {
1851  for (j = 0; j < fullwords; j++) {
1852  l_uint32 word = data[j];
1853  if (word) {
1854  sum += tab[word & 0xff] +
1855  tab[(word >> 8) & 0xff] +
1856  tab[(word >> 16) & 0xff] +
1857  tab[(word >> 24) & 0xff];
1858  }
1859  }
1860  if (endbits) {
1861  l_uint32 word = data[j] & endmask;
1862  if (word) {
1863  sum += tab[word & 0xff] +
1864  tab[(word >> 8) & 0xff] +
1865  tab[(word >> 16) & 0xff] +
1866  tab[(word >> 24) & 0xff];
1867  }
1868  }
1869  }
1870  *pcount = sum;
1871 
1872  if (!tab8) LEPT_FREE(tab);
1873  return 0;
1874 }
1875 
1876 
1886 l_ok
1888  BOX *box,
1889  l_int32 *pcount,
1890  l_int32 *tab8)
1891 {
1892 l_int32 bx, by, bw, bh;
1893 PIX *pix1;
1894 
1895  PROCNAME("pixCountPixelsInRect");
1896 
1897  if (!pcount)
1898  return ERROR_INT("&count not defined", procName, 1);
1899  *pcount = 0;
1900  if (!pixs || pixGetDepth(pixs) != 1)
1901  return ERROR_INT("pixs not defined or not 1 bpp", procName, 1);
1902 
1903  if (box) {
1904  boxGetGeometry(box, &bx, &by, &bw, &bh);
1905  pix1 = pixCreate(bw, bh, 1);
1906  pixRasterop(pix1, 0, 0, bw, bh, PIX_SRC, pixs, bx, by);
1907  pixCountPixels(pix1, pcount, tab8);
1908  pixDestroy(&pix1);
1909  } else {
1910  pixCountPixels(pixs, pcount, tab8);
1911  }
1912 
1913  return 0;
1914 }
1915 
1916 
1930 NUMA *
1932  BOX *box)
1933 {
1934 l_int32 i, j, w, h, wpl, count, xstart, xend, ystart, yend, bw, bh;
1935 l_uint32 *line, *data;
1936 NUMA *na;
1937 
1938  PROCNAME("pixCountByRow");
1939 
1940  if (!pix || pixGetDepth(pix) != 1)
1941  return (NUMA *)ERROR_PTR("pix undefined or not 1 bpp", procName, NULL);
1942  if (!box)
1943  return pixCountPixelsByRow(pix, NULL);
1944 
1945  pixGetDimensions(pix, &w, &h, NULL);
1946  if (boxClipToRectangleParams(box, w, h, &xstart, &ystart, &xend, &yend,
1947  &bw, &bh) == 1)
1948  return (NUMA *)ERROR_PTR("invalid clipping box", procName, NULL);
1949 
1950  if ((na = numaCreate(bh)) == NULL)
1951  return (NUMA *)ERROR_PTR("na not made", procName, NULL);
1952  numaSetParameters(na, ystart, 1);
1953  data = pixGetData(pix);
1954  wpl = pixGetWpl(pix);
1955  for (i = ystart; i < yend; i++) {
1956  count = 0;
1957  line = data + i * wpl;
1958  for (j = xstart; j < xend; j++) {
1959  if (GET_DATA_BIT(line, j))
1960  count++;
1961  }
1962  numaAddNumber(na, count);
1963  }
1964 
1965  return na;
1966 }
1967 
1968 
1982 NUMA *
1984  BOX *box)
1985 {
1986 l_int32 i, j, w, h, wpl, count, xstart, xend, ystart, yend, bw, bh;
1987 l_uint32 *line, *data;
1988 NUMA *na;
1989 
1990  PROCNAME("pixCountByColumn");
1991 
1992  if (!pix || pixGetDepth(pix) != 1)
1993  return (NUMA *)ERROR_PTR("pix undefined or not 1 bpp", procName, NULL);
1994  if (!box)
1995  return pixCountPixelsByColumn(pix);
1996 
1997  pixGetDimensions(pix, &w, &h, NULL);
1998  if (boxClipToRectangleParams(box, w, h, &xstart, &ystart, &xend, &yend,
1999  &bw, &bh) == 1)
2000  return (NUMA *)ERROR_PTR("invalid clipping box", procName, NULL);
2001 
2002  if ((na = numaCreate(bw)) == NULL)
2003  return (NUMA *)ERROR_PTR("na not made", procName, NULL);
2004  numaSetParameters(na, xstart, 1);
2005  data = pixGetData(pix);
2006  wpl = pixGetWpl(pix);
2007  for (j = xstart; j < xend; j++) {
2008  count = 0;
2009  for (i = ystart; i < yend; i++) {
2010  line = data + i * wpl;
2011  if (GET_DATA_BIT(line, j))
2012  count++;
2013  }
2014  numaAddNumber(na, count);
2015  }
2016 
2017  return na;
2018 }
2019 
2020 
2028 NUMA *
2030  l_int32 *tab8)
2031 {
2032 l_int32 h, i, count;
2033 l_int32 *tab;
2034 NUMA *na;
2035 
2036  PROCNAME("pixCountPixelsByRow");
2037 
2038  if (!pix || pixGetDepth(pix) != 1)
2039  return (NUMA *)ERROR_PTR("pix undefined or not 1 bpp", procName, NULL);
2040 
2041  h = pixGetHeight(pix);
2042  if ((na = numaCreate(h)) == NULL)
2043  return (NUMA *)ERROR_PTR("na not made", procName, NULL);
2044 
2045  tab = (tab8) ? tab8 : makePixelSumTab8();
2046  for (i = 0; i < h; i++) {
2047  pixCountPixelsInRow(pix, i, &count, tab);
2048  numaAddNumber(na, count);
2049  }
2050 
2051  if (!tab8) LEPT_FREE(tab);
2052  return na;
2053 }
2054 
2055 
2062 NUMA *
2064 {
2065 l_int32 i, j, w, h, wpl;
2066 l_uint32 *line, *data;
2067 l_float32 *array;
2068 NUMA *na;
2069 
2070  PROCNAME("pixCountPixelsByColumn");
2071 
2072  if (!pix || pixGetDepth(pix) != 1)
2073  return (NUMA *)ERROR_PTR("pix undefined or not 1 bpp", procName, NULL);
2074 
2075  pixGetDimensions(pix, &w, &h, NULL);
2076  if ((na = numaCreate(w)) == NULL)
2077  return (NUMA *)ERROR_PTR("na not made", procName, NULL);
2078  numaSetCount(na, w);
2079  array = numaGetFArray(na, L_NOCOPY);
2080  data = pixGetData(pix);
2081  wpl = pixGetWpl(pix);
2082  for (i = 0; i < h; i++) {
2083  line = data + wpl * i;
2084  for (j = 0; j < w; j++) {
2085  if (GET_DATA_BIT(line, j))
2086  array[j] += 1.0;
2087  }
2088  }
2089 
2090  return na;
2091 }
2092 
2093 
2103 l_ok
2105  l_int32 row,
2106  l_int32 *pcount,
2107  l_int32 *tab8)
2108 {
2109 l_uint32 word, endmask;
2110 l_int32 j, w, h, wpl;
2111 l_int32 fullwords, endbits, sum;
2112 l_int32 *tab;
2113 l_uint32 *line;
2114 
2115  PROCNAME("pixCountPixelsInRow");
2116 
2117  if (!pcount)
2118  return ERROR_INT("&count not defined", procName, 1);
2119  *pcount = 0;
2120  if (!pix || pixGetDepth(pix) != 1)
2121  return ERROR_INT("pix not defined or not 1 bpp", procName, 1);
2122 
2123  pixGetDimensions(pix, &w, &h, NULL);
2124  if (row < 0 || row >= h)
2125  return ERROR_INT("row out of bounds", procName, 1);
2126  wpl = pixGetWpl(pix);
2127  line = pixGetData(pix) + row * wpl;
2128  fullwords = w >> 5;
2129  endbits = w & 31;
2130  endmask = (endbits == 0) ? 0 : (0xffffffffU << (32 - endbits));
2131 
2132  tab = (tab8) ? tab8 : makePixelSumTab8();
2133  sum = 0;
2134  for (j = 0; j < fullwords; j++) {
2135  word = line[j];
2136  if (word) {
2137  sum += tab[word & 0xff] +
2138  tab[(word >> 8) & 0xff] +
2139  tab[(word >> 16) & 0xff] +
2140  tab[(word >> 24) & 0xff];
2141  }
2142  }
2143  if (endbits) {
2144  word = line[j] & endmask;
2145  if (word) {
2146  sum += tab[word & 0xff] +
2147  tab[(word >> 8) & 0xff] +
2148  tab[(word >> 16) & 0xff] +
2149  tab[(word >> 24) & 0xff];
2150  }
2151  }
2152  *pcount = sum;
2153 
2154  if (!tab8) LEPT_FREE(tab);
2155  return 0;
2156 }
2157 
2158 
2166 NUMA *
2168  l_int32 order)
2169 {
2170 l_int32 i, j, w, h, wpl;
2171 l_uint32 *line, *data;
2172 l_float32 *array;
2173 NUMA *na;
2174 
2175  PROCNAME("pixGetMomentByColumn");
2176 
2177  if (!pix || pixGetDepth(pix) != 1)
2178  return (NUMA *)ERROR_PTR("pix undefined or not 1 bpp", procName, NULL);
2179  if (order != 1 && order != 2)
2180  return (NUMA *)ERROR_PTR("order of moment not 1 or 2", procName, NULL);
2181 
2182  pixGetDimensions(pix, &w, &h, NULL);
2183  if ((na = numaCreate(w)) == NULL)
2184  return (NUMA *)ERROR_PTR("na not made", procName, NULL);
2185  numaSetCount(na, w);
2186  array = numaGetFArray(na, L_NOCOPY);
2187  data = pixGetData(pix);
2188  wpl = pixGetWpl(pix);
2189  for (i = 0; i < h; i++) {
2190  line = data + wpl * i;
2191  for (j = 0; j < w; j++) {
2192  if (GET_DATA_BIT(line, j)) {
2193  if (order == 1)
2194  array[j] += i;
2195  else /* order == 2 */
2196  array[j] += i * i;
2197  }
2198  }
2199  }
2200 
2201  return na;
2202 }
2203 
2204 
2224 l_ok
2226  l_int32 thresh,
2227  l_int32 *pabove,
2228  l_int32 *tab8)
2229 {
2230 l_uint32 word, endmask;
2231 l_int32 *tab;
2232 l_int32 w, h, wpl, i, j;
2233 l_int32 fullwords, endbits, sum;
2234 l_uint32 *line, *data;
2235 
2236  PROCNAME("pixThresholdPixelSum");
2237 
2238  if (!pabove)
2239  return ERROR_INT("&above not defined", procName, 1);
2240  *pabove = 0;
2241  if (!pix || pixGetDepth(pix) != 1)
2242  return ERROR_INT("pix not defined or not 1 bpp", procName, 1);
2243 
2244  tab = (tab8) ? tab8 : makePixelSumTab8();
2245  pixGetDimensions(pix, &w, &h, NULL);
2246  wpl = pixGetWpl(pix);
2247  data = pixGetData(pix);
2248  fullwords = w >> 5;
2249  endbits = w & 31;
2250  endmask = 0xffffffff << (32 - endbits);
2251 
2252  sum = 0;
2253  for (i = 0; i < h; i++) {
2254  line = data + wpl * i;
2255  for (j = 0; j < fullwords; j++) {
2256  word = line[j];
2257  if (word) {
2258  sum += tab[word & 0xff] +
2259  tab[(word >> 8) & 0xff] +
2260  tab[(word >> 16) & 0xff] +
2261  tab[(word >> 24) & 0xff];
2262  }
2263  }
2264  if (endbits) {
2265  word = line[j] & endmask;
2266  if (word) {
2267  sum += tab[word & 0xff] +
2268  tab[(word >> 8) & 0xff] +
2269  tab[(word >> 16) & 0xff] +
2270  tab[(word >> 24) & 0xff];
2271  }
2272  }
2273  if (sum > thresh) {
2274  *pabove = 1;
2275  if (!tab8) LEPT_FREE(tab);
2276  return 0;
2277  }
2278  }
2279 
2280  if (!tab8) LEPT_FREE(tab);
2281  return 0;
2282 }
2283 
2284 
2296 l_int32 *
2298 {
2299 l_uint8 byte;
2300 l_int32 i;
2301 l_int32 *tab;
2302 
2303  tab = (l_int32 *)LEPT_CALLOC(256, sizeof(l_int32));
2304  for (i = 0; i < 256; i++) {
2305  byte = (l_uint8)i;
2306  tab[i] = (byte & 0x1) +
2307  ((byte >> 1) & 0x1) +
2308  ((byte >> 2) & 0x1) +
2309  ((byte >> 3) & 0x1) +
2310  ((byte >> 4) & 0x1) +
2311  ((byte >> 5) & 0x1) +
2312  ((byte >> 6) & 0x1) +
2313  ((byte >> 7) & 0x1);
2314  }
2315  return tab;
2316 }
2317 
2318 
2336 l_int32 *
2338 {
2339 l_int32 i;
2340 l_int32 *tab;
2341 
2342  tab = (l_int32 *)LEPT_CALLOC(256, sizeof(l_int32));
2343  tab[0] = 0;
2344  tab[1] = 7;
2345  for (i = 2; i < 4; i++) {
2346  tab[i] = tab[i - 2] + 6;
2347  }
2348  for (i = 4; i < 8; i++) {
2349  tab[i] = tab[i - 4] + 5;
2350  }
2351  for (i = 8; i < 16; i++) {
2352  tab[i] = tab[i - 8] + 4;
2353  }
2354  for (i = 16; i < 32; i++) {
2355  tab[i] = tab[i - 16] + 3;
2356  }
2357  for (i = 32; i < 64; i++) {
2358  tab[i] = tab[i - 32] + 2;
2359  }
2360  for (i = 64; i < 128; i++) {
2361  tab[i] = tab[i - 64] + 1;
2362  }
2363  for (i = 128; i < 256; i++) {
2364  tab[i] = tab[i - 128];
2365  }
2366  return tab;
2367 }
2368 
2369 
2370 /*-------------------------------------------------------------*
2371  * Average of pixel values in gray images *
2372  *-------------------------------------------------------------*/
2389 NUMA *
2391  BOX *box,
2392  l_int32 type)
2393 {
2394 l_int32 i, j, w, h, d, wpl, xstart, xend, ystart, yend, bw, bh;
2395 l_uint32 *line, *data;
2396 l_float64 norm, sum;
2397 NUMA *na;
2398 
2399  PROCNAME("pixAverageByRow");
2400 
2401  if (!pix)
2402  return (NUMA *)ERROR_PTR("pix not defined", procName, NULL);
2403  pixGetDimensions(pix, &w, &h, &d);
2404  if (d != 8 && d != 16)
2405  return (NUMA *)ERROR_PTR("pix not 8 or 16 bpp", procName, NULL);
2406  if (type != L_WHITE_IS_MAX && type != L_BLACK_IS_MAX)
2407  return (NUMA *)ERROR_PTR("invalid type", procName, NULL);
2408  if (pixGetColormap(pix) != NULL)
2409  return (NUMA *)ERROR_PTR("pix colormapped", procName, NULL);
2410 
2411  if (boxClipToRectangleParams(box, w, h, &xstart, &ystart, &xend, &yend,
2412  &bw, &bh) == 1)
2413  return (NUMA *)ERROR_PTR("invalid clipping box", procName, NULL);
2414 
2415  norm = 1. / (l_float32)bw;
2416  if ((na = numaCreate(bh)) == NULL)
2417  return (NUMA *)ERROR_PTR("na not made", procName, NULL);
2418  numaSetParameters(na, ystart, 1);
2419  data = pixGetData(pix);
2420  wpl = pixGetWpl(pix);
2421  for (i = ystart; i < yend; i++) {
2422  sum = 0.0;
2423  line = data + i * wpl;
2424  if (d == 8) {
2425  for (j = xstart; j < xend; j++)
2426  sum += GET_DATA_BYTE(line, j);
2427  if (type == L_BLACK_IS_MAX)
2428  sum = bw * 255 - sum;
2429  } else { /* d == 16 */
2430  for (j = xstart; j < xend; j++)
2431  sum += GET_DATA_TWO_BYTES(line, j);
2432  if (type == L_BLACK_IS_MAX)
2433  sum = bw * 0xffff - sum;
2434  }
2435  numaAddNumber(na, (l_float32)(norm * sum));
2436  }
2437 
2438  return na;
2439 }
2440 
2441 
2458 NUMA *
2460  BOX *box,
2461  l_int32 type)
2462 {
2463 l_int32 i, j, w, h, d, wpl, xstart, xend, ystart, yend, bw, bh;
2464 l_uint32 *line, *data;
2465 l_float32 norm, sum;
2466 NUMA *na;
2467 
2468  PROCNAME("pixAverageByColumn");
2469 
2470  if (!pix)
2471  return (NUMA *)ERROR_PTR("pix not defined", procName, NULL);
2472  pixGetDimensions(pix, &w, &h, &d);
2473 
2474  if (d != 8 && d != 16)
2475  return (NUMA *)ERROR_PTR("pix not 8 or 16 bpp", procName, NULL);
2476  if (type != L_WHITE_IS_MAX && type != L_BLACK_IS_MAX)
2477  return (NUMA *)ERROR_PTR("invalid type", procName, NULL);
2478  if (pixGetColormap(pix) != NULL)
2479  return (NUMA *)ERROR_PTR("pix colormapped", procName, NULL);
2480 
2481  if (boxClipToRectangleParams(box, w, h, &xstart, &ystart, &xend, &yend,
2482  &bw, &bh) == 1)
2483  return (NUMA *)ERROR_PTR("invalid clipping box", procName, NULL);
2484 
2485  if ((na = numaCreate(bw)) == NULL)
2486  return (NUMA *)ERROR_PTR("na not made", procName, NULL);
2487  numaSetParameters(na, xstart, 1);
2488  norm = 1. / (l_float32)bh;
2489  data = pixGetData(pix);
2490  wpl = pixGetWpl(pix);
2491  for (j = xstart; j < xend; j++) {
2492  sum = 0.0;
2493  if (d == 8) {
2494  for (i = ystart; i < yend; i++) {
2495  line = data + i * wpl;
2496  sum += GET_DATA_BYTE(line, j);
2497  }
2498  if (type == L_BLACK_IS_MAX)
2499  sum = bh * 255 - sum;
2500  } else { /* d == 16 */
2501  for (i = ystart; i < yend; i++) {
2502  line = data + i * wpl;
2503  sum += GET_DATA_TWO_BYTES(line, j);
2504  }
2505  if (type == L_BLACK_IS_MAX)
2506  sum = bh * 0xffff - sum;
2507  }
2508  numaAddNumber(na, (l_float32)(norm * sum));
2509  }
2510 
2511  return na;
2512 }
2513 
2514 
2523 l_ok
2525  BOX *box,
2526  l_float32 *pave)
2527 {
2528 l_int32 w, h, d, wpl, i, j, xstart, xend, ystart, yend, bw, bh;
2529 l_uint32 *data, *line;
2530 l_float64 ave;
2531 
2532  PROCNAME("pixAverageInRect");
2533 
2534  if (!pave)
2535  return ERROR_INT("&ave not defined", procName, 1);
2536  *pave = 0;
2537  if (!pix)
2538  return ERROR_INT("pix not defined", procName, 1);
2539  pixGetDimensions(pix, &w, &h, &d);
2540  if (d != 1 && d != 2 && d != 4 && d != 8)
2541  return ERROR_INT("pix not 1, 2, 4 or 8 bpp", procName, 1);
2542  if (pixGetColormap(pix) != NULL)
2543  return ERROR_INT("pix is colormapped", procName, 1);
2544 
2545  if (boxClipToRectangleParams(box, w, h, &xstart, &ystart, &xend, &yend,
2546  &bw, &bh) == 1)
2547  return ERROR_INT("invalid clipping box", procName, 1);
2548 
2549  wpl = pixGetWpl(pix);
2550  data = pixGetData(pix);
2551  ave = 0;
2552  for (i = ystart; i < yend; i++) {
2553  line = data + i * wpl;
2554  for (j = xstart; j < xend; j++) {
2555  if (d == 1)
2556  ave += GET_DATA_BIT(line, j);
2557  else if (d == 2)
2558  ave += GET_DATA_DIBIT(line, j);
2559  else if (d == 4)
2560  ave += GET_DATA_QBIT(line, j);
2561  else /* d == 8 */
2562  ave += GET_DATA_BYTE(line, j);
2563  }
2564  }
2565 
2566  *pave = ave / ((l_float32)(bw) * bh);
2567  return 0;
2568 }
2569 
2570 
2571 /*------------------------------------------------------------------*
2572  * Variance of pixel values in gray images *
2573  *------------------------------------------------------------------*/
2589 NUMA *
2591  BOX *box)
2592 {
2593 l_int32 i, j, w, h, d, wpl, xstart, xend, ystart, yend, bw, bh, val;
2594 l_uint32 *line, *data;
2595 l_float64 sum1, sum2, norm, ave, var, rootvar;
2596 NUMA *na;
2597 
2598  PROCNAME("pixVarianceByRow");
2599 
2600  if (!pix)
2601  return (NUMA *)ERROR_PTR("pix not defined", procName, NULL);
2602  pixGetDimensions(pix, &w, &h, &d);
2603  if (d != 8 && d != 16)
2604  return (NUMA *)ERROR_PTR("pix not 8 or 16 bpp", procName, NULL);
2605  if (pixGetColormap(pix) != NULL)
2606  return (NUMA *)ERROR_PTR("pix colormapped", procName, NULL);
2607 
2608  if (boxClipToRectangleParams(box, w, h, &xstart, &ystart, &xend, &yend,
2609  &bw, &bh) == 1)
2610  return (NUMA *)ERROR_PTR("invalid clipping box", procName, NULL);
2611 
2612  if ((na = numaCreate(bh)) == NULL)
2613  return (NUMA *)ERROR_PTR("na not made", procName, NULL);
2614  numaSetParameters(na, ystart, 1);
2615  norm = 1. / (l_float32)bw;
2616  data = pixGetData(pix);
2617  wpl = pixGetWpl(pix);
2618  for (i = ystart; i < yend; i++) {
2619  sum1 = sum2 = 0.0;
2620  line = data + i * wpl;
2621  for (j = xstart; j < xend; j++) {
2622  if (d == 8)
2623  val = GET_DATA_BYTE(line, j);
2624  else /* d == 16 */
2625  val = GET_DATA_TWO_BYTES(line, j);
2626  sum1 += val;
2627  sum2 += (l_float64)(val) * val;
2628  }
2629  ave = norm * sum1;
2630  var = norm * sum2 - ave * ave;
2631  rootvar = sqrt(var);
2632  numaAddNumber(na, (l_float32)rootvar);
2633  }
2634 
2635  return na;
2636 }
2637 
2638 
2654 NUMA *
2656  BOX *box)
2657 {
2658 l_int32 i, j, w, h, d, wpl, xstart, xend, ystart, yend, bw, bh, val;
2659 l_uint32 *line, *data;
2660 l_float64 sum1, sum2, norm, ave, var, rootvar;
2661 NUMA *na;
2662 
2663  PROCNAME("pixVarianceByColumn");
2664 
2665  if (!pix)
2666  return (NUMA *)ERROR_PTR("pix not defined", procName, NULL);
2667  pixGetDimensions(pix, &w, &h, &d);
2668  if (d != 8 && d != 16)
2669  return (NUMA *)ERROR_PTR("pix not 8 or 16 bpp", procName, NULL);
2670  if (pixGetColormap(pix) != NULL)
2671  return (NUMA *)ERROR_PTR("pix colormapped", procName, NULL);
2672 
2673  if (boxClipToRectangleParams(box, w, h, &xstart, &ystart, &xend, &yend,
2674  &bw, &bh) == 1)
2675  return (NUMA *)ERROR_PTR("invalid clipping box", procName, NULL);
2676 
2677  if ((na = numaCreate(bw)) == NULL)
2678  return (NUMA *)ERROR_PTR("na not made", procName, NULL);
2679  numaSetParameters(na, xstart, 1);
2680  norm = 1. / (l_float32)bh;
2681  data = pixGetData(pix);
2682  wpl = pixGetWpl(pix);
2683  for (j = xstart; j < xend; j++) {
2684  sum1 = sum2 = 0.0;
2685  for (i = ystart; i < yend; i++) {
2686  line = data + wpl * i;
2687  if (d == 8)
2688  val = GET_DATA_BYTE(line, j);
2689  else /* d == 16 */
2690  val = GET_DATA_TWO_BYTES(line, j);
2691  sum1 += val;
2692  sum2 += (l_float64)(val) * val;
2693  }
2694  ave = norm * sum1;
2695  var = norm * sum2 - ave * ave;
2696  rootvar = sqrt(var);
2697  numaAddNumber(na, (l_float32)rootvar);
2698  }
2699 
2700  return na;
2701 }
2702 
2703 
2712 l_ok
2714  BOX *box,
2715  l_float32 *prootvar)
2716 {
2717 l_int32 w, h, d, wpl, i, j, xstart, xend, ystart, yend, bw, bh, val;
2718 l_uint32 *data, *line;
2719 l_float64 sum1, sum2, norm, ave, var;
2720 
2721  PROCNAME("pixVarianceInRect");
2722 
2723  if (!prootvar)
2724  return ERROR_INT("&rootvar not defined", procName, 1);
2725  *prootvar = 0.0;
2726  if (!pix)
2727  return ERROR_INT("pix not defined", procName, 1);
2728  pixGetDimensions(pix, &w, &h, &d);
2729  if (d != 1 && d != 2 && d != 4 && d != 8)
2730  return ERROR_INT("pix not 1, 2, 4 or 8 bpp", procName, 1);
2731  if (pixGetColormap(pix) != NULL)
2732  return ERROR_INT("pix is colormapped", procName, 1);
2733 
2734  if (boxClipToRectangleParams(box, w, h, &xstart, &ystart, &xend, &yend,
2735  &bw, &bh) == 1)
2736  return ERROR_INT("invalid clipping box", procName, 1);
2737 
2738  wpl = pixGetWpl(pix);
2739  data = pixGetData(pix);
2740  sum1 = sum2 = 0.0;
2741  for (i = ystart; i < yend; i++) {
2742  line = data + i * wpl;
2743  for (j = xstart; j < xend; j++) {
2744  if (d == 1) {
2745  val = GET_DATA_BIT(line, j);
2746  sum1 += val;
2747  sum2 += (l_float64)(val) * val;
2748  } else if (d == 2) {
2749  val = GET_DATA_DIBIT(line, j);
2750  sum1 += val;
2751  sum2 += (l_float64)(val) * val;
2752  } else if (d == 4) {
2753  val = GET_DATA_QBIT(line, j);
2754  sum1 += val;
2755  sum2 += (l_float64)(val) * val;
2756  } else { /* d == 8 */
2757  val = GET_DATA_BYTE(line, j);
2758  sum1 += val;
2759  sum2 += (l_float64)(val) * val;
2760  }
2761  }
2762  }
2763  norm = 1.0 / ((l_float64)(bw) * bh);
2764  ave = norm * sum1;
2765  var = norm * sum2 - ave * ave;
2766  *prootvar = (l_float32)sqrt(var);
2767  return 0;
2768 }
2769 
2770 
2771 /*---------------------------------------------------------------------*
2772  * Average of absolute value of pixel differences in gray images *
2773  *---------------------------------------------------------------------*/
2789 NUMA *
2791  BOX *box)
2792 {
2793 l_int32 i, j, w, h, wpl, xstart, xend, ystart, yend, bw, bh, val0, val1;
2794 l_uint32 *line, *data;
2795 l_float64 norm, sum;
2796 NUMA *na;
2797 
2798  PROCNAME("pixAbsDiffByRow");
2799 
2800  if (!pix || pixGetDepth(pix) != 8)
2801  return (NUMA *)ERROR_PTR("pix undefined or not 8 bpp", procName, NULL);
2802  if (pixGetColormap(pix) != NULL)
2803  return (NUMA *)ERROR_PTR("pix colormapped", procName, NULL);
2804 
2805  pixGetDimensions(pix, &w, &h, NULL);
2806  if (boxClipToRectangleParams(box, w, h, &xstart, &ystart, &xend, &yend,
2807  &bw, &bh) == 1)
2808  return (NUMA *)ERROR_PTR("invalid clipping box", procName, NULL);
2809  if (bw < 2)
2810  return (NUMA *)ERROR_PTR("row width must be >= 2", procName, NULL);
2811 
2812  norm = 1. / (l_float32)(bw - 1);
2813  if ((na = numaCreate(bh)) == NULL)
2814  return (NUMA *)ERROR_PTR("na not made", procName, NULL);
2815  numaSetParameters(na, ystart, 1);
2816  data = pixGetData(pix);
2817  wpl = pixGetWpl(pix);
2818  for (i = ystart; i < yend; i++) {
2819  sum = 0.0;
2820  line = data + i * wpl;
2821  val0 = GET_DATA_BYTE(line, xstart);
2822  for (j = xstart + 1; j < xend; j++) {
2823  val1 = GET_DATA_BYTE(line, j);
2824  sum += L_ABS(val1 - val0);
2825  val0 = val1;
2826  }
2827  numaAddNumber(na, (l_float32)(norm * sum));
2828  }
2829 
2830  return na;
2831 }
2832 
2833 
2850 NUMA *
2852  BOX *box)
2853 {
2854 l_int32 i, j, w, h, wpl, xstart, xend, ystart, yend, bw, bh, val0, val1;
2855 l_uint32 *line, *data;
2856 l_float64 norm, sum;
2857 NUMA *na;
2858 
2859  PROCNAME("pixAbsDiffByColumn");
2860 
2861  if (!pix || pixGetDepth(pix) != 8)
2862  return (NUMA *)ERROR_PTR("pix undefined or not 8 bpp", procName, NULL);
2863  if (pixGetColormap(pix) != NULL)
2864  return (NUMA *)ERROR_PTR("pix colormapped", procName, NULL);
2865 
2866  pixGetDimensions(pix, &w, &h, NULL);
2867  if (boxClipToRectangleParams(box, w, h, &xstart, &ystart, &xend, &yend,
2868  &bw, &bh) == 1)
2869  return (NUMA *)ERROR_PTR("invalid clipping box", procName, NULL);
2870  if (bh < 2)
2871  return (NUMA *)ERROR_PTR("column height must be >= 2", procName, NULL);
2872 
2873  norm = 1. / (l_float32)(bh - 1);
2874  if ((na = numaCreate(bw)) == NULL)
2875  return (NUMA *)ERROR_PTR("na not made", procName, NULL);
2876  numaSetParameters(na, xstart, 1);
2877  data = pixGetData(pix);
2878  wpl = pixGetWpl(pix);
2879  for (j = xstart; j < xend; j++) {
2880  sum = 0.0;
2881  line = data + ystart * wpl;
2882  val0 = GET_DATA_BYTE(line, j);
2883  for (i = ystart + 1; i < yend; i++) {
2884  line = data + i * wpl;
2885  val1 = GET_DATA_BYTE(line, j);
2886  sum += L_ABS(val1 - val0);
2887  val0 = val1;
2888  }
2889  numaAddNumber(na, (l_float32)(norm * sum));
2890  }
2891 
2892  return na;
2893 }
2894 
2895 
2913 l_ok
2915  BOX *box,
2916  l_int32 dir,
2917  l_float32 *pabsdiff)
2918 {
2919 l_int32 w, h, wpl, i, j, xstart, xend, ystart, yend, bw, bh, val0, val1;
2920 l_uint32 *data, *line;
2921 l_float64 norm, sum;
2922 
2923  PROCNAME("pixAbsDiffInRect");
2924 
2925  if (!pabsdiff)
2926  return ERROR_INT("&absdiff not defined", procName, 1);
2927  *pabsdiff = 0.0;
2928  if (!pix || pixGetDepth(pix) != 8)
2929  return ERROR_INT("pix undefined or not 8 bpp", procName, 1);
2930  if (dir != L_HORIZONTAL_LINE && dir != L_VERTICAL_LINE)
2931  return ERROR_INT("invalid direction", procName, 1);
2932  if (pixGetColormap(pix) != NULL)
2933  return ERROR_INT("pix is colormapped", procName, 1);
2934 
2935  pixGetDimensions(pix, &w, &h, NULL);
2936  if (boxClipToRectangleParams(box, w, h, &xstart, &ystart, &xend, &yend,
2937  &bw, &bh) == 1)
2938  return ERROR_INT("invalid clipping box", procName, 1);
2939 
2940  wpl = pixGetWpl(pix);
2941  data = pixGetData(pix);
2942  if (dir == L_HORIZONTAL_LINE) {
2943  norm = 1. / (l_float32)(bh * (bw - 1));
2944  sum = 0.0;
2945  for (i = ystart; i < yend; i++) {
2946  line = data + i * wpl;
2947  val0 = GET_DATA_BYTE(line, xstart);
2948  for (j = xstart + 1; j < xend; j++) {
2949  val1 = GET_DATA_BYTE(line, j);
2950  sum += L_ABS(val1 - val0);
2951  val0 = val1;
2952  }
2953  }
2954  } else { /* vertical line */
2955  norm = 1. / (l_float32)(bw * (bh - 1));
2956  sum = 0.0;
2957  for (j = xstart; j < xend; j++) {
2958  line = data + ystart * wpl;
2959  val0 = GET_DATA_BYTE(line, j);
2960  for (i = ystart + 1; i < yend; i++) {
2961  line = data + i * wpl;
2962  val1 = GET_DATA_BYTE(line, j);
2963  sum += L_ABS(val1 - val0);
2964  val0 = val1;
2965  }
2966  }
2967  }
2968  *pabsdiff = (l_float32)(norm * sum);
2969  return 0;
2970 }
2971 
2972 
2990 l_ok
2992  l_int32 x1,
2993  l_int32 y1,
2994  l_int32 x2,
2995  l_int32 y2,
2996  l_float32 *pabsdiff)
2997 {
2998 l_int32 w, h, i, j, dir, size, sum;
2999 l_uint32 val0, val1;
3000 
3001  PROCNAME("pixAbsDiffOnLine");
3002 
3003  if (!pabsdiff)
3004  return ERROR_INT("&absdiff not defined", procName, 1);
3005  *pabsdiff = 0.0;
3006  if (!pix || pixGetDepth(pix) != 8)
3007  return ERROR_INT("pix undefined or not 8 bpp", procName, 1);
3008  if (y1 == y2) {
3009  dir = L_HORIZONTAL_LINE;
3010  } else if (x1 == x2) {
3011  dir = L_VERTICAL_LINE;
3012  } else {
3013  return ERROR_INT("line is neither horiz nor vert", procName, 1);
3014  }
3015  if (pixGetColormap(pix) != NULL)
3016  return ERROR_INT("pix is colormapped", procName, 1);
3017 
3018  pixGetDimensions(pix, &w, &h, NULL);
3019  sum = 0;
3020  if (dir == L_HORIZONTAL_LINE) {
3021  x1 = L_MAX(x1, 0);
3022  x2 = L_MIN(x2, w - 1);
3023  if (x1 >= x2)
3024  return ERROR_INT("x1 >= x2", procName, 1);
3025  size = x2 - x1;
3026  pixGetPixel(pix, x1, y1, &val0);
3027  for (j = x1 + 1; j <= x2; j++) {
3028  pixGetPixel(pix, j, y1, &val1);
3029  sum += L_ABS((l_int32)val1 - (l_int32)val0);
3030  val0 = val1;
3031  }
3032  } else { /* vertical */
3033  y1 = L_MAX(y1, 0);
3034  y2 = L_MIN(y2, h - 1);
3035  if (y1 >= y2)
3036  return ERROR_INT("y1 >= y2", procName, 1);
3037  size = y2 - y1;
3038  pixGetPixel(pix, x1, y1, &val0);
3039  for (i = y1 + 1; i <= y2; i++) {
3040  pixGetPixel(pix, x1, i, &val1);
3041  sum += L_ABS((l_int32)val1 - (l_int32)val0);
3042  val0 = val1;
3043  }
3044  }
3045  *pabsdiff = (l_float32)sum / (l_float32)size;
3046  return 0;
3047 }
3048 
3049 
3050 /*-------------------------------------------------------------*
3051  * Count of pixels with specific value *
3052  *-------------------------------------------------------------*/
3072 l_int32
3074  BOX *box,
3075  l_int32 val,
3076  l_int32 factor,
3077  l_int32 *pcount)
3078 {
3079 l_int32 i, j, bx, by, bw, bh, w, h, wpl, pixval;
3080 l_uint32 *data, *line;
3081 
3082  PROCNAME("pixCountArbInRect");
3083 
3084  if (!pcount)
3085  return ERROR_INT("&count not defined", procName, 1);
3086  *pcount = 0;
3087  if (!pixs)
3088  return ERROR_INT("pixs not defined", procName, 1);
3089  if (pixGetDepth(pixs) != 8 && !pixGetColormap(pixs))
3090  return ERROR_INT("pixs neither 8 bpp nor colormapped",
3091  procName, 1);
3092  if (factor < 1)
3093  return ERROR_INT("sampling factor < 1", procName, 1);
3094 
3095  pixGetDimensions(pixs, &w, &h, NULL);
3096  data = pixGetData(pixs);
3097  wpl = pixGetWpl(pixs);
3098 
3099  if (!box) {
3100  for (i = 0; i < h; i += factor) {
3101  line = data + i * wpl;
3102  for (j = 0; j < w; j += factor) {
3103  pixval = GET_DATA_BYTE(line, j);
3104  if (pixval == val) (*pcount)++;
3105  }
3106  }
3107  } else {
3108  boxGetGeometry(box, &bx, &by, &bw, &bh);
3109  for (i = 0; i < bh; i += factor) {
3110  if (by + i < 0 || by + i >= h) continue;
3111  line = data + (by + i) * wpl;
3112  for (j = 0; j < bw; j += factor) {
3113  if (bx + j < 0 || bx + j >= w) continue;
3114  pixval = GET_DATA_BYTE(line, bx + j);
3115  if (pixval == val) (*pcount)++;
3116  }
3117  }
3118  }
3119 
3120  if (factor > 1) /* assume pixel color is randomly distributed */
3121  *pcount = *pcount * factor * factor;
3122  return 0;
3123 }
3124 
3125 
3126 /*-------------------------------------------------------------*
3127  * Mirrored tiling of a smaller image *
3128  *-------------------------------------------------------------*/
3150 PIX *
3152  l_int32 w,
3153  l_int32 h)
3154 {
3155 l_int32 wt, ht, d, i, j, nx, ny;
3156 PIX *pixd, *pixsfx, *pixsfy, *pixsfxy, *pix;
3157 
3158  PROCNAME("pixMirroredTiling");
3159 
3160  if (!pixs)
3161  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
3162  pixGetDimensions(pixs, &wt, &ht, &d);
3163  if (wt <= 0 || ht <= 0)
3164  return (PIX *)ERROR_PTR("pixs size illegal", procName, NULL);
3165  if (d != 8 && d != 32)
3166  return (PIX *)ERROR_PTR("depth not 32 bpp", procName, NULL);
3167 
3168  if ((pixd = pixCreate(w, h, d)) == NULL)
3169  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
3170  pixCopySpp(pixd, pixs);
3171 
3172  nx = (w + wt - 1) / wt;
3173  ny = (h + ht - 1) / ht;
3174  pixsfx = pixFlipLR(NULL, pixs);
3175  pixsfy = pixFlipTB(NULL, pixs);
3176  pixsfxy = pixFlipTB(NULL, pixsfx);
3177  for (i = 0; i < ny; i++) {
3178  for (j = 0; j < nx; j++) {
3179  pix = pixs;
3180  if ((i & 1) && !(j & 1))
3181  pix = pixsfy;
3182  else if (!(i & 1) && (j & 1))
3183  pix = pixsfx;
3184  else if ((i & 1) && (j & 1))
3185  pix = pixsfxy;
3186  pixRasterop(pixd, j * wt, i * ht, wt, ht, PIX_SRC, pix, 0, 0);
3187  }
3188  }
3189 
3190  pixDestroy(&pixsfx);
3191  pixDestroy(&pixsfy);
3192  pixDestroy(&pixsfxy);
3193  return pixd;
3194 }
3195 
3196 
3225 l_ok
3227  BOX *box,
3228  l_int32 searchdir,
3229  l_int32 mindist,
3230  l_int32 tsize,
3231  l_int32 ntiles,
3232  BOX **pboxtile,
3233  l_int32 debug)
3234 {
3235 l_int32 w, h, i, n, bestindex;
3236 l_float32 var_of_mean, median_of_mean, median_of_stdev, mean_val, stdev_val;
3237 l_float32 mindels, bestdelm, delm, dels, mean, stdev;
3238 BOXA *boxa;
3239 NUMA *namean, *nastdev;
3240 PIX *pix, *pixg;
3241 PIXA *pixa;
3242 
3243  PROCNAME("pixFindRepCloseTile");
3244 
3245  if (!pboxtile)
3246  return ERROR_INT("&boxtile not defined", procName, 1);
3247  *pboxtile = NULL;
3248  if (!pixs)
3249  return ERROR_INT("pixs not defined", procName, 1);
3250  if (!box)
3251  return ERROR_INT("box not defined", procName, 1);
3252  if (searchdir != L_HORIZ && searchdir != L_VERT)
3253  return ERROR_INT("invalid searchdir", procName, 1);
3254  if (mindist < 0)
3255  return ERROR_INT("mindist must be >= 0", procName, 1);
3256  if (tsize < 2)
3257  return ERROR_INT("tsize must be > 1", procName, 1);
3258  if (ntiles > 7) {
3259  L_WARNING("ntiles = %d; larger than suggested max of 7\n",
3260  procName, ntiles);
3261  }
3262 
3263  /* Locate tile regions */
3264  pixGetDimensions(pixs, &w, &h, NULL);
3265  boxa = findTileRegionsForSearch(box, w, h, searchdir, mindist,
3266  tsize, ntiles);
3267  if (!boxa)
3268  return ERROR_INT("no tiles found", procName, 1);
3269 
3270  /* Generate the tiles and the mean and stdev of intensity */
3271  pixa = pixClipRectangles(pixs, boxa);
3272  n = pixaGetCount(pixa);
3273  namean = numaCreate(n);
3274  nastdev = numaCreate(n);
3275  for (i = 0; i < n; i++) {
3276  pix = pixaGetPix(pixa, i, L_CLONE);
3277  pixg = pixConvertRGBToGray(pix, 0.33, 0.34, 0.33);
3278  pixGetAverageMasked(pixg, NULL, 0, 0, 1, L_MEAN_ABSVAL, &mean);
3279  pixGetAverageMasked(pixg, NULL, 0, 0, 1, L_STANDARD_DEVIATION, &stdev);
3280  numaAddNumber(namean, mean);
3281  numaAddNumber(nastdev, stdev);
3282  pixDestroy(&pix);
3283  pixDestroy(&pixg);
3284  }
3285 
3286  /* Find the median and variance of the averages. We require
3287  * the best tile to have a mean pixel intensity within a standard
3288  * deviation of the median of mean intensities, and choose the
3289  * tile in that set with the smallest stdev of pixel intensities
3290  * (as a proxy for the tile with least visible structure).
3291  * The median of the stdev is used, for debugging, as a normalizing
3292  * factor for the stdev of intensities within a tile. */
3293  numaGetStatsUsingHistogram(namean, 256, NULL, NULL, NULL, &var_of_mean,
3294  &median_of_mean, 0.0, NULL, NULL);
3295  numaGetStatsUsingHistogram(nastdev, 256, NULL, NULL, NULL, NULL,
3296  &median_of_stdev, 0.0, NULL, NULL);
3297  mindels = 1000.0;
3298  bestdelm = 1000.0;
3299  bestindex = 0;
3300  for (i = 0; i < n; i++) {
3301  numaGetFValue(namean, i, &mean_val);
3302  numaGetFValue(nastdev, i, &stdev_val);
3303  if (var_of_mean == 0.0) { /* uniform color; any box will do */
3304  delm = 0.0; /* any value < 1.01 */
3305  dels = 1.0; /* n'importe quoi */
3306  } else {
3307  delm = L_ABS(mean_val - median_of_mean) / sqrt(var_of_mean);
3308  dels = stdev_val / median_of_stdev;
3309  }
3310  if (delm < 1.01) {
3311  if (dels < mindels) {
3312  if (debug) {
3313  fprintf(stderr, "i = %d, mean = %7.3f, delm = %7.3f,"
3314  " stdev = %7.3f, dels = %7.3f\n",
3315  i, mean_val, delm, stdev_val, dels);
3316  }
3317  mindels = dels;
3318  bestdelm = delm;
3319  bestindex = i;
3320  }
3321  }
3322  }
3323  *pboxtile = boxaGetBox(boxa, bestindex, L_COPY);
3324 
3325  if (debug) {
3326  L_INFO("median of mean = %7.3f\n", procName, median_of_mean);
3327  L_INFO("standard dev of mean = %7.3f\n", procName, sqrt(var_of_mean));
3328  L_INFO("median of stdev = %7.3f\n", procName, median_of_stdev);
3329  L_INFO("best tile: index = %d\n", procName, bestindex);
3330  L_INFO("delta from median in units of stdev = %5.3f\n",
3331  procName, bestdelm);
3332  L_INFO("stdev as fraction of median stdev = %5.3f\n",
3333  procName, mindels);
3334  }
3335 
3336  numaDestroy(&namean);
3337  numaDestroy(&nastdev);
3338  pixaDestroy(&pixa);
3339  boxaDestroy(&boxa);
3340  return 0;
3341 }
3342 
3343 
3360 static BOXA *
3362  l_int32 w,
3363  l_int32 h,
3364  l_int32 searchdir,
3365  l_int32 mindist,
3366  l_int32 tsize,
3367  l_int32 ntiles)
3368 {
3369 l_int32 bx, by, bw, bh, left, right, top, bot, i, j, nrows, ncols;
3370 l_int32 x0, y0, x, y, w_avail, w_needed, h_avail, h_needed, t_avail;
3371 BOX *box1;
3372 BOXA *boxa;
3373 
3374  PROCNAME("findTileRegionsForSearch");
3375 
3376  if (!box)
3377  return (BOXA *)ERROR_PTR("box not defined", procName, NULL);
3378  if (ntiles == 0)
3379  return (BOXA *)ERROR_PTR("no tiles requested", procName, NULL);
3380 
3381  boxGetGeometry(box, &bx, &by, &bw, &bh);
3382  if (searchdir == L_HORIZ) {
3383  /* Find the tile parameters for the search. Note that the
3384  * tiles are overlapping by 50% in each direction. */
3385  left = bx; /* distance to left of box */
3386  right = w - bx - bw + 1; /* distance to right of box */
3387  w_avail = L_MAX(left, right) - mindist;
3388  if (tsize & 1) tsize++; /* be sure it's even */
3389  if (w_avail < tsize) {
3390  L_ERROR("tsize = %d, w_avail = %d\n", procName, tsize, w_avail);
3391  return NULL;
3392  }
3393  w_needed = tsize + (ntiles - 1) * (tsize / 2);
3394  if (w_needed > w_avail) {
3395  t_avail = 1 + 2 * (w_avail - tsize) / tsize;
3396  L_WARNING("ntiles = %d; room for only %d\n", procName,
3397  ntiles, t_avail);
3398  ntiles = t_avail;
3399  w_needed = tsize + (ntiles - 1) * (tsize / 2);
3400  }
3401  nrows = L_MAX(1, 1 + 2 * (bh - tsize) / tsize);
3402 
3403  /* Generate the tile regions to search */
3404  boxa = boxaCreate(0);
3405  if (left > right) /* search to left */
3406  x0 = bx - w_needed;
3407  else /* search to right */
3408  x0 = bx + bw + mindist;
3409  for (i = 0; i < nrows; i++) {
3410  y = by + i * tsize / 2;
3411  for (j = 0; j < ntiles; j++) {
3412  x = x0 + j * tsize / 2;
3413  box1 = boxCreate(x, y, tsize, tsize);
3414  boxaAddBox(boxa, box1, L_INSERT);
3415  }
3416  }
3417  } else { /* L_VERT */
3418  /* Find the tile parameters for the search */
3419  top = by; /* distance above box */
3420  bot = h - by - bh + 1; /* distance below box */
3421  h_avail = L_MAX(top, bot) - mindist;
3422  if (h_avail < tsize) {
3423  L_ERROR("tsize = %d, h_avail = %d\n", procName, tsize, h_avail);
3424  return NULL;
3425  }
3426  h_needed = tsize + (ntiles - 1) * (tsize / 2);
3427  if (h_needed > h_avail) {
3428  t_avail = 1 + 2 * (h_avail - tsize) / tsize;
3429  L_WARNING("ntiles = %d; room for only %d\n", procName,
3430  ntiles, t_avail);
3431  ntiles = t_avail;
3432  h_needed = tsize + (ntiles - 1) * (tsize / 2);
3433  }
3434  ncols = L_MAX(1, 1 + 2 * (bw - tsize) / tsize);
3435 
3436  /* Generate the tile regions to search */
3437  boxa = boxaCreate(0);
3438  if (top > bot) /* search above */
3439  y0 = by - h_needed;
3440  else /* search below */
3441  y0 = by + bh + mindist;
3442  for (j = 0; j < ncols; j++) {
3443  x = bx + j * tsize / 2;
3444  for (i = 0; i < ntiles; i++) {
3445  y = y0 + i * tsize / 2;
3446  box1 = boxCreate(x, y, tsize, tsize);
3447  boxaAddBox(boxa, box1, L_INSERT);
3448  }
3449  }
3450  }
3451  return boxa;
3452 }
PIX * pixFlipLR(PIX *pixd, PIX *pixs)
pixFlipLR()
Definition: rotateorth.c:423
NUMA * pixCountPixelsByRow(PIX *pix, l_int32 *tab8)
pixCountPixelsByRow()
Definition: pix3.c:2029
PIX * pixUnpackBinary(PIX *pixs, l_int32 depth, l_int32 invert)
pixUnpackBinary()
Definition: pixconv.c:1878
NUMA * pixCountByRow(PIX *pix, BOX *box)
pixCountByRow()
Definition: pix3.c:1931
l_ok numaGetFValue(NUMA *na, l_int32 index, l_float32 *pval)
numaGetFValue()
Definition: numabasic.c:692
NUMA * pixCountPixelsByColumn(PIX *pix)
pixCountPixelsByColumn()
Definition: pix3.c:2063
l_int32 lept_mkdir(const char *subdir)
lept_mkdir()
Definition: utils2.c:1944
Definition: pix.h:717
l_ok pixCountPixelsInRow(PIX *pix, l_int32 row, l_int32 *pcount, l_int32 *tab8)
pixCountPixelsInRow()
Definition: pix3.c:2104
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:3226
l_ok pixSetMasked(PIX *pixd, PIX *pixm, l_uint32 val)
pixSetMasked()
Definition: pix3.c:155
l_int32 * makePixelCentroidTab8(void)
makePixelCentroidTab8()
Definition: pix3.c:2337
NUMA * pixVarianceByRow(PIX *pix, BOX *box)
pixVarianceByRow()
Definition: pix3.c:2590
l_ok numaAddNumber(NUMA *na, l_float32 val)
numaAddNumber()
Definition: numabasic.c:473
l_ok pixAbsDiffInRect(PIX *pix, BOX *box, l_int32 dir, l_float32 *pabsdiff)
pixAbsDiffInRect()
Definition: pix3.c:2914
Definition: pix.h:716
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:3361
PIX * pixMakeAlphaFromMask(PIX *pixs, l_int32 dist, BOX **pbox)
pixMakeAlphaFromMask()
Definition: pix3.c:1222
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:193
PIX * pixDilateBrick(PIX *pixd, PIX *pixs, l_int32 hsize, l_int32 vsize)
pixDilateBrick()
Definition: morph.c:684
l_int32 pixCountArbInRect(PIX *pixs, BOX *box, l_int32 val, l_int32 factor, l_int32 *pcount)
pixCountArbInRect()
Definition: pix3.c:3073
BOX * boxClipToRectangle(BOX *box, l_int32 wi, l_int32 hi)
boxClipToRectangle()
Definition: boxfunc1.c:1587
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
pixCreate()
Definition: pix1.c:302
l_ok pixSetMaskedGeneral(PIX *pixd, PIX *pixm, l_uint32 val, l_int32 x, l_int32 y)
pixSetMaskedGeneral()
Definition: pix3.c:294
PIX * pixInvert(PIX *pixd, PIX *pixs)
pixInvert()
Definition: pix3.c:1395
#define SET_DATA_QBIT(pdata, n, val)
Definition: arrayaccess.h:168
NUMA * numaCreate(l_int32 n)
numaCreate()
Definition: numabasic.c:187
void boxaDestroy(BOXA **pboxa)
boxaDestroy()
Definition: boxbasic.c:580
l_uint32 * pixGetData(PIX *pix)
pixGetData()
Definition: pix1.c:1624
BOX * pixaGetBox(PIXA *pixa, l_int32 index, l_int32 accesstype)
pixaGetBox()
Definition: pixabasic.c:797
l_ok numaSetCount(NUMA *na, l_int32 newcount)
numaSetCount()
Definition: numabasic.c:658
PIX * pixThresholdToBinary(PIX *pixs, l_int32 thresh)
pixThresholdToBinary()
Definition: grayquant.c:443
l_ok pixGetColorNearMaskBoundary(PIX *pixs, PIX *pixm, BOX *box, l_int32 dist, l_uint32 *pval, l_int32 debug)
pixGetColorNearMaskBoundary()
Definition: pix3.c:1291
#define GET_DATA_BIT(pdata, n)
Definition: arrayaccess.h:123
PIX * pixCreateTemplate(PIX *pixs)
pixCreateTemplate()
Definition: pix1.c:367
PIX * pixClipRectangle(PIX *pixs, BOX *box, BOX **pboxc)
pixClipRectangle()
Definition: pix5.c:1020
l_ok pixThresholdPixelSum(PIX *pix, l_int32 thresh, l_int32 *pabove, l_int32 *tab8)
pixThresholdPixelSum()
Definition: pix3.c:2225
Definition: pix.h:492
PIX * pixGetRGBComponent(PIX *pixs, l_int32 comp)
pixGetRGBComponent()
Definition: pix2.c:2404
#define SET_DATA_DIBIT(pdata, n, val)
Definition: arrayaccess.h:149
l_ok pixPaintThroughMask(PIX *pixd, PIX *pixm, l_int32 x, l_int32 y, l_uint32 val)
pixPaintThroughMask()
Definition: pix3.c:618
l_ok pixSetAllArbitrary(PIX *pix, l_uint32 val)
pixSetAllArbitrary()
Definition: pix2.c:876
l_ok pixCombineMasked(PIX *pixd, PIX *pixs, PIX *pixm)
pixCombineMasked()
Definition: pix3.c:374
l_ok pixClipToForeground(PIX *pixs, PIX **ppixd, BOX **pbox)
pixClipToForeground()
Definition: pix5.c:1660
#define PIX_MASK
Definition: pix.h:334
PIX * pixMakeMaskFromVal(PIX *pixs, l_int32 val)
pixMakeMaskFromVal()
Definition: pix3.c:943
PIX * pixSetUnderTransparency(PIX *pixs, l_uint32 val, l_int32 debug)
pixSetUnderTransparency()
Definition: pix3.c:1146
BOXA * pixConnComp(PIX *pixs, PIXA **ppixa, l_int32 connectivity)
pixConnComp()
Definition: conncomp.c:147
PIX * pixFlipTB(PIX *pixd, PIX *pixs)
pixFlipTB()
Definition: rotateorth.c:601
Definition: array.h:59
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:1457
PIX * pixXor(PIX *pixd, PIX *pixs1, PIX *pixs2)
pixXor()
Definition: pix3.c:1574
PIX * pixBlend(PIX *pixs1, PIX *pixs2, l_int32 x, l_int32 y, l_float32 fract)
pixBlend()
Definition: blend.c:174
l_ok pixForegroundFraction(PIX *pix, l_float32 *pfract)
pixForegroundFraction()
Definition: pix3.c:1751
PIX * pixAnd(PIX *pixd, PIX *pixs1, PIX *pixs2)
pixAnd()
Definition: pix3.c:1510
NUMA * pixAbsDiffByRow(PIX *pix, BOX *box)
pixAbsDiffByRow()
Definition: pix3.c:2790
PIX * pixMorphSequence(PIX *pixs, const char *sequence, l_int32 dispsep)
pixMorphSequence()
Definition: morphseq.c:133
l_ok pixCountPixels(PIX *pixs, l_int32 *pcount, l_int32 *tab8)
pixCountPixels()
Definition: pix3.c:1823
l_ok boxaAddBox(BOXA *boxa, BOX *box, l_int32 copyflag)
boxaAddBox()
Definition: boxbasic.c:618
PIX * pixBlendWithGrayMask(PIX *pixs1, PIX *pixs2, PIX *pixg, l_int32 x, l_int32 y)
pixBlendWithGrayMask()
Definition: blend.c:1692
l_int32 * makePixelSumTab8(void)
makePixelSumTab8()
Definition: pix3.c:2297
#define SET_DATA_BYTE(pdata, n, val)
Definition: arrayaccess.h:198
PIXA * pixClipRectangles(PIX *pixs, BOXA *boxa)
pixClipRectangles()
Definition: pix5.c:954
#define GET_DATA_QBIT(pdata, n)
Definition: arrayaccess.h:164
BOX * boxAdjustSides(BOX *boxd, BOX *boxs, l_int32 delleft, l_int32 delright, l_int32 deltop, l_int32 delbot)
boxAdjustSides()
Definition: boxfunc1.c:1807
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:1361
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:693
#define GET_DATA_BYTE(pdata, n)
Definition: arrayaccess.h:188
#define PIX_PAINT
Definition: pix.h:333
l_ok numaSetParameters(NUMA *na, l_float32 startx, l_float32 delx)
numaSetParameters()
Definition: numabasic.c:966
NUMA * pixAbsDiffByColumn(PIX *pix, BOX *box)
pixAbsDiffByColumn()
Definition: pix3.c:2851
l_ok pixaGetBoxGeometry(PIXA *pixa, l_int32 index, l_int32 *px, l_int32 *py, l_int32 *pw, l_int32 *ph)
pixaGetBoxGeometry()
Definition: pixabasic.c:835
l_ok pixCountPixelsInRect(PIX *pixs, BOX *box, l_int32 *pcount, l_int32 *tab8)
pixCountPixelsInRect()
Definition: pix3.c:1887
NUMA * pixAverageByColumn(PIX *pix, BOX *box, l_int32 type)
pixAverageByColumn()
Definition: pix3.c:2459
PIX * pixClone(PIX *pixs)
pixClone()
Definition: pix1.c:515
PIX * pixSubtract(PIX *pixd, PIX *pixs1, PIX *pixs2)
pixSubtract()
Definition: pix3.c:1639
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:543
BOX * boxaGetBox(BOXA *boxa, l_int32 index, l_int32 accessflag)
boxaGetBox()
Definition: boxbasic.c:763
NUMA * pixGetMomentByColumn(PIX *pix, l_int32 order)
pixGetMomentByColumn()
Definition: pix3.c:2167
PIX * pixMakeArbMaskFromRGB(PIX *pixs, l_float32 rc, l_float32 gc, l_float32 bc, l_float32 thresh)
pixMakeArbMaskFromRGB()
Definition: pix3.c:1069
Definition: pix.h:454
void numaDestroy(NUMA **pna)
numaDestroy()
Definition: numabasic.c:360
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
PIX * pixConvertRGBToGray(PIX *pixs, l_float32 rwt, l_float32 gwt, l_float32 bwt)
pixConvertRGBToGray()
Definition: pixconv.c:753
PIX * pixOr(PIX *pixd, PIX *pixs1, PIX *pixs2)
pixOr()
Definition: pix3.c:1446
NUMA * pixCountByColumn(PIX *pix, BOX *box)
pixCountByColumn()
Definition: pix3.c:1983
NUMA * pixaCountPixels(PIXA *pixa)
pixaCountPixels()
Definition: pix3.c:1778
l_ok pixVarianceInRect(PIX *pix, BOX *box, l_float32 *prootvar)
pixVarianceInRect()
Definition: pix3.c:2713
NUMA * pixVarianceByColumn(PIX *pix, BOX *box)
pixVarianceByColumn()
Definition: pix3.c:2655
PIX * pixConvertRGBToGrayArb(PIX *pixs, l_float32 rc, l_float32 gc, l_float32 bc)
pixConvertRGBToGrayArb()
Definition: pixconv.c:1052
l_ok pixAverageInRect(PIX *pix, BOX *box, l_float32 *pave)
pixAverageInRect()
Definition: pix3.c:2524
l_float32 * numaGetFArray(NUMA *na, l_int32 copyflag)
numaGetFArray()
Definition: numabasic.c:865
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:1644
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:786
#define GET_DATA_TWO_BYTES(pdata, n)
Definition: arrayaccess.h:212
PIX * pixDistanceFunction(PIX *pixs, l_int32 connectivity, l_int32 outdepth, l_int32 boundcond)
pixDistanceFunction()
Definition: seedfill.c:2533
#define GET_DATA_DIBIT(pdata, n)
Definition: arrayaccess.h:145
l_ok pixCombineMaskedGeneral(PIX *pixd, PIX *pixs, PIX *pixm, l_int32 x, l_int32 y)
pixCombineMaskedGeneral()
Definition: pix3.c:493
PIX * pixMirroredTiling(PIX *pixs, l_int32 w, l_int32 h)
pixMirroredTiling()
Definition: pix3.c:3151
PIX * pixaGetPix(PIXA *pixa, l_int32 index, l_int32 accesstype)
pixaGetPix()
Definition: pixabasic.c:672
Definition: pix.h:718
PIX * pixMakeMaskFromLUT(PIX *pixs, l_int32 *tab)
pixMakeMaskFromLUT()
Definition: pix3.c:1000
#define PIX_NOT(op)
Definition: pix.h:329
PIX * pixDisplayLayersRGBA(PIX *pixs, l_uint32 val, l_int32 maxw)
pixDisplayLayersRGBA()
Definition: pix2.c:2276
Definition: pix.h:134
l_ok pixMultConstantGray(PIX *pixs, l_float32 val)
pixMultConstantGray()
Definition: pixarith.c:186
Definition: pix.h:719
l_ok pixZero(PIX *pix, l_int32 *pempty)
pixZero()
Definition: pix3.c:1701
BOXA * boxaCreate(l_int32 n)
boxaCreate()
Definition: boxbasic.c:499
#define PIX_SRC
Definition: pix.h:327
PIX * pixCopy(PIX *pixd, PIX *pixs)
pixCopy()
Definition: pix1.c:628
void boxDestroy(BOX **pbox)
boxDestroy()
Definition: boxbasic.c:278
PIX * pixConvert1To8(PIX *pixd, PIX *pixs, l_uint8 val0, l_uint8 val1)
pixConvert1To8()
Definition: pixconv.c:2366
NUMA * pixAverageByRow(PIX *pix, BOX *box, l_int32 type)
pixAverageByRow()
Definition: pix3.c:2390
l_ok boxPrintStreamInfo(FILE *fp, BOX *box)
boxPrintStreamInfo()
Definition: boxbasic.c:2340
l_ok composeRGBPixel(l_int32 rval, l_int32 gval, l_int32 bval, l_uint32 *ppixel)
composeRGBPixel()
Definition: pix2.c:2671
l_int32 lept_rmdir(const char *subdir)
lept_rmdir()
Definition: utils2.c:2021
l_ok pixAbsDiffOnLine(PIX *pix, l_int32 x1, l_int32 y1, l_int32 x2, l_int32 y2, l_float32 *pabsdiff)
pixAbsDiffOnLine()
Definition: pix3.c:2991
l_ok pixCopySpp(PIX *pixd, const PIX *pixs)
pixCopySpp()
Definition: pix1.c:1188
l_int32 pixSizesEqual(const PIX *pix1, const PIX *pix2)
pixSizesEqual()
Definition: pix1.c:781
l_ok boxGetGeometry(BOX *box, l_int32 *px, l_int32 *py, l_int32 *pw, l_int32 *ph)
boxGetGeometry()
Definition: boxbasic.c:310
Definition: pix.h:480
#define SET_DATA_TWO_BYTES(pdata, n, val)
Definition: arrayaccess.h:222
void pixaDestroy(PIXA **ppixa)
pixaDestroy()
Definition: pixabasic.c:408
void extractRGBValues(l_uint32 pixel, l_int32 *prval, l_int32 *pgval, l_int32 *pbval)
extractRGBValues()
Definition: pix2.c:2737
BOX * boxCreate(l_int32 x, l_int32 y, l_int32 w, l_int32 h)
boxCreate()
Definition: boxbasic.c:165
l_int32 pixaGetCount(PIXA *pixa)
pixaGetCount()
Definition: pixabasic.c:631
#define SET_DATA_BIT(pdata, n)
Definition: arrayaccess.h:127
#define PIX_DST
Definition: pix.h:328
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:1254