Leptonica  1.73
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_int32
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_int32
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_int32
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_int32
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_int32
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_int32
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_int32
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  pixWrite("/tmp/masknear/input.png", pix1, IFF_PNG);
1353  pixWrite("/tmp/masknear/adjusted.png", pix2, IFF_PNG);
1354  pixWrite("/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  *-------------------------------------------------------------*/
1701 l_int32
1703  l_int32 *pempty)
1704 {
1705 l_int32 w, h, wpl, i, j, fullwords, endbits;
1706 l_uint32 endmask;
1707 l_uint32 *data, *line;
1708 
1709  PROCNAME("pixZero");
1710 
1711  if (!pempty)
1712  return ERROR_INT("&empty not defined", procName, 1);
1713  *pempty = 1;
1714  if (!pix)
1715  return ERROR_INT("pix not defined", procName, 1);
1716 
1717  w = pixGetWidth(pix) * pixGetDepth(pix); /* in bits */
1718  h = pixGetHeight(pix);
1719  wpl = pixGetWpl(pix);
1720  data = pixGetData(pix);
1721  fullwords = w / 32;
1722  endbits = w & 31;
1723  endmask = (endbits == 0) ? 0 : (0xffffffffU << (32 - endbits));
1724 
1725  for (i = 0; i < h; i++) {
1726  line = data + wpl * i;
1727  for (j = 0; j < fullwords; j++)
1728  if (*line++) {
1729  *pempty = 0;
1730  return 0;
1731  }
1732  if (endbits) {
1733  if (*line & endmask) {
1734  *pempty = 0;
1735  return 0;
1736  }
1737  }
1738  }
1739 
1740  return 0;
1741 }
1742 
1743 
1751 l_int32
1753  l_float32 *pfract)
1754 {
1755 l_int32 w, h, count;
1756 
1757  PROCNAME("pixForegroundFraction");
1758 
1759  if (!pfract)
1760  return ERROR_INT("&fract not defined", procName, 1);
1761  *pfract = 0.0;
1762  if (!pix || pixGetDepth(pix) != 1)
1763  return ERROR_INT("pix not defined or not 1 bpp", procName, 1);
1764 
1765  pixCountPixels(pix, &count, NULL);
1766  pixGetDimensions(pix, &w, &h, NULL);
1767  *pfract = (l_float32)count / (l_float32)(w * h);
1768  return 0;
1769 }
1770 
1771 
1778 NUMA *
1780 {
1781 l_int32 d, i, n, count;
1782 l_int32 *tab;
1783 NUMA *na;
1784 PIX *pix;
1785 
1786  PROCNAME("pixaCountPixels");
1787 
1788  if (!pixa)
1789  return (NUMA *)ERROR_PTR("pix not defined", procName, NULL);
1790 
1791  if ((n = pixaGetCount(pixa)) == 0)
1792  return numaCreate(1);
1793 
1794  pix = pixaGetPix(pixa, 0, L_CLONE);
1795  d = pixGetDepth(pix);
1796  pixDestroy(&pix);
1797  if (d != 1)
1798  return (NUMA *)ERROR_PTR("pixa not 1 bpp", procName, NULL);
1799 
1800  if ((na = numaCreate(n)) == NULL)
1801  return (NUMA *)ERROR_PTR("na not made", procName, NULL);
1802  tab = makePixelSumTab8();
1803  for (i = 0; i < n; i++) {
1804  pix = pixaGetPix(pixa, i, L_CLONE);
1805  pixCountPixels(pix, &count, tab);
1806  numaAddNumber(na, count);
1807  pixDestroy(&pix);
1808  }
1809 
1810  LEPT_FREE(tab);
1811  return na;
1812 }
1813 
1814 
1823 l_int32
1825  l_int32 *pcount,
1826  l_int32 *tab8)
1827 {
1828 l_uint32 endmask;
1829 l_int32 w, h, wpl, i, j;
1830 l_int32 fullwords, endbits, sum;
1831 l_int32 *tab;
1832 l_uint32 *data;
1833 
1834  PROCNAME("pixCountPixels");
1835 
1836  if (!pcount)
1837  return ERROR_INT("&count not defined", procName, 1);
1838  *pcount = 0;
1839  if (!pixs || pixGetDepth(pixs) != 1)
1840  return ERROR_INT("pixs not defined or not 1 bpp", procName, 1);
1841 
1842  tab = (tab8) ? tab8 : makePixelSumTab8();
1843  pixGetDimensions(pixs, &w, &h, NULL);
1844  wpl = pixGetWpl(pixs);
1845  data = pixGetData(pixs);
1846  fullwords = w >> 5;
1847  endbits = w & 31;
1848  endmask = (endbits == 0) ? 0 : (0xffffffffU << (32 - endbits));
1849 
1850  sum = 0;
1851  for (i = 0; i < h; i++, data += wpl) {
1852  for (j = 0; j < fullwords; j++) {
1853  l_uint32 word = data[j];
1854  if (word) {
1855  sum += tab[word & 0xff] +
1856  tab[(word >> 8) & 0xff] +
1857  tab[(word >> 16) & 0xff] +
1858  tab[(word >> 24) & 0xff];
1859  }
1860  }
1861  if (endbits) {
1862  l_uint32 word = data[j] & endmask;
1863  if (word) {
1864  sum += tab[word & 0xff] +
1865  tab[(word >> 8) & 0xff] +
1866  tab[(word >> 16) & 0xff] +
1867  tab[(word >> 24) & 0xff];
1868  }
1869  }
1870  }
1871  *pcount = sum;
1872 
1873  if (!tab8) LEPT_FREE(tab);
1874  return 0;
1875 }
1876 
1877 
1887 l_int32
1889  BOX *box,
1890  l_int32 *pcount,
1891  l_int32 *tab8)
1892 {
1893 l_int32 bx, by, bw, bh;
1894 PIX *pix1;
1895 
1896  PROCNAME("pixCountPixelsInRect");
1897 
1898  if (!pcount)
1899  return ERROR_INT("&count not defined", procName, 1);
1900  *pcount = 0;
1901  if (!pixs || pixGetDepth(pixs) != 1)
1902  return ERROR_INT("pixs not defined or not 1 bpp", procName, 1);
1903 
1904  if (box) {
1905  boxGetGeometry(box, &bx, &by, &bw, &bh);
1906  pix1 = pixCreate(bw, bh, 1);
1907  pixRasterop(pix1, 0, 0, bw, bh, PIX_SRC, pixs, bx, by);
1908  pixCountPixels(pix1, pcount, tab8);
1909  pixDestroy(&pix1);
1910  } else {
1911  pixCountPixels(pixs, pcount, tab8);
1912  }
1913 
1914  return 0;
1915 }
1916 
1917 
1931 NUMA *
1933  BOX *box)
1934 {
1935 l_int32 i, j, w, h, wpl, count, xstart, xend, ystart, yend, bw, bh;
1936 l_uint32 *line, *data;
1937 NUMA *na;
1938 
1939  PROCNAME("pixCountByRow");
1940 
1941  if (!pix || pixGetDepth(pix) != 1)
1942  return (NUMA *)ERROR_PTR("pix undefined or not 1 bpp", procName, NULL);
1943  if (!box)
1944  return pixCountPixelsByRow(pix, NULL);
1945 
1946  pixGetDimensions(pix, &w, &h, NULL);
1947  if (boxClipToRectangleParams(box, w, h, &xstart, &ystart, &xend, &yend,
1948  &bw, &bh) == 1)
1949  return (NUMA *)ERROR_PTR("invalid clipping box", procName, NULL);
1950 
1951  if ((na = numaCreate(bh)) == NULL)
1952  return (NUMA *)ERROR_PTR("na not made", procName, NULL);
1953  numaSetParameters(na, ystart, 1);
1954  data = pixGetData(pix);
1955  wpl = pixGetWpl(pix);
1956  for (i = ystart; i < yend; i++) {
1957  count = 0;
1958  line = data + i * wpl;
1959  for (j = xstart; j < xend; j++) {
1960  if (GET_DATA_BIT(line, j))
1961  count++;
1962  }
1963  numaAddNumber(na, count);
1964  }
1965 
1966  return na;
1967 }
1968 
1969 
1983 NUMA *
1985  BOX *box)
1986 {
1987 l_int32 i, j, w, h, wpl, count, xstart, xend, ystart, yend, bw, bh;
1988 l_uint32 *line, *data;
1989 NUMA *na;
1990 
1991  PROCNAME("pixCountByColumn");
1992 
1993  if (!pix || pixGetDepth(pix) != 1)
1994  return (NUMA *)ERROR_PTR("pix undefined or not 1 bpp", procName, NULL);
1995  if (!box)
1996  return pixCountPixelsByColumn(pix);
1997 
1998  pixGetDimensions(pix, &w, &h, NULL);
1999  if (boxClipToRectangleParams(box, w, h, &xstart, &ystart, &xend, &yend,
2000  &bw, &bh) == 1)
2001  return (NUMA *)ERROR_PTR("invalid clipping box", procName, NULL);
2002 
2003  if ((na = numaCreate(bw)) == NULL)
2004  return (NUMA *)ERROR_PTR("na not made", procName, NULL);
2005  numaSetParameters(na, xstart, 1);
2006  data = pixGetData(pix);
2007  wpl = pixGetWpl(pix);
2008  for (j = xstart; j < xend; j++) {
2009  count = 0;
2010  for (i = ystart; i < yend; i++) {
2011  line = data + i * wpl;
2012  if (GET_DATA_BIT(line, j))
2013  count++;
2014  }
2015  numaAddNumber(na, count);
2016  }
2017 
2018  return na;
2019 }
2020 
2021 
2029 NUMA *
2031  l_int32 *tab8)
2032 {
2033 l_int32 h, i, count;
2034 l_int32 *tab;
2035 NUMA *na;
2036 
2037  PROCNAME("pixCountPixelsByRow");
2038 
2039  if (!pix || pixGetDepth(pix) != 1)
2040  return (NUMA *)ERROR_PTR("pix undefined or not 1 bpp", procName, NULL);
2041 
2042  h = pixGetHeight(pix);
2043  if ((na = numaCreate(h)) == NULL)
2044  return (NUMA *)ERROR_PTR("na not made", procName, NULL);
2045 
2046  tab = (tab8) ? tab8 : makePixelSumTab8();
2047  for (i = 0; i < h; i++) {
2048  pixCountPixelsInRow(pix, i, &count, tab);
2049  numaAddNumber(na, count);
2050  }
2051 
2052  if (!tab8) LEPT_FREE(tab);
2053  return na;
2054 }
2055 
2056 
2063 NUMA *
2065 {
2066 l_int32 i, j, w, h, wpl;
2067 l_uint32 *line, *data;
2068 l_float32 *array;
2069 NUMA *na;
2070 
2071  PROCNAME("pixCountPixelsByColumn");
2072 
2073  if (!pix || pixGetDepth(pix) != 1)
2074  return (NUMA *)ERROR_PTR("pix undefined or not 1 bpp", procName, NULL);
2075 
2076  pixGetDimensions(pix, &w, &h, NULL);
2077  if ((na = numaCreate(w)) == NULL)
2078  return (NUMA *)ERROR_PTR("na not made", procName, NULL);
2079  numaSetCount(na, w);
2080  array = numaGetFArray(na, L_NOCOPY);
2081  data = pixGetData(pix);
2082  wpl = pixGetWpl(pix);
2083  for (i = 0; i < h; i++) {
2084  line = data + wpl * i;
2085  for (j = 0; j < w; j++) {
2086  if (GET_DATA_BIT(line, j))
2087  array[j] += 1.0;
2088  }
2089  }
2090 
2091  return na;
2092 }
2093 
2094 
2104 l_int32
2106  l_int32 row,
2107  l_int32 *pcount,
2108  l_int32 *tab8)
2109 {
2110 l_uint32 word, endmask;
2111 l_int32 j, w, h, wpl;
2112 l_int32 fullwords, endbits, sum;
2113 l_int32 *tab;
2114 l_uint32 *line;
2115 
2116  PROCNAME("pixCountPixelsInRow");
2117 
2118  if (!pcount)
2119  return ERROR_INT("&count not defined", procName, 1);
2120  *pcount = 0;
2121  if (!pix || pixGetDepth(pix) != 1)
2122  return ERROR_INT("pix not defined or not 1 bpp", procName, 1);
2123 
2124  pixGetDimensions(pix, &w, &h, NULL);
2125  if (row < 0 || row >= h)
2126  return ERROR_INT("row out of bounds", procName, 1);
2127  wpl = pixGetWpl(pix);
2128  line = pixGetData(pix) + row * wpl;
2129  fullwords = w >> 5;
2130  endbits = w & 31;
2131  endmask = (endbits == 0) ? 0 : (0xffffffffU << (32 - endbits));
2132 
2133  tab = (tab8) ? tab8 : makePixelSumTab8();
2134  sum = 0;
2135  for (j = 0; j < fullwords; j++) {
2136  word = line[j];
2137  if (word) {
2138  sum += tab[word & 0xff] +
2139  tab[(word >> 8) & 0xff] +
2140  tab[(word >> 16) & 0xff] +
2141  tab[(word >> 24) & 0xff];
2142  }
2143  }
2144  if (endbits) {
2145  word = line[j] & endmask;
2146  if (word) {
2147  sum += tab[word & 0xff] +
2148  tab[(word >> 8) & 0xff] +
2149  tab[(word >> 16) & 0xff] +
2150  tab[(word >> 24) & 0xff];
2151  }
2152  }
2153  *pcount = sum;
2154 
2155  if (!tab8) LEPT_FREE(tab);
2156  return 0;
2157 }
2158 
2159 
2167 NUMA *
2169  l_int32 order)
2170 {
2171 l_int32 i, j, w, h, wpl;
2172 l_uint32 *line, *data;
2173 l_float32 *array;
2174 NUMA *na;
2175 
2176  PROCNAME("pixGetMomentByColumn");
2177 
2178  if (!pix || pixGetDepth(pix) != 1)
2179  return (NUMA *)ERROR_PTR("pix undefined or not 1 bpp", procName, NULL);
2180  if (order != 1 && order != 2)
2181  return (NUMA *)ERROR_PTR("order of moment not 1 or 2", procName, NULL);
2182 
2183  pixGetDimensions(pix, &w, &h, NULL);
2184  if ((na = numaCreate(w)) == NULL)
2185  return (NUMA *)ERROR_PTR("na not made", procName, NULL);
2186  numaSetCount(na, w);
2187  array = numaGetFArray(na, L_NOCOPY);
2188  data = pixGetData(pix);
2189  wpl = pixGetWpl(pix);
2190  for (i = 0; i < h; i++) {
2191  line = data + wpl * i;
2192  for (j = 0; j < w; j++) {
2193  if (GET_DATA_BIT(line, j)) {
2194  if (order == 1)
2195  array[j] += i;
2196  else /* order == 2 */
2197  array[j] += i * i;
2198  }
2199  }
2200  }
2201 
2202  return na;
2203 }
2204 
2205 
2225 l_int32
2227  l_int32 thresh,
2228  l_int32 *pabove,
2229  l_int32 *tab8)
2230 {
2231 l_uint32 word, endmask;
2232 l_int32 *tab;
2233 l_int32 w, h, wpl, i, j;
2234 l_int32 fullwords, endbits, sum;
2235 l_uint32 *line, *data;
2236 
2237  PROCNAME("pixThresholdPixelSum");
2238 
2239  if (!pabove)
2240  return ERROR_INT("&above not defined", procName, 1);
2241  *pabove = 0;
2242  if (!pix || pixGetDepth(pix) != 1)
2243  return ERROR_INT("pix not defined or not 1 bpp", procName, 1);
2244 
2245  tab = (tab8) ? tab8 : makePixelSumTab8();
2246  pixGetDimensions(pix, &w, &h, NULL);
2247  wpl = pixGetWpl(pix);
2248  data = pixGetData(pix);
2249  fullwords = w >> 5;
2250  endbits = w & 31;
2251  endmask = 0xffffffff << (32 - endbits);
2252 
2253  sum = 0;
2254  for (i = 0; i < h; i++) {
2255  line = data + wpl * i;
2256  for (j = 0; j < fullwords; j++) {
2257  word = line[j];
2258  if (word) {
2259  sum += tab[word & 0xff] +
2260  tab[(word >> 8) & 0xff] +
2261  tab[(word >> 16) & 0xff] +
2262  tab[(word >> 24) & 0xff];
2263  }
2264  }
2265  if (endbits) {
2266  word = line[j] & endmask;
2267  if (word) {
2268  sum += tab[word & 0xff] +
2269  tab[(word >> 8) & 0xff] +
2270  tab[(word >> 16) & 0xff] +
2271  tab[(word >> 24) & 0xff];
2272  }
2273  }
2274  if (sum > thresh) {
2275  *pabove = 1;
2276  if (!tab8) LEPT_FREE(tab);
2277  return 0;
2278  }
2279  }
2280 
2281  if (!tab8) LEPT_FREE(tab);
2282  return 0;
2283 }
2284 
2285 
2297 l_int32 *
2299 {
2300 l_uint8 byte;
2301 l_int32 i;
2302 l_int32 *tab;
2303 
2304  PROCNAME("makePixelSumTab8");
2305 
2306  if ((tab = (l_int32 *)LEPT_CALLOC(256, sizeof(l_int32))) == NULL)
2307  return (l_int32 *)ERROR_PTR("tab not made", procName, NULL);
2308 
2309  for (i = 0; i < 256; i++) {
2310  byte = (l_uint8)i;
2311  tab[i] = (byte & 0x1) +
2312  ((byte >> 1) & 0x1) +
2313  ((byte >> 2) & 0x1) +
2314  ((byte >> 3) & 0x1) +
2315  ((byte >> 4) & 0x1) +
2316  ((byte >> 5) & 0x1) +
2317  ((byte >> 6) & 0x1) +
2318  ((byte >> 7) & 0x1);
2319  }
2320 
2321  return tab;
2322 }
2323 
2324 
2342 l_int32 *
2344 {
2345 l_int32 i;
2346 l_int32 *tab;
2347 
2348  PROCNAME("makePixelCentroidTab8");
2349 
2350  if ((tab = (l_int32 *)LEPT_CALLOC(256, sizeof(l_int32))) == NULL)
2351  return (l_int32 *)ERROR_PTR("tab not made", procName, NULL);
2352 
2353  tab[0] = 0;
2354  tab[1] = 7;
2355  for (i = 2; i < 4; i++) {
2356  tab[i] = tab[i - 2] + 6;
2357  }
2358  for (i = 4; i < 8; i++) {
2359  tab[i] = tab[i - 4] + 5;
2360  }
2361  for (i = 8; i < 16; i++) {
2362  tab[i] = tab[i - 8] + 4;
2363  }
2364  for (i = 16; i < 32; i++) {
2365  tab[i] = tab[i - 16] + 3;
2366  }
2367  for (i = 32; i < 64; i++) {
2368  tab[i] = tab[i - 32] + 2;
2369  }
2370  for (i = 64; i < 128; i++) {
2371  tab[i] = tab[i - 64] + 1;
2372  }
2373  for (i = 128; i < 256; i++) {
2374  tab[i] = tab[i - 128];
2375  }
2376 
2377  return tab;
2378 }
2379 
2380 
2381 /*-------------------------------------------------------------*
2382  * Average of pixel values in gray images *
2383  *-------------------------------------------------------------*/
2400 NUMA *
2402  BOX *box,
2403  l_int32 type)
2404 {
2405 l_int32 i, j, w, h, d, wpl, xstart, xend, ystart, yend, bw, bh;
2406 l_uint32 *line, *data;
2407 l_float64 norm, sum;
2408 NUMA *na;
2409 
2410  PROCNAME("pixAverageByRow");
2411 
2412  if (!pix)
2413  return (NUMA *)ERROR_PTR("pix not defined", procName, NULL);
2414  pixGetDimensions(pix, &w, &h, &d);
2415  if (d != 8 && d != 16)
2416  return (NUMA *)ERROR_PTR("pix not 8 or 16 bpp", procName, NULL);
2417  if (type != L_WHITE_IS_MAX && type != L_BLACK_IS_MAX)
2418  return (NUMA *)ERROR_PTR("invalid type", procName, NULL);
2419  if (pixGetColormap(pix) != NULL)
2420  return (NUMA *)ERROR_PTR("pix colormapped", procName, NULL);
2421 
2422  if (boxClipToRectangleParams(box, w, h, &xstart, &ystart, &xend, &yend,
2423  &bw, &bh) == 1)
2424  return (NUMA *)ERROR_PTR("invalid clipping box", procName, NULL);
2425 
2426  norm = 1. / (l_float32)bw;
2427  if ((na = numaCreate(bh)) == NULL)
2428  return (NUMA *)ERROR_PTR("na not made", procName, NULL);
2429  numaSetParameters(na, ystart, 1);
2430  data = pixGetData(pix);
2431  wpl = pixGetWpl(pix);
2432  for (i = ystart; i < yend; i++) {
2433  sum = 0.0;
2434  line = data + i * wpl;
2435  if (d == 8) {
2436  for (j = xstart; j < xend; j++)
2437  sum += GET_DATA_BYTE(line, j);
2438  if (type == L_BLACK_IS_MAX)
2439  sum = bw * 255 - sum;
2440  } else { /* d == 16 */
2441  for (j = xstart; j < xend; j++)
2442  sum += GET_DATA_TWO_BYTES(line, j);
2443  if (type == L_BLACK_IS_MAX)
2444  sum = bw * 0xffff - sum;
2445  }
2446  numaAddNumber(na, (l_float32)(norm * sum));
2447  }
2448 
2449  return na;
2450 }
2451 
2452 
2469 NUMA *
2471  BOX *box,
2472  l_int32 type)
2473 {
2474 l_int32 i, j, w, h, d, wpl, xstart, xend, ystart, yend, bw, bh;
2475 l_uint32 *line, *data;
2476 l_float32 norm, sum;
2477 NUMA *na;
2478 
2479  PROCNAME("pixAverageByColumn");
2480 
2481  if (!pix)
2482  return (NUMA *)ERROR_PTR("pix not defined", procName, NULL);
2483  pixGetDimensions(pix, &w, &h, &d);
2484 
2485  if (d != 8 && d != 16)
2486  return (NUMA *)ERROR_PTR("pix not 8 or 16 bpp", procName, NULL);
2487  if (type != L_WHITE_IS_MAX && type != L_BLACK_IS_MAX)
2488  return (NUMA *)ERROR_PTR("invalid type", procName, NULL);
2489  if (pixGetColormap(pix) != NULL)
2490  return (NUMA *)ERROR_PTR("pix colormapped", procName, NULL);
2491 
2492  if (boxClipToRectangleParams(box, w, h, &xstart, &ystart, &xend, &yend,
2493  &bw, &bh) == 1)
2494  return (NUMA *)ERROR_PTR("invalid clipping box", procName, NULL);
2495 
2496  if ((na = numaCreate(bw)) == NULL)
2497  return (NUMA *)ERROR_PTR("na not made", procName, NULL);
2498  numaSetParameters(na, xstart, 1);
2499  norm = 1. / (l_float32)bh;
2500  data = pixGetData(pix);
2501  wpl = pixGetWpl(pix);
2502  for (j = xstart; j < xend; j++) {
2503  sum = 0.0;
2504  if (d == 8) {
2505  for (i = ystart; i < yend; i++) {
2506  line = data + i * wpl;
2507  sum += GET_DATA_BYTE(line, j);
2508  }
2509  if (type == L_BLACK_IS_MAX)
2510  sum = bh * 255 - sum;
2511  } else { /* d == 16 */
2512  for (i = ystart; i < yend; i++) {
2513  line = data + i * wpl;
2514  sum += GET_DATA_TWO_BYTES(line, j);
2515  }
2516  if (type == L_BLACK_IS_MAX)
2517  sum = bh * 0xffff - sum;
2518  }
2519  numaAddNumber(na, (l_float32)(norm * sum));
2520  }
2521 
2522  return na;
2523 }
2524 
2525 
2534 l_int32
2536  BOX *box,
2537  l_float32 *pave)
2538 {
2539 l_int32 w, h, d, wpl, i, j, xstart, xend, ystart, yend, bw, bh;
2540 l_uint32 *data, *line;
2541 l_float64 ave;
2542 
2543  PROCNAME("pixAverageInRect");
2544 
2545  if (!pave)
2546  return ERROR_INT("&ave not defined", procName, 1);
2547  *pave = 0;
2548  if (!pix)
2549  return ERROR_INT("pix not defined", procName, 1);
2550  pixGetDimensions(pix, &w, &h, &d);
2551  if (d != 1 && d != 2 && d != 4 && d != 8)
2552  return ERROR_INT("pix not 1, 2, 4 or 8 bpp", procName, 1);
2553  if (pixGetColormap(pix) != NULL)
2554  return ERROR_INT("pix is colormapped", procName, 1);
2555 
2556  if (boxClipToRectangleParams(box, w, h, &xstart, &ystart, &xend, &yend,
2557  &bw, &bh) == 1)
2558  return ERROR_INT("invalid clipping box", procName, 1);
2559 
2560  wpl = pixGetWpl(pix);
2561  data = pixGetData(pix);
2562  ave = 0;
2563  for (i = ystart; i < yend; i++) {
2564  line = data + i * wpl;
2565  for (j = xstart; j < xend; j++) {
2566  if (d == 1)
2567  ave += GET_DATA_BIT(line, j);
2568  else if (d == 2)
2569  ave += GET_DATA_DIBIT(line, j);
2570  else if (d == 4)
2571  ave += GET_DATA_QBIT(line, j);
2572  else /* d == 8 */
2573  ave += GET_DATA_BYTE(line, j);
2574  }
2575  }
2576 
2577  *pave = ave / ((l_float32)(bw) * bh);
2578  return 0;
2579 }
2580 
2581 
2582 /*------------------------------------------------------------------*
2583  * Variance of pixel values in gray images *
2584  *------------------------------------------------------------------*/
2600 NUMA *
2602  BOX *box)
2603 {
2604 l_int32 i, j, w, h, d, wpl, xstart, xend, ystart, yend, bw, bh, val;
2605 l_uint32 *line, *data;
2606 l_float64 sum1, sum2, norm, ave, var, rootvar;
2607 NUMA *na;
2608 
2609  PROCNAME("pixVarianceByRow");
2610 
2611  if (!pix)
2612  return (NUMA *)ERROR_PTR("pix not defined", procName, NULL);
2613  pixGetDimensions(pix, &w, &h, &d);
2614  if (d != 8 && d != 16)
2615  return (NUMA *)ERROR_PTR("pix not 8 or 16 bpp", procName, NULL);
2616  if (pixGetColormap(pix) != NULL)
2617  return (NUMA *)ERROR_PTR("pix colormapped", procName, NULL);
2618 
2619  if (boxClipToRectangleParams(box, w, h, &xstart, &ystart, &xend, &yend,
2620  &bw, &bh) == 1)
2621  return (NUMA *)ERROR_PTR("invalid clipping box", procName, NULL);
2622 
2623  if ((na = numaCreate(bh)) == NULL)
2624  return (NUMA *)ERROR_PTR("na not made", procName, NULL);
2625  numaSetParameters(na, ystart, 1);
2626  norm = 1. / (l_float32)bw;
2627  data = pixGetData(pix);
2628  wpl = pixGetWpl(pix);
2629  for (i = ystart; i < yend; i++) {
2630  sum1 = sum2 = 0.0;
2631  line = data + i * wpl;
2632  for (j = xstart; j < xend; j++) {
2633  if (d == 8)
2634  val = GET_DATA_BYTE(line, j);
2635  else /* d == 16 */
2636  val = GET_DATA_TWO_BYTES(line, j);
2637  sum1 += val;
2638  sum2 += (l_float64)(val) * val;
2639  }
2640  ave = norm * sum1;
2641  var = norm * sum2 - ave * ave;
2642  rootvar = sqrt(var);
2643  numaAddNumber(na, (l_float32)rootvar);
2644  }
2645 
2646  return na;
2647 }
2648 
2649 
2665 NUMA *
2667  BOX *box)
2668 {
2669 l_int32 i, j, w, h, d, wpl, xstart, xend, ystart, yend, bw, bh, val;
2670 l_uint32 *line, *data;
2671 l_float64 sum1, sum2, norm, ave, var, rootvar;
2672 NUMA *na;
2673 
2674  PROCNAME("pixVarianceByColumn");
2675 
2676  if (!pix)
2677  return (NUMA *)ERROR_PTR("pix not defined", procName, NULL);
2678  pixGetDimensions(pix, &w, &h, &d);
2679  if (d != 8 && d != 16)
2680  return (NUMA *)ERROR_PTR("pix not 8 or 16 bpp", procName, NULL);
2681  if (pixGetColormap(pix) != NULL)
2682  return (NUMA *)ERROR_PTR("pix colormapped", procName, NULL);
2683 
2684  if (boxClipToRectangleParams(box, w, h, &xstart, &ystart, &xend, &yend,
2685  &bw, &bh) == 1)
2686  return (NUMA *)ERROR_PTR("invalid clipping box", procName, NULL);
2687 
2688  if ((na = numaCreate(bw)) == NULL)
2689  return (NUMA *)ERROR_PTR("na not made", procName, NULL);
2690  numaSetParameters(na, xstart, 1);
2691  norm = 1. / (l_float32)bh;
2692  data = pixGetData(pix);
2693  wpl = pixGetWpl(pix);
2694  for (j = xstart; j < xend; j++) {
2695  sum1 = sum2 = 0.0;
2696  for (i = ystart; i < yend; i++) {
2697  line = data + wpl * i;
2698  if (d == 8)
2699  val = GET_DATA_BYTE(line, j);
2700  else /* d == 16 */
2701  val = GET_DATA_TWO_BYTES(line, j);
2702  sum1 += val;
2703  sum2 += (l_float64)(val) * val;
2704  }
2705  ave = norm * sum1;
2706  var = norm * sum2 - ave * ave;
2707  rootvar = sqrt(var);
2708  numaAddNumber(na, (l_float32)rootvar);
2709  }
2710 
2711  return na;
2712 }
2713 
2714 
2723 l_int32
2725  BOX *box,
2726  l_float32 *prootvar)
2727 {
2728 l_int32 w, h, d, wpl, i, j, xstart, xend, ystart, yend, bw, bh, val;
2729 l_uint32 *data, *line;
2730 l_float64 sum1, sum2, norm, ave, var;
2731 
2732  PROCNAME("pixVarianceInRect");
2733 
2734  if (!prootvar)
2735  return ERROR_INT("&rootvar not defined", procName, 1);
2736  *prootvar = 0.0;
2737  if (!pix)
2738  return ERROR_INT("pix not defined", procName, 1);
2739  pixGetDimensions(pix, &w, &h, &d);
2740  if (d != 1 && d != 2 && d != 4 && d != 8)
2741  return ERROR_INT("pix not 1, 2, 4 or 8 bpp", procName, 1);
2742  if (pixGetColormap(pix) != NULL)
2743  return ERROR_INT("pix is colormapped", procName, 1);
2744 
2745  if (boxClipToRectangleParams(box, w, h, &xstart, &ystart, &xend, &yend,
2746  &bw, &bh) == 1)
2747  return ERROR_INT("invalid clipping box", procName, 1);
2748 
2749  wpl = pixGetWpl(pix);
2750  data = pixGetData(pix);
2751  sum1 = sum2 = 0.0;
2752  for (i = ystart; i < yend; i++) {
2753  line = data + i * wpl;
2754  for (j = xstart; j < xend; j++) {
2755  if (d == 1) {
2756  val = GET_DATA_BIT(line, j);
2757  sum1 += val;
2758  sum2 += (l_float64)(val) * val;
2759  } else if (d == 2) {
2760  val = GET_DATA_DIBIT(line, j);
2761  sum1 += val;
2762  sum2 += (l_float64)(val) * val;
2763  } else if (d == 4) {
2764  val = GET_DATA_QBIT(line, j);
2765  sum1 += val;
2766  sum2 += (l_float64)(val) * val;
2767  } else { /* d == 8 */
2768  val = GET_DATA_BYTE(line, j);
2769  sum1 += val;
2770  sum2 += (l_float64)(val) * val;
2771  }
2772  }
2773  }
2774  norm = 1.0 / ((l_float64)(bw) * bh);
2775  ave = norm * sum1;
2776  var = norm * sum2 - ave * ave;
2777  *prootvar = (l_float32)sqrt(var);
2778  return 0;
2779 }
2780 
2781 
2782 /*---------------------------------------------------------------------*
2783  * Average of absolute value of pixel differences in gray images *
2784  *---------------------------------------------------------------------*/
2800 NUMA *
2802  BOX *box)
2803 {
2804 l_int32 i, j, w, h, wpl, xstart, xend, ystart, yend, bw, bh, val0, val1;
2805 l_uint32 *line, *data;
2806 l_float64 norm, sum;
2807 NUMA *na;
2808 
2809  PROCNAME("pixAbsDiffByRow");
2810 
2811  if (!pix || pixGetDepth(pix) != 8)
2812  return (NUMA *)ERROR_PTR("pix undefined or not 8 bpp", procName, NULL);
2813  if (pixGetColormap(pix) != NULL)
2814  return (NUMA *)ERROR_PTR("pix colormapped", procName, NULL);
2815 
2816  pixGetDimensions(pix, &w, &h, NULL);
2817  if (boxClipToRectangleParams(box, w, h, &xstart, &ystart, &xend, &yend,
2818  &bw, &bh) == 1)
2819  return (NUMA *)ERROR_PTR("invalid clipping box", procName, NULL);
2820  if (bw < 2)
2821  return (NUMA *)ERROR_PTR("row width must be >= 2", procName, NULL);
2822 
2823  norm = 1. / (l_float32)(bw - 1);
2824  if ((na = numaCreate(bh)) == NULL)
2825  return (NUMA *)ERROR_PTR("na not made", procName, NULL);
2826  numaSetParameters(na, ystart, 1);
2827  data = pixGetData(pix);
2828  wpl = pixGetWpl(pix);
2829  for (i = ystart; i < yend; i++) {
2830  sum = 0.0;
2831  line = data + i * wpl;
2832  val0 = GET_DATA_BYTE(line, xstart);
2833  for (j = xstart + 1; j < xend; j++) {
2834  val1 = GET_DATA_BYTE(line, j);
2835  sum += L_ABS(val1 - val0);
2836  val0 = val1;
2837  }
2838  numaAddNumber(na, (l_float32)(norm * sum));
2839  }
2840 
2841  return na;
2842 }
2843 
2844 
2861 NUMA *
2863  BOX *box)
2864 {
2865 l_int32 i, j, w, h, wpl, xstart, xend, ystart, yend, bw, bh, val0, val1;
2866 l_uint32 *line, *data;
2867 l_float64 norm, sum;
2868 NUMA *na;
2869 
2870  PROCNAME("pixAbsDiffByColumn");
2871 
2872  if (!pix || pixGetDepth(pix) != 8)
2873  return (NUMA *)ERROR_PTR("pix undefined or not 8 bpp", procName, NULL);
2874  if (pixGetColormap(pix) != NULL)
2875  return (NUMA *)ERROR_PTR("pix colormapped", procName, NULL);
2876 
2877  pixGetDimensions(pix, &w, &h, NULL);
2878  if (boxClipToRectangleParams(box, w, h, &xstart, &ystart, &xend, &yend,
2879  &bw, &bh) == 1)
2880  return (NUMA *)ERROR_PTR("invalid clipping box", procName, NULL);
2881  if (bh < 2)
2882  return (NUMA *)ERROR_PTR("column height must be >= 2", procName, NULL);
2883 
2884  norm = 1. / (l_float32)(bh - 1);
2885  if ((na = numaCreate(bw)) == NULL)
2886  return (NUMA *)ERROR_PTR("na not made", procName, NULL);
2887  numaSetParameters(na, xstart, 1);
2888  data = pixGetData(pix);
2889  wpl = pixGetWpl(pix);
2890  for (j = xstart; j < xend; j++) {
2891  sum = 0.0;
2892  line = data + ystart * wpl;
2893  val0 = GET_DATA_BYTE(line, j);
2894  for (i = ystart + 1; i < yend; i++) {
2895  line = data + i * wpl;
2896  val1 = GET_DATA_BYTE(line, j);
2897  sum += L_ABS(val1 - val0);
2898  val0 = val1;
2899  }
2900  numaAddNumber(na, (l_float32)(norm * sum));
2901  }
2902 
2903  return na;
2904 }
2905 
2906 
2924 l_int32
2926  BOX *box,
2927  l_int32 dir,
2928  l_float32 *pabsdiff)
2929 {
2930 l_int32 w, h, wpl, i, j, xstart, xend, ystart, yend, bw, bh, val0, val1;
2931 l_uint32 *data, *line;
2932 l_float64 norm, sum;
2933 
2934  PROCNAME("pixAbsDiffInRect");
2935 
2936  if (!pabsdiff)
2937  return ERROR_INT("&absdiff not defined", procName, 1);
2938  *pabsdiff = 0.0;
2939  if (!pix || pixGetDepth(pix) != 8)
2940  return ERROR_INT("pix undefined or not 8 bpp", procName, 1);
2941  if (dir != L_HORIZONTAL_LINE && dir != L_VERTICAL_LINE)
2942  return ERROR_INT("invalid direction", procName, 1);
2943  if (pixGetColormap(pix) != NULL)
2944  return ERROR_INT("pix is colormapped", procName, 1);
2945 
2946  pixGetDimensions(pix, &w, &h, NULL);
2947  if (boxClipToRectangleParams(box, w, h, &xstart, &ystart, &xend, &yend,
2948  &bw, &bh) == 1)
2949  return ERROR_INT("invalid clipping box", procName, 1);
2950 
2951  wpl = pixGetWpl(pix);
2952  data = pixGetData(pix);
2953  if (dir == L_HORIZONTAL_LINE) {
2954  norm = 1. / (l_float32)(bh * (bw - 1));
2955  sum = 0.0;
2956  for (i = ystart; i < yend; i++) {
2957  line = data + i * wpl;
2958  val0 = GET_DATA_BYTE(line, xstart);
2959  for (j = xstart + 1; j < xend; j++) {
2960  val1 = GET_DATA_BYTE(line, j);
2961  sum += L_ABS(val1 - val0);
2962  val0 = val1;
2963  }
2964  }
2965  } else { /* vertical line */
2966  norm = 1. / (l_float32)(bw * (bh - 1));
2967  sum = 0.0;
2968  for (j = xstart; j < xend; j++) {
2969  line = data + ystart * wpl;
2970  val0 = GET_DATA_BYTE(line, j);
2971  for (i = ystart + 1; i < yend; i++) {
2972  line = data + i * wpl;
2973  val1 = GET_DATA_BYTE(line, j);
2974  sum += L_ABS(val1 - val0);
2975  val0 = val1;
2976  }
2977  }
2978  }
2979  *pabsdiff = (l_float32)(norm * sum);
2980  return 0;
2981 }
2982 
2983 
3001 l_int32
3003  l_int32 x1,
3004  l_int32 y1,
3005  l_int32 x2,
3006  l_int32 y2,
3007  l_float32 *pabsdiff)
3008 {
3009 l_int32 w, h, i, j, dir, size, sum;
3010 l_uint32 val0, val1;
3011 
3012  PROCNAME("pixAbsDiffOnLine");
3013 
3014  if (!pabsdiff)
3015  return ERROR_INT("&absdiff not defined", procName, 1);
3016  *pabsdiff = 0.0;
3017  if (!pix || pixGetDepth(pix) != 8)
3018  return ERROR_INT("pix undefined or not 8 bpp", procName, 1);
3019  if (y1 == y2) {
3020  dir = L_HORIZONTAL_LINE;
3021  } else if (x1 == x2) {
3022  dir = L_VERTICAL_LINE;
3023  } else {
3024  return ERROR_INT("line is neither horiz nor vert", procName, 1);
3025  }
3026  if (pixGetColormap(pix) != NULL)
3027  return ERROR_INT("pix is colormapped", procName, 1);
3028 
3029  pixGetDimensions(pix, &w, &h, NULL);
3030  sum = 0;
3031  if (dir == L_HORIZONTAL_LINE) {
3032  x1 = L_MAX(x1, 0);
3033  x2 = L_MIN(x2, w - 1);
3034  if (x1 >= x2)
3035  return ERROR_INT("x1 >= x2", procName, 1);
3036  size = x2 - x1;
3037  pixGetPixel(pix, x1, y1, &val0);
3038  for (j = x1 + 1; j <= x2; j++) {
3039  pixGetPixel(pix, j, y1, &val1);
3040  sum += L_ABS((l_int32)val1 - (l_int32)val0);
3041  val0 = val1;
3042  }
3043  } else { /* vertical */
3044  y1 = L_MAX(y1, 0);
3045  y2 = L_MIN(y2, h - 1);
3046  if (y1 >= y2)
3047  return ERROR_INT("y1 >= y2", procName, 1);
3048  size = y2 - y1;
3049  pixGetPixel(pix, x1, y1, &val0);
3050  for (i = y1 + 1; i <= y2; i++) {
3051  pixGetPixel(pix, x1, i, &val1);
3052  sum += L_ABS((l_int32)val1 - (l_int32)val0);
3053  val0 = val1;
3054  }
3055  }
3056  *pabsdiff = (l_float32)sum / (l_float32)size;
3057  return 0;
3058 }
3059 
3060 
3061 /*-------------------------------------------------------------*
3062  * Count of pixels with specific value *
3063  *-------------------------------------------------------------*/
3083 l_int32
3085  BOX *box,
3086  l_int32 val,
3087  l_int32 factor,
3088  l_int32 *pcount)
3089 {
3090 l_int32 i, j, bx, by, bw, bh, w, h, wpl, pixval;
3091 l_uint32 *data, *line;
3092 
3093  PROCNAME("pixCountArbInRect");
3094 
3095  if (!pcount)
3096  return ERROR_INT("&count not defined", procName, 1);
3097  *pcount = 0;
3098  if (!pixs)
3099  return ERROR_INT("pixs not defined", procName, 1);
3100  if (pixGetDepth(pixs) != 8 && !pixGetColormap(pixs))
3101  return ERROR_INT("pixs neither 8 bpp nor colormapped",
3102  procName, 1);
3103  if (factor < 1)
3104  return ERROR_INT("sampling factor < 1", procName, 1);
3105 
3106  pixGetDimensions(pixs, &w, &h, NULL);
3107  data = pixGetData(pixs);
3108  wpl = pixGetWpl(pixs);
3109 
3110  if (!box) {
3111  for (i = 0; i < h; i += factor) {
3112  line = data + i * wpl;
3113  for (j = 0; j < w; j += factor) {
3114  pixval = GET_DATA_BYTE(line, j);
3115  if (pixval == val) (*pcount)++;
3116  }
3117  }
3118  } else {
3119  boxGetGeometry(box, &bx, &by, &bw, &bh);
3120  for (i = 0; i < bh; i += factor) {
3121  if (by + i < 0 || by + i >= h) continue;
3122  line = data + (by + i) * wpl;
3123  for (j = 0; j < bw; j += factor) {
3124  if (bx + j < 0 || bx + j >= w) continue;
3125  pixval = GET_DATA_BYTE(line, bx + j);
3126  if (pixval == val) (*pcount)++;
3127  }
3128  }
3129  }
3130 
3131  if (factor > 1) /* assume pixel color is randomly distributed */
3132  *pcount = *pcount * factor * factor;
3133  return 0;
3134 }
3135 
3136 
3137 /*-------------------------------------------------------------*
3138  * Mirrored tiling of a smaller image *
3139  *-------------------------------------------------------------*/
3161 PIX *
3163  l_int32 w,
3164  l_int32 h)
3165 {
3166 l_int32 wt, ht, d, i, j, nx, ny;
3167 PIX *pixd, *pixsfx, *pixsfy, *pixsfxy, *pix;
3168 
3169  PROCNAME("pixMirroredTiling");
3170 
3171  if (!pixs)
3172  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
3173  pixGetDimensions(pixs, &wt, &ht, &d);
3174  if (wt <= 0 || ht <= 0)
3175  return (PIX *)ERROR_PTR("pixs size illegal", procName, NULL);
3176  if (d != 8 && d != 32)
3177  return (PIX *)ERROR_PTR("depth not 32 bpp", procName, NULL);
3178 
3179  if ((pixd = pixCreate(w, h, d)) == NULL)
3180  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
3181  pixCopySpp(pixd, pixs);
3182 
3183  nx = (w + wt - 1) / wt;
3184  ny = (h + ht - 1) / ht;
3185  pixsfx = pixFlipLR(NULL, pixs);
3186  pixsfy = pixFlipTB(NULL, pixs);
3187  pixsfxy = pixFlipTB(NULL, pixsfx);
3188  for (i = 0; i < ny; i++) {
3189  for (j = 0; j < nx; j++) {
3190  pix = pixs;
3191  if ((i & 1) && !(j & 1))
3192  pix = pixsfy;
3193  else if (!(i & 1) && (j & 1))
3194  pix = pixsfx;
3195  else if ((i & 1) && (j & 1))
3196  pix = pixsfxy;
3197  pixRasterop(pixd, j * wt, i * ht, wt, ht, PIX_SRC, pix, 0, 0);
3198  }
3199  }
3200 
3201  pixDestroy(&pixsfx);
3202  pixDestroy(&pixsfy);
3203  pixDestroy(&pixsfxy);
3204  return pixd;
3205 }
3206 
3207 
3236 l_int32
3238  BOX *box,
3239  l_int32 searchdir,
3240  l_int32 mindist,
3241  l_int32 tsize,
3242  l_int32 ntiles,
3243  BOX **pboxtile,
3244  l_int32 debug)
3245 {
3246 l_int32 w, h, i, n, bestindex;
3247 l_float32 var_of_mean, median_of_mean, median_of_stdev, mean_val, stdev_val;
3248 l_float32 mindels, bestdelm, delm, dels, mean, stdev;
3249 BOXA *boxa;
3250 NUMA *namean, *nastdev;
3251 PIX *pix, *pixg;
3252 PIXA *pixa;
3253 
3254  PROCNAME("pixFindRepCloseTile");
3255 
3256  if (!pboxtile)
3257  return ERROR_INT("&boxtile not defined", procName, 1);
3258  *pboxtile = NULL;
3259  if (!pixs)
3260  return ERROR_INT("pixs not defined", procName, 1);
3261  if (!box)
3262  return ERROR_INT("box not defined", procName, 1);
3263  if (searchdir != L_HORIZ && searchdir != L_VERT)
3264  return ERROR_INT("invalid searchdir", procName, 1);
3265  if (mindist < 0)
3266  return ERROR_INT("mindist must be >= 0", procName, 1);
3267  if (tsize < 2)
3268  return ERROR_INT("tsize must be > 1", procName, 1);
3269  if (ntiles > 7) {
3270  L_WARNING("ntiles = %d; larger than suggested max of 7\n",
3271  procName, ntiles);
3272  }
3273 
3274  /* Locate tile regions */
3275  pixGetDimensions(pixs, &w, &h, NULL);
3276  boxa = findTileRegionsForSearch(box, w, h, searchdir, mindist,
3277  tsize, ntiles);
3278  if (!boxa)
3279  return ERROR_INT("no tiles found", procName, 1);
3280 
3281  /* Generate the tiles and the mean and stdev of intensity */
3282  pixa = pixClipRectangles(pixs, boxa);
3283  n = pixaGetCount(pixa);
3284  namean = numaCreate(n);
3285  nastdev = numaCreate(n);
3286  for (i = 0; i < n; i++) {
3287  pix = pixaGetPix(pixa, i, L_CLONE);
3288  pixg = pixConvertRGBToGray(pix, 0.33, 0.34, 0.33);
3289  pixGetAverageMasked(pixg, NULL, 0, 0, 1, L_MEAN_ABSVAL, &mean);
3290  pixGetAverageMasked(pixg, NULL, 0, 0, 1, L_STANDARD_DEVIATION, &stdev);
3291  numaAddNumber(namean, mean);
3292  numaAddNumber(nastdev, stdev);
3293  pixDestroy(&pix);
3294  pixDestroy(&pixg);
3295  }
3296 
3297  /* Find the median and variance of the averages. We require
3298  * the best tile to have a mean pixel intensity within a standard
3299  * deviation of the median of mean intensities, and choose the
3300  * tile in that set with the smallest stdev of pixel intensities
3301  * (as a proxy for the tile with least visible structure).
3302  * The median of the stdev is used, for debugging, as a normalizing
3303  * factor for the stdev of intensities within a tile. */
3304  numaGetStatsUsingHistogram(namean, 256, NULL, NULL, NULL, &var_of_mean,
3305  &median_of_mean, 0.0, NULL, NULL);
3306  numaGetStatsUsingHistogram(nastdev, 256, NULL, NULL, NULL, NULL,
3307  &median_of_stdev, 0.0, NULL, NULL);
3308  mindels = 1000.0;
3309  bestdelm = 1000.0;
3310  bestindex = 0;
3311  for (i = 0; i < n; i++) {
3312  numaGetFValue(namean, i, &mean_val);
3313  numaGetFValue(nastdev, i, &stdev_val);
3314  if (var_of_mean == 0.0) { /* uniform color; any box will do */
3315  delm = 0.0; /* any value < 1.01 */
3316  dels = 1.0; /* n'importe quoi */
3317  } else {
3318  delm = L_ABS(mean_val - median_of_mean) / sqrt(var_of_mean);
3319  dels = stdev_val / median_of_stdev;
3320  }
3321  if (delm < 1.01) {
3322  if (dels < mindels) {
3323  if (debug) {
3324  fprintf(stderr, "i = %d, mean = %7.3f, delm = %7.3f,"
3325  " stdev = %7.3f, dels = %7.3f\n",
3326  i, mean_val, delm, stdev_val, dels);
3327  }
3328  mindels = dels;
3329  bestdelm = delm;
3330  bestindex = i;
3331  }
3332  }
3333  }
3334  *pboxtile = boxaGetBox(boxa, bestindex, L_COPY);
3335 
3336  if (debug) {
3337  L_INFO("median of mean = %7.3f\n", procName, median_of_mean);
3338  L_INFO("standard dev of mean = %7.3f\n", procName, sqrt(var_of_mean));
3339  L_INFO("median of stdev = %7.3f\n", procName, median_of_stdev);
3340  L_INFO("best tile: index = %d\n", procName, bestindex);
3341  L_INFO("delta from median in units of stdev = %5.3f\n",
3342  procName, bestdelm);
3343  L_INFO("stdev as fraction of median stdev = %5.3f\n",
3344  procName, mindels);
3345  }
3346 
3347  numaDestroy(&namean);
3348  numaDestroy(&nastdev);
3349  pixaDestroy(&pixa);
3350  boxaDestroy(&boxa);
3351  return 0;
3352 }
3353 
3354 
3371 static BOXA *
3373  l_int32 w,
3374  l_int32 h,
3375  l_int32 searchdir,
3376  l_int32 mindist,
3377  l_int32 tsize,
3378  l_int32 ntiles)
3379 {
3380 l_int32 bx, by, bw, bh, left, right, top, bot, i, j, nrows, ncols;
3381 l_int32 x0, y0, x, y, w_avail, w_needed, h_avail, h_needed, t_avail;
3382 BOX *box1;
3383 BOXA *boxa;
3384 
3385  PROCNAME("findTileRegionsForSearch");
3386 
3387  if (!box)
3388  return (BOXA *)ERROR_PTR("box not defined", procName, NULL);
3389  if (ntiles == 0)
3390  return (BOXA *)ERROR_PTR("no tiles requested", procName, NULL);
3391 
3392  boxGetGeometry(box, &bx, &by, &bw, &bh);
3393  if (searchdir == L_HORIZ) {
3394  /* Find the tile parameters for the search. Note that the
3395  * tiles are overlapping by 50% in each direction. */
3396  left = bx; /* distance to left of box */
3397  right = w - bx - bw + 1; /* distance to right of box */
3398  w_avail = L_MAX(left, right) - mindist;
3399  if (tsize & 1) tsize++; /* be sure it's even */
3400  if (w_avail < tsize) {
3401  L_ERROR("tsize = %d, w_avail = %d\n", procName, tsize, w_avail);
3402  return NULL;
3403  }
3404  w_needed = tsize + (ntiles - 1) * (tsize / 2);
3405  if (w_needed > w_avail) {
3406  t_avail = 1 + 2 * (w_avail - tsize) / tsize;
3407  L_WARNING("ntiles = %d; room for only %d\n", procName,
3408  ntiles, t_avail);
3409  ntiles = t_avail;
3410  w_needed = tsize + (ntiles - 1) * (tsize / 2);
3411  }
3412  nrows = L_MAX(1, 1 + 2 * (bh - tsize) / tsize);
3413 
3414  /* Generate the tile regions to search */
3415  boxa = boxaCreate(0);
3416  if (left > right) /* search to left */
3417  x0 = bx - w_needed;
3418  else /* search to right */
3419  x0 = bx + bw + mindist;
3420  for (i = 0; i < nrows; i++) {
3421  y = by + i * tsize / 2;
3422  for (j = 0; j < ntiles; j++) {
3423  x = x0 + j * tsize / 2;
3424  box1 = boxCreate(x, y, tsize, tsize);
3425  boxaAddBox(boxa, box1, L_INSERT);
3426  }
3427  }
3428  } else { /* L_VERT */
3429  /* Find the tile parameters for the search */
3430  top = by; /* distance above box */
3431  bot = h - by - bh + 1; /* distance below box */
3432  h_avail = L_MAX(top, bot) - mindist;
3433  if (h_avail < tsize) {
3434  L_ERROR("tsize = %d, h_avail = %d\n", procName, tsize, h_avail);
3435  return NULL;
3436  }
3437  h_needed = tsize + (ntiles - 1) * (tsize / 2);
3438  if (h_needed > h_avail) {
3439  t_avail = 1 + 2 * (h_avail - tsize) / tsize;
3440  L_WARNING("ntiles = %d; room for only %d\n", procName,
3441  ntiles, t_avail);
3442  ntiles = t_avail;
3443  h_needed = tsize + (ntiles - 1) * (tsize / 2);
3444  }
3445  ncols = L_MAX(1, 1 + 2 * (bw - tsize) / tsize);
3446 
3447  /* Generate the tile regions to search */
3448  boxa = boxaCreate(0);
3449  if (top > bot) /* search above */
3450  y0 = by - h_needed;
3451  else /* search below */
3452  y0 = by + bh + mindist;
3453  for (j = 0; j < ncols; j++) {
3454  x = bx + j * tsize / 2;
3455  for (i = 0; i < ntiles; i++) {
3456  y = y0 + i * tsize / 2;
3457  box1 = boxCreate(x, y, tsize, tsize);
3458  boxaAddBox(boxa, box1, L_INSERT);
3459  }
3460  }
3461  }
3462  return boxa;
3463 }
PIX * pixFlipLR(PIX *pixd, PIX *pixs)
pixFlipLR()
Definition: rotateorth.c:423
NUMA * pixCountPixelsByRow(PIX *pix, l_int32 *tab8)
pixCountPixelsByRow()
Definition: pix3.c:2030
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:1932
NUMA * pixCountPixelsByColumn(PIX *pix)
pixCountPixelsByColumn()
Definition: pix3.c:2064
l_int32 numaSetCount(NUMA *na, l_int32 newcount)
numaSetCount()
Definition: numabasic.c:657
l_int32 pixSetMaskedGeneral(PIX *pixd, PIX *pixm, l_uint32 val, l_int32 x, l_int32 y)
pixSetMaskedGeneral()
Definition: pix3.c:294
l_int32 lept_mkdir(const char *subdir)
lept_mkdir()
Definition: utils2.c:1880
l_int32 numaAddNumber(NUMA *na, l_float32 val)
numaAddNumber()
Definition: numabasic.c:472
l_int32 * makePixelCentroidTab8(void)
makePixelCentroidTab8()
Definition: pix3.c:2343
NUMA * pixVarianceByRow(PIX *pix, BOX *box)
pixVarianceByRow()
Definition: pix3.c:2601
l_int32 pixGetPixel(PIX *pix, l_int32 x, l_int32 y, l_uint32 *pval)
pixGetPixel()
Definition: pix2.c:180
l_int32 pixZero(PIX *pix, l_int32 *pempty)
pixZero()
Definition: pix3.c:1702
l_int32 pixAverageInRect(PIX *pix, BOX *box, l_float32 *pave)
pixAverageInRect()
Definition: pix3.c:2535
Definition: pix.h:704
l_int32 pixSetAllArbitrary(PIX *pix, l_uint32 val)
pixSetAllArbitrary()
Definition: pix2.c:864
l_int32 pixSetMasked(PIX *pixd, PIX *pixm, l_uint32 val)
pixSetMasked()
Definition: pix3.c:155
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:3372
PIX * pixMakeAlphaFromMask(PIX *pixs, l_int32 dist, BOX **pbox)
pixMakeAlphaFromMask()
Definition: pix3.c:1222
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:3084
l_int32 pixGetColorNearMaskBoundary(PIX *pixs, PIX *pixm, BOX *box, l_int32 dist, l_uint32 *pval, l_int32 debug)
pixGetColorNearMaskBoundary()
Definition: pix3.c:1291
l_int32 boxaAddBox(BOXA *boxa, BOX *box, l_int32 copyflag)
boxaAddBox()
Definition: boxbasic.c:615
l_int32 numaGetFValue(NUMA *na, l_int32 index, l_float32 *pval)
numaGetFValue()
Definition: numabasic.c:691
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
PIX * pixInvert(PIX *pixd, PIX *pixs)
pixInvert()
Definition: pix3.c:1395
#define SET_DATA_QBIT(pdata, n, val)
Definition: arrayaccess.h:162
NUMA * numaCreate(l_int32 n)
numaCreate()
Definition: numabasic.c:186
void boxaDestroy(BOXA **pboxa)
boxaDestroy()
Definition: boxbasic.c:577
l_uint32 * pixGetData(PIX *pix)
pixGetData()
Definition: pix1.c:1602
BOX * pixaGetBox(PIXA *pixa, l_int32 index, l_int32 accesstype)
pixaGetBox()
Definition: pixabasic.c:785
l_int32 boxPrintStreamInfo(FILE *fp, BOX *box)
boxPrintStreamInfo()
Definition: boxbasic.c:2323
l_int32 pixCountPixelsInRect(PIX *pixs, BOX *box, l_int32 *pcount, l_int32 *tab8)
pixCountPixelsInRect()
Definition: pix3.c:1888
PIX * pixThresholdToBinary(PIX *pixs, l_int32 thresh)
pixThresholdToBinary()
Definition: grayquant.c:443
#define GET_DATA_BIT(pdata, n)
Definition: arrayaccess.h:117
PIX * pixCreateTemplate(PIX *pixs)
pixCreateTemplate()
Definition: pix1.c:367
PIX * pixClipRectangle(PIX *pixs, BOX *box, BOX **pboxc)
pixClipRectangle()
Definition: pix5.c:1013
Definition: pix.h:492
PIX * pixGetRGBComponent(PIX *pixs, l_int32 comp)
pixGetRGBComponent()
Definition: pix2.c:2392
#define SET_DATA_DIBIT(pdata, n, val)
Definition: arrayaccess.h:143
#define PIX_MASK
Definition: pix.h:334
PIX * pixMakeMaskFromVal(PIX *pixs, l_int32 val)
pixMakeMaskFromVal()
Definition: pix3.c:943
l_int32 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 * 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:144
PIX * pixFlipTB(PIX *pixd, PIX *pixs)
pixFlipTB()
Definition: rotateorth.c:601
Definition: array.h:59
l_int32 pixCopySpp(PIX *pixd, PIX *pixs)
pixCopySpp()
Definition: pix1.c:1172
static const l_int32 L_INSERT
Definition: pix.h:710
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_int32 pixForegroundFraction(PIX *pix, l_float32 *pfract)
pixForegroundFraction()
Definition: pix3.c:1752
PIX * pixAnd(PIX *pixd, PIX *pixs1, PIX *pixs2)
pixAnd()
Definition: pix3.c:1510
NUMA * pixAbsDiffByRow(PIX *pix, BOX *box)
pixAbsDiffByRow()
Definition: pix3.c:2801
l_int32 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
PIX * pixMorphSequence(PIX *pixs, const char *sequence, l_int32 dispsep)
pixMorphSequence()
Definition: morphseq.c:133
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:2298
l_int32 pixMultConstantGray(PIX *pixs, l_float32 val)
pixMultConstantGray()
Definition: pixarith.c:186
#define SET_DATA_BYTE(pdata, n, val)
Definition: arrayaccess.h:192
PIXA * pixClipRectangles(PIX *pixs, BOXA *boxa)
pixClipRectangles()
Definition: pix5.c:947
l_int32 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:3237
l_int32 boxGetGeometry(BOX *box, l_int32 *px, l_int32 *py, l_int32 *pw, l_int32 *ph)
boxGetGeometry()
Definition: boxbasic.c:309
#define GET_DATA_QBIT(pdata, n)
Definition: arrayaccess.h:158
BOX * boxAdjustSides(BOX *boxd, BOX *boxs, l_int32 delleft, l_int32 delright, l_int32 deltop, l_int32 delbot)
boxAdjustSides()
Definition: boxfunc1.c:1807
l_int32 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
l_int32 pixSizesEqual(PIX *pix1, PIX *pix2)
pixSizesEqual()
Definition: pix1.c:768
#define GET_DATA_BYTE(pdata, n)
Definition: arrayaccess.h:182
#define PIX_PAINT
Definition: pix.h:333
NUMA * pixAbsDiffByColumn(PIX *pix, BOX *box)
pixAbsDiffByColumn()
Definition: pix3.c:2862
NUMA * pixAverageByColumn(PIX *pix, BOX *box, l_int32 type)
pixAverageByColumn()
Definition: pix3.c:2470
PIX * pixClone(PIX *pixs)
pixClone()
Definition: pix1.c:517
PIX * pixSubtract(PIX *pixd, PIX *pixs1, PIX *pixs2)
pixSubtract()
Definition: pix3.c:1639
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:545
BOX * boxaGetBox(BOXA *boxa, l_int32 index, l_int32 accessflag)
boxaGetBox()
Definition: boxbasic.c:760
NUMA * pixGetMomentByColumn(PIX *pix, l_int32 order)
pixGetMomentByColumn()
Definition: pix3.c:2168
l_int32 numaSetParameters(NUMA *na, l_float32 startx, l_float32 delx)
numaSetParameters()
Definition: numabasic.c:965
PIX * pixMakeArbMaskFromRGB(PIX *pixs, l_float32 rc, l_float32 gc, l_float32 bc, l_float32 thresh)
pixMakeArbMaskFromRGB()
Definition: pix3.c:1069
l_int32 pixCombineMasked(PIX *pixd, PIX *pixs, PIX *pixm)
pixCombineMasked()
Definition: pix3.c:374
Definition: pix.h:454
l_int32 pixAbsDiffOnLine(PIX *pix, l_int32 x1, l_int32 y1, l_int32 x2, l_int32 y2, l_float32 *pabsdiff)
pixAbsDiffOnLine()
Definition: pix3.c:3002
l_int32 pixPaintThroughMask(PIX *pixd, PIX *pixm, l_int32 x, l_int32 y, l_uint32 val)
pixPaintThroughMask()
Definition: pix3.c:618
l_int32 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
void numaDestroy(NUMA **pna)
numaDestroy()
Definition: numabasic.c:359
l_int32 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:1235
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:1984
NUMA * pixaCountPixels(PIXA *pixa)
pixaCountPixels()
Definition: pix3.c:1779
l_int32 pixCombineMaskedGeneral(PIX *pixd, PIX *pixs, PIX *pixm, l_int32 x, l_int32 y)
pixCombineMaskedGeneral()
Definition: pix3.c:493
NUMA * pixVarianceByColumn(PIX *pix, BOX *box)
pixVarianceByColumn()
Definition: pix3.c:2666
PIX * pixConvertRGBToGrayArb(PIX *pixs, l_float32 rc, l_float32 gc, l_float32 bc)
pixConvertRGBToGrayArb()
Definition: pixconv.c:1052
l_int32 pixAbsDiffInRect(PIX *pix, BOX *box, l_int32 dir, l_float32 *pabsdiff)
pixAbsDiffInRect()
Definition: pix3.c:2925
l_float32 * numaGetFArray(NUMA *na, l_int32 copyflag)
numaGetFArray()
Definition: numabasic.c:864
#define GET_DATA_TWO_BYTES(pdata, n)
Definition: arrayaccess.h:206
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:139
PIX * pixMirroredTiling(PIX *pixs, l_int32 w, l_int32 h)
pixMirroredTiling()
Definition: pix3.c:3162
PIX * pixaGetPix(PIXA *pixa, l_int32 index, l_int32 accesstype)
pixaGetPix()
Definition: pixabasic.c:660
Definition: pix.h:705
l_int32 composeRGBPixel(l_int32 rval, l_int32 gval, l_int32 bval, l_uint32 *ppixel)
composeRGBPixel()
Definition: pix2.c:2659
PIX * pixMakeMaskFromLUT(PIX *pixs, l_int32 *tab)
pixMakeMaskFromLUT()
Definition: pix3.c:1000
#define PIX_NOT(op)
Definition: pix.h:329
l_int32 pixClipToForeground(PIX *pixs, PIX **ppixd, BOX **pbox)
pixClipToForeground()
Definition: pix5.c:1455
PIX * pixDisplayLayersRGBA(PIX *pixs, l_uint32 val, l_int32 maxw)
pixDisplayLayersRGBA()
Definition: pix2.c:2264
l_int32 pixaGetBoxGeometry(PIXA *pixa, l_int32 index, l_int32 *px, l_int32 *py, l_int32 *pw, l_int32 *ph)
pixaGetBoxGeometry()
Definition: pixabasic.c:823
Definition: pix.h:134
Definition: pix.h:706
BOXA * boxaCreate(l_int32 n)
boxaCreate()
Definition: boxbasic.c:496
#define PIX_SRC
Definition: pix.h:327
PIX * pixCopy(PIX *pixd, PIX *pixs)
pixCopy()
Definition: pix1.c:630
void boxDestroy(BOX **pbox)
boxDestroy()
Definition: boxbasic.c:277
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:2401
l_int32 pixGetDimensions(PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
Definition: pix1.c:1052
l_int32 lept_rmdir(const char *subdir)
lept_rmdir()
Definition: utils2.c:1951
l_int32 pixCountPixels(PIX *pixs, l_int32 *pcount, l_int32 *tab8)
pixCountPixels()
Definition: pix3.c:1824
Definition: pix.h:480
#define SET_DATA_TWO_BYTES(pdata, n, val)
Definition: arrayaccess.h:216
void pixaDestroy(PIXA **ppixa)
pixaDestroy()
Definition: pixabasic.c:398
void extractRGBValues(l_uint32 pixel, l_int32 *prval, l_int32 *pgval, l_int32 *pbval)
extractRGBValues()
Definition: pix2.c:2725
BOX * boxCreate(l_int32 x, l_int32 y, l_int32 w, l_int32 h)
boxCreate()
Definition: boxbasic.c:164
l_int32 pixaGetCount(PIXA *pixa)
pixaGetCount()
Definition: pixabasic.c:620
l_int32 pixVarianceInRect(PIX *pix, BOX *box, l_float32 *prootvar)
pixVarianceInRect()
Definition: pix3.c:2724
#define SET_DATA_BIT(pdata, n)
Definition: arrayaccess.h:121
l_int32 pixThresholdPixelSum(PIX *pix, l_int32 thresh, l_int32 *pabove, l_int32 *tab8)
pixThresholdPixelSum()
Definition: pix3.c:2226
l_int32 pixCountPixelsInRow(PIX *pix, l_int32 row, l_int32 *pcount, l_int32 *tab8)
pixCountPixelsInRow()
Definition: pix3.c:2105
#define PIX_DST
Definition: pix.h:328
l_int32 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
l_int32 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