w32tex
About: TeX Live provides a comprehensive TeX system including all the major TeX-related programs, macro packages, and fonts that are free software. Windows sources.
  Fossies Dox: w32tex-src.tar.xz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

pix2.c
Go to the documentation of this file.
1 /*====================================================================*
2  - Copyright (C) 2001 Leptonica. All rights reserved.
3  - This software is distributed in the hope that it will be
4  - useful, but with NO WARRANTY OF ANY KIND.
5  - No author or distributor accepts responsibility to anyone for the
6  - consequences of using this software, or for whether it serves any
7  - particular purpose or works at all, unless he or she says so in
8  - writing. Everyone is granted permission to copy, modify and
9  - redistribute this source code, for commercial or non-commercial
10  - purposes, with the following restrictions: (1) the origin of this
11  - source code must not be misrepresented; (2) modified versions must
12  - be plainly marked as such; and (3) this notice may not be removed
13  - or altered from any source or modified source distribution.
14  *====================================================================*/
15 
16 /*
17  * pix2.c
18  *
19  * Pixel poking
20  * l_int32 pixGetPixel()
21  * l_int32 pixSetPixel()
22  * l_int32 pixClearPixel()
23  * l_int32 pixFlipPixel()
24  * void setPixelLow()
25  *
26  * Full image clear/set/set-to-arbitrary-value
27  * l_int32 pixClearAll()
28  * l_int32 pixSetAll()
29  * l_int32 pixSetAllArbitrary()
30  * l_int32 pixSetPadBits()
31  * l_int32 pixSetPadBitsBand()
32  *
33  * Set border pixels to arbitrary value
34  * l_int32 pixSetOrClearBorder()
35  * l_int32 pixSetBorderVal()
36  *
37  * Masked operations
38  * l_int32 pixSetMasked()
39  * l_int32 pixSetMaskedGeneral()
40  * l_int32 pixCombineMasked()
41  * l_int32 pixPaintThroughMask()
42  *
43  * One and two-image boolean operations on arbitrary depth images
44  * PIX *pixInvert()
45  * PIX *pixOr()
46  * PIX *pixAnd()
47  * PIX *pixXor()
48  * PIX *pixSubtract()
49  *
50  * Pixel counting
51  * l_int32 pixZero()
52  * l_int32 pixCountPixels()
53  * NUMA *pixaCountPixels()
54  * l_int32 pixCountPixelsInRow()
55  * NUMA *pixCountPixelsByRow()
56  * l_int32 pixThresholdPixels()
57  * l_int32 *makePixelSumTab8()
58  *
59  * Pixel histogram
60  * NUMA *pixGrayHistogram()
61  *
62  * Conversion between big and little endians
63  * PIX *pixEndianByteSwapNew()
64  * l_int32 pixEndianByteSwap()
65  * l_int32 pixEndianTwoByteSwap()
66  *
67  * Color sample setting and extraction
68  * PIX *pixCreateRGBImage()
69  * PIX *pixGetRGBComponent()
70  * l_int32 pixSetRGBComponent()
71  * l_int32 composeRGBPixel()
72  * l_int32 pixGetRGBLine()
73  *
74  * Add and remove border
75  * PIX *pixAddBorder()
76  * PIX *pixRemoveBorder()
77  * PIX *pixAddBorderGeneral()
78  * PIX *pixRemoveBorderGeneral()
79  *
80  * Test for pix equality
81  * l_int32 pixEqual()
82  * l_int32 pixEqualWithCmap()
83  *
84  * Extract rectangle
85  * PIX *pixClipRectangle()
86  *
87  * Clip to foreground
88  * PIX *pixClipToForeground()
89  */
90 
91 
92 #include <stdio.h>
93 #include <stdlib.h>
94 #include <string.h>
95 #include <math.h>
96 
97 #include "allheaders.h"
98 
99 static const l_uint32 rmask32[] = {0x0,
100  0x00000001, 0x00000003, 0x00000007, 0x0000000f,
101  0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff,
102  0x000001ff, 0x000003ff, 0x000007ff, 0x00000fff,
103  0x00001fff, 0x00003fff, 0x00007fff, 0x0000ffff,
104  0x0001ffff, 0x0003ffff, 0x0007ffff, 0x000fffff,
105  0x001fffff, 0x003fffff, 0x007fffff, 0x00ffffff,
106  0x01ffffff, 0x03ffffff, 0x07ffffff, 0x0fffffff,
107  0x1fffffff, 0x3fffffff, 0x7fffffff, 0xffffffff};
108 
109 
110 #ifndef NO_CONSOLE_IO
111 #define EQUAL_SIZE_WARNING 0
112 #endif /* ~NO_CONSOLE_IO */
113 
114 
115 
116 /*-------------------------------------------------------------*
117  * Pixel poking *
118  *-------------------------------------------------------------*/
119 /*!
120  * pixGetPixel()
121  *
122  * Input: pix
123  * (x,y) pixel coords
124  * &val (<return> pixel value)
125  * Return: 0 if OK; 1 on error
126  */
127 l_int32
129  l_int32 x,
130  l_int32 y,
131  l_uint32 *pval)
132 {
133 l_int32 w, h, d, wpl, val;
134 l_uint32 *line, *data;
135 
136  PROCNAME("pixGetPixel");
137 
138  if (!pix)
139  return ERROR_INT("pix not defined", procName, 1);
140  if (!pval)
141  return ERROR_INT("pval not defined", procName, 1);
142  *pval = 0;
143 
144  w = pixGetWidth(pix);
145  h = pixGetHeight(pix);
146  if (x < 0 || x >= w)
147  return ERROR_INT("x out of bounds", procName, 1);
148  if (y < 0 || y >= h)
149  return ERROR_INT("y out of bounds", procName, 1);
150 
151  wpl = pixGetWpl(pix);
152  data = pixGetData(pix);
153  line = data + y * wpl;
154 
155  d = pixGetDepth(pix);
156  switch (d)
157  {
158  case 1:
159  val = GET_DATA_BIT(line, x);
160  break;
161  case 2:
162  val = GET_DATA_DIBIT(line, x);
163  break;
164  case 4:
165  val = GET_DATA_QBIT(line, x);
166  break;
167  case 8:
168  val = GET_DATA_BYTE(line, x);
169  break;
170  case 16:
172  break;
173  case 32:
174  val = line[x];
175  break;
176  default:
177  return ERROR_INT("depth must be in {1,2,4,8,16,32} bpp", procName, 1);
178  }
179 
180  *pval = val;
181  return 0;
182 }
183 
184 
185 /*!
186  * pixSetPixel()
187  *
188  * Input: pix
189  * (x,y) pixel coords
190  * val (value to be inserted)
191  * Return: 0 if OK; 1 on error
192  *
193  * Note: the input value is not checked for overflow, and
194  * the sign bit (if any) is ignored.
195  */
196 l_int32
198  l_int32 x,
199  l_int32 y,
200  l_uint32 val)
201 {
202 l_int32 w, h, d, wpl;
203 l_uint32 *line, *data;
204 
205  PROCNAME("pixSetPixel");
206 
207  if (!pix)
208  return ERROR_INT("pix not defined", procName, 1);
209 
210  w = pixGetWidth(pix);
211  h = pixGetHeight(pix);
212  if (x < 0 || x >= w)
213  return ERROR_INT("x out of bounds", procName, 1);
214  if (y < 0 || y >= h)
215  return ERROR_INT("y out of bounds", procName, 1);
216 
217  data = pixGetData(pix);
218  wpl = pixGetWpl(pix);
219  line = data + y * wpl;
220 
221  d = pixGetDepth(pix);
222  switch (d)
223  {
224  case 1:
225  if (val)
226  SET_DATA_BIT(line, x);
227  else
229  break;
230  case 2:
232  break;
233  case 4:
234  SET_DATA_QBIT(line, x, val);
235  break;
236  case 8:
237  SET_DATA_BYTE(line, x, val);
238  break;
239  case 16:
241  break;
242  case 32:
243  line[x] = val;
244  break;
245  default:
246  return ERROR_INT("depth must be in {1,2,4,8,16,32} bpp", procName, 1);
247  }
248 
249  return 0;
250 }
251 
252 
253 
254 /*!
255  * pixClearPixel()
256  *
257  * Input: pix
258  * (x,y) pixel coords
259  * Return: 0 if OK; 1 on error.
260  */
261 l_int32
263  l_int32 x,
264  l_int32 y)
265 {
266 l_int32 w, h, d, wpl;
267 l_uint32 *line, *data;
268 
269  PROCNAME("pixClearPixel");
270 
271  if (!pix)
272  return ERROR_INT("pix not defined", procName, 1);
273 
274  w = pixGetWidth(pix);
275  h = pixGetHeight(pix);
276  if (x < 0 || x >= w)
277  return ERROR_INT("x out of bounds", procName, 1);
278  if (y < 0 || y >= h)
279  return ERROR_INT("y out of bounds", procName, 1);
280 
281  wpl = pixGetWpl(pix);
282  data = pixGetData(pix);
283  line = data + y * wpl;
284 
285  d = pixGetDepth(pix);
286  switch (d)
287  {
288  case 1:
290  break;
291  case 2:
293  break;
294  case 4:
296  break;
297  case 8:
298  SET_DATA_BYTE(line, x, 0);
299  break;
300  case 16:
302  break;
303  case 32:
304  line[x] = 0;
305  break;
306  default:
307  return ERROR_INT("depth must be in {1,2,4,8,16,32} bpp", procName, 1);
308  }
309 
310  return 0;
311 }
312 
313 
314 /*!
315  * pixFlipPixel()
316  *
317  * Input: pix
318  * (x,y) pixel coords
319  * Return: 0 if OK; 1 on error
320  */
321 l_int32
323  l_int32 x,
324  l_int32 y)
325 {
326 l_int32 w, h, d, wpl;
327 l_uint32 val;
328 l_uint32 *line, *data;
329 
330  PROCNAME("pixFlipPixel");
331 
332  if (!pix)
333  return ERROR_INT("pix not defined", procName, 1);
334 
335  w = pixGetWidth(pix);
336  h = pixGetHeight(pix);
337  if (x < 0 || x >= w)
338  return ERROR_INT("x out of bounds", procName, 1);
339  if (y < 0 || y >= h)
340  return ERROR_INT("y out of bounds", procName, 1);
341 
342  data = pixGetData(pix);
343  wpl = pixGetWpl(pix);
344  line = data + y * wpl;
345 
346  d = pixGetDepth(pix);
347  switch (d)
348  {
349  case 1:
350  val = GET_DATA_BIT(line, x);
351  if (val)
353  else
354  SET_DATA_BIT(line, x);
355  break;
356  case 2:
357  val = GET_DATA_DIBIT(line, x);
358  val ^= 0x3;
360  break;
361  case 4:
362  val = GET_DATA_QBIT(line, x);
363  val ^= 0xf;
364  SET_DATA_QBIT(line, x, val);
365  break;
366  case 8:
367  val = GET_DATA_BYTE(line, x);
368  val ^= 0xff;
369  SET_DATA_BYTE(line, x, val);
370  break;
371  case 16:
373  val ^= 0xffff;
375  break;
376  case 32:
377  val = line[x] ^ 0xffffffff;
378  line[x] = val;
379  break;
380  default:
381  return ERROR_INT("depth must be in {1,2,4,8,16,32} bpp", procName, 1);
382  }
383 
384  return 0;
385 }
386 
387 
388 /*!
389  * setPixelLow()
390  *
391  * Input: line (ptr to beginning of line),
392  * x (pixel location in line)
393  * depth (bpp)
394  * val (to be inserted)
395  * Return: void
396  *
397  * Note: input variables are not checked
398  */
399 void
401  l_int32 x,
402  l_int32 depth,
403  l_uint32 val)
404 {
405  switch (depth)
406  {
407  case 1:
408  if (val)
409  SET_DATA_BIT(line, x);
410  else
412  break;
413  case 2:
415  break;
416  case 4:
417  SET_DATA_QBIT(line, x, val);
418  break;
419  case 8:
420  SET_DATA_BYTE(line, x, val);
421  break;
422  case 16:
424  break;
425  case 32:
426  line[x] = val;
427  break;
428  default:
429  fprintf(stderr, "illegal depth in setPixelLow()\n");
430  }
431 
432  return;
433 }
434 
435 
436 
437 /*-------------------------------------------------------------*
438  * Full image clear/set/set-to-arbitrary-value/invert *
439  *-------------------------------------------------------------*/
440 /*!
441  * pixClearAll()
442  *
443  * Input: pix
444  * Return: 0 if OK, 1 on error
445  *
446  * Action: clears all data to 0
447  */
448 l_int32
450 {
451  PROCNAME("pixClearAll");
452 
453  if (!pix)
454  return ERROR_INT("pix not defined", procName, 1);
455 
457  PIX_CLR, NULL, 0, 0);
458  return 0;
459 }
460 
461 
462 /*!
463  * pixSetAll()
464  *
465  * Input: pix
466  * Return: 0 if OK, 1 on error
467  *
468  * Action: sets all data to 1
469  */
470 l_int32
472 {
473  PROCNAME("pixSetAll");
474 
475  if (!pix)
476  return ERROR_INT("pix not defined", procName, 1);
477 
479  PIX_SET, NULL, 0, 0);
480  return 0;
481 }
482 
483 
484 /*!
485  * pixSetAllArbitrary()
486  *
487  * Input: pix
488  * val (value to set all pixels)
489  * Return: 0 if OK; 1 on error
490  */
491 l_int32
493  l_uint32 val)
494 {
495 l_int32 i, j, w, h, d, wpl, npix;
496 l_uint32 maxval, wordval;
497 l_uint32 *data, *line;
498 
499  PROCNAME("pixSetAllArbitrary");
500 
501  if (!pix)
502  return ERROR_INT("pix not defined", procName, 1);
503 
504  d = pixGetDepth(pix);
505  w = pixGetWidth(pix);
506  h = pixGetHeight(pix);
507 
508  if (d == 32)
509  maxval = 0xffffffff;
510  else
511  maxval = (1 << d) - 1;
512  if (val < 0) {
513  L_WARNING("invalid pixel value; set to 0", procName);
514  val = 0;
515  }
516  if (val > maxval) {
517  L_WARNING_INT("invalid pixel val; set to maxval = %d",
518  procName, maxval);
519  val = maxval;
520  }
521 
522  /* set up word to tile with */
523  wordval = 0;
524  npix = 32 / d; /* number of pixels per 32 bit word */
525  for (j = 0; j < npix; j++)
526  wordval |= (val << (j * d));
527 
528  wpl = pixGetWpl(pix);
529  data = pixGetData(pix);
530  for (i = 0; i < h; i++) {
531  line = data + i * wpl;
532  for (j = 0; j < wpl; j++) {
533  *(line + j) = wordval;
534  }
535  }
536 
537  return 0;
538 }
539 
540 
541 /*!
542  * pixSetPadBits()
543  *
544  * Input: pix (1, 2, 4, 8, 16, 32 bpp)
545  * val (0 or 1)
546  * Return: 0 if OK; 1 on error
547  *
548  * Notes:
549  * (1) The pad bits are the bits that expand each scanline to a
550  * multiple of 32 bits. They are usually not used in
551  * image processing operations. When boundary conditions
552  * are important, as in seedfill, they must be set properly.
553  * (2) This sets the value of the pad bits (if any) in the last
554  * 32-bit word in each scanline.
555  * (3) For 32 bpp pix, there are no pad bits, so this is a no-op.
556  */
557 l_int32
559  l_int32 val)
560 {
561 l_int32 i, w, h, d, wpl, endbits, fullwords;
562 l_uint32 mask;
563 l_uint32 *data, *pword;
564 
565  PROCNAME("pixSetPadBits");
566 
567  if (!pix)
568  return ERROR_INT("pix not defined", procName, 1);
569 
570  if ((d = pixGetDepth(pix)) == 32) /* no padding exists for 32 bpp */
571  return 0;
572 
573  w = pixGetWidth(pix);
574  h = pixGetHeight(pix);
575  data = pixGetData(pix);
576  wpl = pixGetWpl(pix);
577  endbits = 32 - ((w * d) % 32);
578  if (endbits == 32) /* no partial word */
579  return 0;
580  fullwords = w * d / 32;
581 
582  mask = rmask32[endbits];
583  if (val == 0)
584  mask = ~~mask;
585 
586  for (i = 0; i < h; i++) {
587  pword = data + i * wpl + fullwords;
588  if (val == 0) /* clear */
589  *pword = *pword & mask;
590  else /* set */
591  *pword = *pword | mask;
592  }
593 
594  return 0;
595 }
596 
597 
598 /*!
599  * pixSetPadBitsBand()
600  *
601  * Input: pix (1, 2, 4, 8, 16, 32 bpp)
602  * by (starting y value of band)
603  * bh (height of band)
604  * val (0 or 1)
605  * Return: 0 if OK; 1 on error
606  *
607  * Notes:
608  * (1) The pad bits are the bits that expand each scanline to a
609  * multiple of 32 bits. They are usually not used in
610  * image processing operations. When boundary conditions
611  * are important, as in seedfill, they must be set properly.
612  * (2) This sets the value of the pad bits (if any) in the last
613  * 32-bit word in each scanline, within the specified
614  * band of raster lines.
615  * (3) For 32 bpp pix, there are no pad bits, so this is a no-op.
616  */
617 l_int32
619  l_int32 by,
620  l_int32 bh,
621  l_int32 val)
622 {
623 l_int32 i, w, h, d, wpl, endbits, fullwords;
624 l_uint32 mask;
625 l_uint32 *data, *pword;
626 
627  PROCNAME("pixSetPadBitsBand");
628 
629  if (!pix)
630  return ERROR_INT("pix not defined", procName, 1);
631 
632  if ((d = pixGetDepth(pix)) == 32) /* no padding exists for 32 bpp */
633  return 0;
634 
635  h = pixGetHeight(pix);
636  if (by < 0)
637  by = 0;
638  if (by >= h)
639  return ERROR_INT("start y not in image", procName, 1);
640  if (by + bh > h)
641  bh = h - by;
642 
643  w = pixGetWidth(pix);
644  data = pixGetData(pix);
645  wpl = pixGetWpl(pix);
646  endbits = 32 - ((w * d) % 32);
647  if (endbits == 32) /* no partial word */
648  return 0;
649  fullwords = w * d / 32;
650 
651  mask = rmask32[endbits];
652  if (val == 0)
653  mask = ~~mask;
654 
655  for (i = by; i < by + bh; i++) {
656  pword = data + i * wpl + fullwords;
657  if (val == 0) /* clear */
658  *pword = *pword & mask;
659  else /* set */
660  *pword = *pword | mask;
661  }
662 
663  return 0;
664 }
665 
666 
667 /*-------------------------------------------------------------*
668  * Set border pixels *
669  *-------------------------------------------------------------*/
670 /*!
671  * pixSetOrClearBorder()
672  *
673  * Input: pixs (all depths)
674  * leftpix, rightpix, toppix, bottompix
675  * operation (PIX_SET or PIX_CLR)
676  * Return: 0 if OK; 1 on error
677  *
678  * Notes:
679  * (1) The border region is defined to be the region in the
680  * image within a specific distance of each edge. Here, we
681  * allow the pixels within a specified distance of each
682  * edge to be set independently. This either sets or
683  * clears all pixels in the border region.
684  * (2) For binary images, use PIX_SET for black and PIX_CLR for white.
685  * (3) For grayscale or color images, use PIX_SET for white
686  * and PIX_CLR for black.
687  */
688 l_int32
690  l_int32 leftpix,
691  l_int32 rightpix,
692  l_int32 toppix,
693  l_int32 bottompix,
694  l_int32 op)
695 {
696 l_int32 w, h;
697 
698  PROCNAME("pixSetOrClearBorder");
699 
700  if (!pixs)
701  return ERROR_INT("pixs not defined", procName, 1);
702  if (op != PIX_SET && op != PIX_CLR)
703  return ERROR_INT("op must be PIX_SET or PIX_CLR", procName, 1);
704 
705  w = pixGetWidth(pixs);
706  h = pixGetHeight(pixs);
707 
708  pixRasterop(pixs, 0, 0, leftpix, h, op, NULL, 0, 0);
709  pixRasterop(pixs, w - rightpix, 0, rightpix, h, op, NULL, 0, 0);
710  pixRasterop(pixs, 0, 0, w, toppix, op, NULL, 0, 0);
711  pixRasterop(pixs, 0, h - bottompix, w, bottompix, op, NULL, 0, 0);
712 
713  return 0;
714 }
715 
716 
717 /*!
718  * pixSetBorderVal()
719  *
720  * Input: pixs (8 or 32 bpp)
721  * leftpix, rightpix, toppix, bottompix
722  * val (value to set at each border pixel)
723  * Return: 0 if OK; 1 on error
724  *
725  * Notes:
726  * (1) The border region is defined to be the region in the
727  * image within a specific distance of each edge. Here, we
728  * allow the pixels within a specified distance of each
729  * edge to be set independently. This sets the pixels
730  * in the border region to the given input value.
731  * (2) For efficiency, use pixSetOrClearBorder() if
732  * you're setting the border to either black or white.
733  * (3) If d != 32, the input value should be masked off
734  * to the appropriate number of least significant bits.
735  * (4) The code is easily generalized for 2, 4 or 16 bpp.
736  */
737 l_int32
739  l_int32 leftpix,
740  l_int32 rightpix,
741  l_int32 toppix,
742  l_int32 bottompix,
743  l_uint32 val)
744 {
745 l_int32 w, h, d, wpls, i, j, bstart, rstart;
746 l_uint32 *datas, *lines;
747 
748  PROCNAME("pixSetBorderVal");
749 
750  if (!pixs)
751  return ERROR_INT("pixs not defined", procName, 1);
752  d = pixGetDepth(pixs);
753  if (d != 8 && d != 32)
754  return ERROR_INT("depth must be 8 or 32 bpp", procName, 1);
755 
756  w = pixGetWidth(pixs);
757  h = pixGetHeight(pixs);
758  datas = pixGetData(pixs);
759  wpls = pixGetWpl(pixs);
760 
761  if (d == 8) {
762  val &= 0xff;
763  for (i = 0; i < toppix; i++) {
764  lines = datas + i * wpls;
765  for (j = 0; j < w; j++)
767  }
768  rstart = w - rightpix;
769  bstart = h - bottompix;
770  for (i = toppix; i < bstart; i++) {
771  lines = datas + i * wpls;
772  for (j = 0; j < leftpix; j++)
774  for (j = rstart; j < w; j++)
776  }
777  for (i = bstart; i < h; i++) {
778  lines = datas + i * wpls;
779  for (j = 0; j < w; j++)
781  }
782  }
783  else { /* d == 32 */
784  for (i = 0; i < toppix; i++) {
785  lines = datas + i * wpls;
786  for (j = 0; j < w; j++)
787  *(lines + j) = val;
788  }
789  rstart = w - rightpix;
790  bstart = h - bottompix;
791  for (i = toppix; i < bstart; i++) {
792  lines = datas + i * wpls;
793  for (j = 0; j < leftpix; j++)
794  *(lines + j) = val;
795  for (j = rstart; j < w; j++)
796  *(lines + j) = val;
797  }
798  for (i = bstart; i < h; i++) {
799  lines = datas + i * wpls;
800  for (j = 0; j < w; j++)
801  *(lines + j) = val;
802  }
803  }
804 
805  return 0;
806 }
807 
808 
809 
810 /*-------------------------------------------------------------*
811  * Masked operations *
812  *-------------------------------------------------------------*/
813 /*!
814  * pixSetMasked()
815  *
816  * Input: pixd (8, 16 or 32 bpp)
817  * pixm (<optional> 1 bpp mask; no operation if NULL)
818  * val (value to set at each masked pixel)
819  * Return: 0 if OK; 1 on error
820  *
821  * Notes:
822  * (1) In-place operation. Calls pixSetMaskedCmap() for colormapped
823  * images.
824  * (2) If pixm == NULL, a warning is given.
825  * (3) It is an implicitly aligned operation, where the UL
826  * corners of pixd and pixm coincide. A warning is
827  * issued if the two image sizes differ significantly,
828  * but the operation proceeds.
829  * (4) Each pixel in pixd that co-locates with an ON pixel
830  * in pixm is set to the specified input value.
831  * Other pixels in pixd are not changed.
832  * (5) You can visualize this as painting the color through
833  * the mask, as a stencil.
834  * (6) If you do not want to have the UL corners aligned,
835  * use the function pixSetMaskedGeneral(), which requires
836  * you to input the UL corner of pixm relative to pixd.
837  */
838 l_int32
840  PIX *pixm,
841  l_uint32 val)
842 {
843 l_int32 wd, hd, wm, hm, w, h, d, wpld, wplm;
844 l_int32 i, j, bitval, rval, gval, bval;
845 l_uint32 *datad, *datam, *lined, *linem;
846 
847  PROCNAME("pixSetMasked");
848 
849  if (!pixd)
850  return ERROR_INT("pixd not defined", procName, 1);
851  if (!pixm) {
852  L_WARNING("no mask; nothing to do", procName);
853  return 0;
854  }
855  if (pixGetColormap(pixd)) {
856  rval = GET_DATA_BYTE(&val, COLOR_RED);
858  bval = GET_DATA_BYTE(&val, COLOR_BLUE);
859  return pixSetMaskedCmap(pixd, pixm, 0, 0, rval, gval, bval);
860  }
861 
862  wd = pixGetWidth(pixd);
863  hd = pixGetHeight(pixd);
864  wm = pixGetWidth(pixm);
865  hm = pixGetHeight(pixm);
866  w = L_MIN(wd, wm);
867  h = L_MIN(hd, hm);
868  if (L_ABS(wd - wm) > 7 || L_ABS(hd - hm) > 7) /* allow a small tolerance */
869  L_WARNING("pixd and pixm sizes differ", procName);
870  d = pixGetDepth(pixd);
871  if (d != 8 && d != 16 && d != 32)
872  return ERROR_INT("pixd not 8, 16 or 32 bpp", procName, 1);
873  if (pixGetDepth(pixm) != 1)
874  return ERROR_INT("pixm not 1 bpp", procName, 1);
875 
876  datad = pixGetData(pixd);
877  datam = pixGetData(pixm);
878  wpld = pixGetWpl(pixd);
879  wplm = pixGetWpl(pixm);
880  if (d == 8) {
881  val &= 0xff;
882  for (i = 0; i < h; i++) {
883  lined = datad + i * wpld;
884  linem = datam + i * wplm;
885  for (j = 0; j < w; j++) {
886  bitval = GET_DATA_BIT(linem, j);
887  if (bitval)
888  SET_DATA_BYTE(lined, j, val);
889  }
890  }
891  }
892  else if (d == 16) {
893  val &= 0xffff;
894  for (i = 0; i < h; i++) {
895  lined = datad + i * wpld;
896  linem = datam + i * wplm;
897  for (j = 0; j < w; j++) {
898  bitval = GET_DATA_BIT(linem, j);
899  if (bitval)
900  SET_DATA_TWO_BYTES(lined, j, val);
901  }
902  }
903  }
904  else { /* d == 32 */
905  for (i = 0; i < h; i++) {
906  lined = datad + i * wpld;
907  linem = datam + i * wplm;
908  for (j = 0; j < w; j++) {
909  bitval = GET_DATA_BIT(linem, j);
910  if (bitval)
911  *(lined + j) = val;
912  }
913  }
914  }
915 
916  return 0;
917 }
918 
919 
920 /*!
921  * pixSetMaskedGeneral()
922  *
923  * Input: pixd (8, 16 or 32 bpp)
924  * pixm (<optional> 1 bpp mask; no operation if null)
925  * val (value to set at each masked pixel)
926  * x, y (location of UL corner of pixm relative to pixd;
927  * can be negative)
928  * Return: 0 if OK; 1 on error
929  *
930  * Notes:
931  * (1) This is an in-place operation.
932  * (2) Alignment is explicit. If you want the UL corners of
933  * the two images to be aligned, use pixSetMasked().
934  * (3) A typical use would be painting through the foreground
935  * of a small binary mask pixm, located somewhere on a
936  * larger pixd. Other pixels in pixd are not changed.
937  * (4) You can visualize this as painting the color through
938  * the mask, as a stencil.
939  * (5) This uses rasterop to handle clipping and different depths of pixd.
940  * (6) If pixd has a colormap, you should call pixPaintThroughMask().
941  * (7) Why is this function here, if pixPaintThroughMask() does the
942  * same thing, and does it more generally? I've retained it here
943  * to show how one can paint through a mask using only full
944  * image rasterops, rather than pixel peeking in pixm and poking
945  * in pixd. It's somewhat baroque, but I found it amusing.
946  */
947 l_int32
949  PIX *pixm,
950  l_uint32 val,
951  l_int32 x,
952  l_int32 y)
953 {
954 l_int32 wm, hm, d;
955 PIX *pixmu, *pixc;
956 
957  PROCNAME("pixSetMaskedGeneral");
958 
959  if (!pixd)
960  return ERROR_INT("pixd not defined", procName, 1);
961  if (!pixm) /* nothing to do */
962  return 0;
963 
964  d = pixGetDepth(pixd);
965  if (d != 8 && d != 16 && d != 32)
966  return ERROR_INT("pixd not 8, 16 or 32 bpp", procName, 1);
967  if (pixGetDepth(pixm) != 1)
968  return ERROR_INT("pixm not 1 bpp", procName, 1);
969  wm = pixGetWidth(pixm);
970  hm = pixGetHeight(pixm);
971 
972  /* Unpack binary to depth d, with inversion: 1 --> 0, 0 --> 0xff... */
973  if ((pixmu = pixUnpackBinary(pixm, d, 1)) == NULL)
974  return ERROR_INT("pixmu not made", procName, 1);
975 
976  /* Clear stenciled pixels in pixd */
977  pixRasterop(pixd, x, y, wm, hm, PIX_SRC & PIX_DST, pixmu, 0, 0);
978 
979  /* Generate image with requisite color */
980  if ((pixc = pixCreateTemplate(pixmu)) == NULL)
981  return ERROR_INT("pixc not made", procName, 1);
982  pixSetAllArbitrary(pixc, val);
983 
984  /* Invert stencil mask, and paint color color into stencil */
985  pixInvert(pixmu, pixmu);
986  pixAnd(pixmu, pixmu, pixc);
987 
988  /* Finally, repaint stenciled pixels, with val, in pixd */
989  pixRasterop(pixd, x, y, wm, hm, PIX_SRC | PIX_DST, pixmu, 0, 0);
990 
991  pixDestroy(&pixmu);
992  pixDestroy(&pixc);
993  return 0;
994 }
995 
996 
997 /*!
998  * pixCombineMasked()
999  *
1000  * Input: pixd (8 or 32 bpp)
1001  * pixs (8 or 32 bpp)
1002  * pixm (<optional> 1 bpp mask; no operation if NULL)
1003  * Return: 0 if OK; 1 on error
1004  *
1005  * Action: sets each pixel in pixd that co-locates with an ON
1006  * pixel in pixm to the corresponding value of pixs.
1007  *
1008  * Implementation note:
1009  * For 8 bpp selective masking, you might think that it would
1010  * be faster to generate an 8 bpp version of pixm, using
1011  * pixConvert1To8(pixm, 0, 255), and then use a general combine
1012  * operation
1013  * d = (d & ~m) | (s & m)
1014  * on a word-by-word basis. Not always. The word-by-word combine
1015  * takes a time that is independent of the mask data. If the mask is
1016  * relatively sparse, the byte-check method is actually faster!
1017  */
1018 l_int32
1020  PIX *pixs,
1021  PIX *pixm)
1022 {
1023 l_uint8 val;
1024 l_int32 d, w, wd, wm, h, hd, hm, wpld, wpls, wplm, i, j;
1025 l_uint32 *datad, *datas, *datam, *lined, *lines, *linem;
1026 
1027  PROCNAME("pixCombineMasked");
1028 
1029  if (!pixd)
1030  return ERROR_INT("pixd not defined", procName, 1);
1031  if (!pixm) /* nothing to do */
1032  return 0;
1033  if (!pixs)
1034  return ERROR_INT("pixs not defined", procName, 1);
1035 
1036  d = pixGetDepth(pixd);
1037  if (d != 8 && d != 32)
1038  return ERROR_INT("pixd not 8 or 32 bpp", procName, 1);
1039  if (pixGetDepth(pixm) != 1)
1040  return ERROR_INT("pixm not 1 bpp", procName, 1);
1041  if (!pixSizesEqual(pixd, pixs))
1042  return ERROR_INT("pixs and pixd sizes differ", procName, 1);
1043 
1044  wd = pixGetWidth(pixd);
1045  hd = pixGetHeight(pixd);
1046  wm = pixGetWidth(pixm);
1047  hm = pixGetHeight(pixm);
1048  w = L_MIN(wd, wm);
1049  h = L_MIN(hd, hm);
1050  datad = pixGetData(pixd);
1051  datas = pixGetData(pixs);
1052  datam = pixGetData(pixm);
1053  wpld = pixGetWpl(pixd);
1054  wpls = pixGetWpl(pixs);
1055  wplm = pixGetWpl(pixm);
1056 
1057  if (d == 8) {
1058  for (i = 0; i < h; i++) {
1059  lined = datad + i * wpld;
1060  lines = datas + i * wpls;
1061  linem = datam + i * wplm;
1062  for (j = 0; j < w; j++) {
1063  if (GET_DATA_BIT(linem, j)) {
1064  val = GET_DATA_BYTE(lines, j);
1065  SET_DATA_BYTE(lined, j, val);
1066  }
1067  }
1068  }
1069  }
1070  else { /* d == 32 */
1071  for (i = 0; i < h; i++) {
1072  lined = datad + i * wpld;
1073  lines = datas + i * wpls;
1074  linem = datam + i * wplm;
1075  for (j = 0; j < w; j++) {
1076  if (GET_DATA_BIT(linem, j))
1077  lined[j] = lines[j];
1078  }
1079  }
1080  }
1081 
1082  return 0;
1083 }
1084 
1085 
1086 /*!
1087  * pixPaintThroughMask()
1088  *
1089  * Input: pixd (8 or 32 bpp)
1090  * pixm (<optional> 1 bpp mask)
1091  * x, y (origin of pixm relative to pixd; can be negative)
1092  * val (1 byte or rgb color to set at each masked pixel)
1093  * Return: 0 if OK; 1 on error
1094  *
1095  * Notes:
1096  * (1) In-place operation. Calls pixSetMaskedCmap() for colormapped
1097  * images.
1098  * (2) For 8 bpp gray, we take the LSB of the color
1099  * (3) If pixm == NULL, it's a no-op.
1100  * (4) The mask origin is placed at (x,y) on pixd, and the
1101  * operation is clipped to the intersection of rectangles.
1102  * (5) For rgb, the components in val are in the canonical locations,
1103  * with red in location COLOR_RED, etc.
1104  */
1105 l_int32
1107  PIX *pixm,
1108  l_int32 x,
1109  l_int32 y,
1110  l_uint32 val)
1111 {
1112 l_int32 d, w, h, wm, hm, wpl, wplm, i, j, rval, gval, bval;
1113 l_uint32 *data, *datam, *line, *linem;
1114 
1115  PROCNAME("pixPaintThroughMask");
1116 
1117  if (!pixd)
1118  return ERROR_INT("pixd not defined", procName, 1);
1119  if (!pixm) /* nothing to do */
1120  return 0;
1121  if (pixGetColormap(pixd)) {
1122  rval = GET_DATA_BYTE(&val, COLOR_RED);
1124  bval = GET_DATA_BYTE(&val, COLOR_BLUE);
1125  return pixSetMaskedCmap(pixd, pixm, x, y, rval, gval, bval);
1126  }
1127  d = pixGetDepth(pixd);
1128  if (d != 8 && d != 32)
1129  return ERROR_INT("pixd not 8 or 32 bpp", procName, 1);
1130  if (pixGetDepth(pixm) != 1)
1131  return ERROR_INT("pixm not 1 bpp", procName, 1);
1132 
1133  w = pixGetWidth(pixd);
1134  h = pixGetHeight(pixd);
1135  wpl = pixGetWpl(pixd);
1136  data = pixGetData(pixd);
1137  wm = pixGetWidth(pixm);
1138  hm = pixGetHeight(pixm);
1139  wplm = pixGetWpl(pixm);
1140  datam = pixGetData(pixm);
1141 
1142  if (d == 8)
1143  val = val & 0xff;
1144  for (i = 0; i < hm; i++) {
1145  if (y + i < 0 || y + i >= h) continue;
1146  line = data + (y + i) * wpl;
1147  linem = datam + i * wplm;
1148  for (j = 0; j < wm; j++) {
1149  if (x + j < 0 || x + j >= w) continue;
1150  if (GET_DATA_BIT(linem, j)) {
1151  switch (d)
1152  {
1153  case 8:
1154  SET_DATA_BYTE(line, x + j, val);
1155  break;
1156  case 32:
1157  *(line + x + j) = val;
1158  break;
1159  default:
1160  return ERROR_INT("d not 8 or 32 bpp", procName, 1);
1161  }
1162  }
1163  }
1164  }
1165 
1166  return 0;
1167 }
1168 
1169 
1170 /*-------------------------------------------------------------*
1171  * One and two-image boolean ops on arbitrary depth images *
1172  *-------------------------------------------------------------*/
1173 /*!
1174  * pixInvert()
1175  *
1176  * Input: pixd (<optional> destination: this can be null,
1177  * equal to pixs, or different from pixs)
1178  * pixs
1179  * Return: pixd always
1180  *
1181  * Inversion of pixs, independent of pixel depth.
1182  * There are 3 cases:
1183  * if pixd == null, ~src --> new pixd
1184  * if pixd == pixs, ~src --> src (in-place)
1185  * if pixd != pixs, ~src --> input pixd
1186  */
1187 PIX *
1189  PIX *pixs)
1190 {
1191  PROCNAME("pixInvert");
1192 
1193  if (!pixs)
1194  return (PIX *)ERROR_PTR("pixs not defined", procName, pixd);
1195 
1196  if (pixs != pixd) {
1197  if ((pixd = pixCopy(pixd, pixs)) == NULL)
1198  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
1199  }
1200 
1201  pixRasterop(pixd, 0, 0, pixGetWidth(pixd), pixGetHeight(pixd),
1202  PIX_NOT(PIX_DST), NULL, 0, 0); /* invert pixd */
1203 
1204  return pixd;
1205 }
1206 
1207 
1208 /*!
1209  * pixOr()
1210  *
1211  * Input: pixd (<optional> destination: this can be null,
1212  * equal to pixs1, or different from pixs1)
1213  * pixs1 (can be == to pixd)
1214  * pixs2
1215  * Return: pixd always
1216  *
1217  * Union of two images, independent of pixel depth.
1218  * There are 3 cases:
1219  * if pixd == null, (src1 | src2) --> new pixd
1220  * if pixd == pixs1, (src1 | src2) --> src1 (in-place)
1221  * if pixd != pixs1, (src1 | src2) --> input pixd
1222  */
1223 PIX *
1224 pixOr(PIX *pixd,
1225  PIX *pixs1,
1226  PIX *pixs2)
1227 {
1228  PROCNAME("pixOr");
1229 
1230  if (!pixs1)
1231  return (PIX *)ERROR_PTR("pixs1 not defined", procName, pixd);
1232  if (!pixs2)
1233  return (PIX *)ERROR_PTR("pixs2 not defined", procName, pixd);
1234  if (pixs1 == pixs2)
1235  return (PIX *)ERROR_PTR("pixs1 and pixs2 must differ", procName, pixd);
1236 
1237 #if EQUAL_SIZE_WARNING
1238  if (!pixSizesEqual(pixs1, pixs2))
1239  L_WARNING("pixs1 and pixs2 not equal sizes", procName);
1240 #endif /* EQUAL_SIZE_WARNING */
1241 
1242  if (pixs1 != pixd) {
1243  if ((pixd = pixCopy(pixd, pixs1)) == NULL)
1244  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
1245  }
1246 
1247  /* src1 | src2 --> dest */
1248  pixRasterop(pixd, 0, 0, pixGetWidth(pixd), pixGetHeight(pixd),
1249  PIX_SRC | PIX_DST, pixs2, 0, 0);
1250 
1251  return pixd;
1252 }
1253 
1254 
1255 /*!
1256  * pixAnd()
1257  *
1258  * Input: pixd (<optional> destination: this can be null,
1259  * equal to pixs1, or different from pixs1)
1260  * pixs1 (can be == to pixd)
1261  * pixs2
1262  * Return: pixd always
1263  *
1264  * Intersection of two images, independent of pixel depth.
1265  * There are 3 cases:
1266  * if pixd == null, (src1 & src2) --> new pixd
1267  * if pixd == pixs1, (src1 & src2) --> src1 (in-place)
1268  * if pixd != pixs1, (src1 & src2) --> input pixd
1269  */
1270 PIX *
1271 pixAnd(PIX *pixd,
1272  PIX *pixs1,
1273  PIX *pixs2)
1274 {
1275  PROCNAME("pixAnd");
1276 
1277  if (!pixs1)
1278  return (PIX *)ERROR_PTR("pixs1 not defined", procName, pixd);
1279  if (!pixs2)
1280  return (PIX *)ERROR_PTR("pixs2 not defined", procName, pixd);
1281  if (pixs1 == pixs2)
1282  return (PIX *)ERROR_PTR("pixs1 and pixs2 must differ", procName, pixd);
1283 
1284 #if EQUAL_SIZE_WARNING
1285  if (!pixSizesEqual(pixs1, pixs2))
1286  L_WARNING("pixs1 and pixs2 not equal sizes", procName);
1287 #endif /* EQUAL_SIZE_WARNING */
1288 
1289  if (pixs1 != pixd) {
1290  if ((pixd = pixCopy(pixd, pixs1)) == NULL)
1291  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
1292  }
1293 
1294  /* src1 & src2 --> dest */
1295  pixRasterop(pixd, 0, 0, pixGetWidth(pixd), pixGetHeight(pixd),
1296  PIX_SRC & PIX_DST, pixs2, 0, 0);
1297 
1298  return pixd;
1299 }
1300 
1301 
1302 /*!
1303  * pixXor()
1304  *
1305  * Input: pixd (<optional> destination: this can be null,
1306  * equal to pixs1, or different from pixs1)
1307  * pixs1 (can be == to pixd)
1308  * pixs2
1309  * Return: pixd always
1310  *
1311  * XOR of two images, independent of pixel depth.
1312  * There are 3 cases:
1313  * if pixd == null, (src1 ^ src2) --> new pixd
1314  * if pixd == pixs1, (src1 ^ src2) --> src1 (in-place)
1315  * if pixd != pixs1, (src1 ^ src2) --> input pixd
1316  */
1317 PIX *
1318 pixXor(PIX *pixd,
1319  PIX *pixs1,
1320  PIX *pixs2)
1321 {
1322  PROCNAME("pixXor");
1323 
1324  if (!pixs1)
1325  return (PIX *)ERROR_PTR("pixs1 not defined", procName, pixd);
1326  if (!pixs2)
1327  return (PIX *)ERROR_PTR("pixs2 not defined", procName, pixd);
1328  if (pixs1 == pixs2)
1329  return (PIX *)ERROR_PTR("pixs1 and pixs2 must differ", procName, pixd);
1330 
1331 #if EQUAL_SIZE_WARNING
1332  if (!pixSizesEqual(pixs1, pixs2))
1333  L_WARNING("pixs1 and pixs2 not equal sizes", procName);
1334 #endif /* EQUAL_SIZE_WARNING */
1335 
1336  if (pixs1 != pixd) {
1337  if ((pixd = pixCopy(pixd, pixs1)) == NULL)
1338  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
1339  }
1340 
1341  /* src1 ^ src2 --> dest */
1342  pixRasterop(pixd, 0, 0, pixGetWidth(pixd), pixGetHeight(pixd),
1343  PIX_SRC ^ PIX_DST, pixs2, 0, 0);
1344 
1345  return pixd;
1346 }
1347 
1348 
1349 /*!
1350  * pixSubtract()
1351  *
1352  * Input: pixd (<optional> destination: this can be null,
1353  * equal to pixs1, equal to pixs2, or different
1354  * from both pixs1 and pixs2)
1355  * pixs1 (can be == to pixd)
1356  * pixs2 (can be == to pixd)
1357  * Return: pixd always
1358  *
1359  * Notes:
1360  * (1) Set subtraction of two images, independent of pixel depth.
1361  * (2) Source pixs2 is always subtracted from source pixs1.
1362  * The result is
1363  * pixs1 \ pixs2 = pixs1 & (~pixs2)
1364  * (3) There are 4 cases. The result can go to a new dest,
1365  * in-place to either pixs1 or pixs2, or to an existing input dest:
1366  * if pixd == null, (src1 - src2) --> new pixd
1367  * if pixd == pixs1, (src1 - src2) --> src1 (in-place)
1368  * if pixd == pixs2, (src1 - src2) --> src2 (in-place)
1369  * if pixd != pixs1 && pixd != pixs2),
1370  * (src1 - src2) --> input pixd
1371  */
1372 PIX *
1374  PIX *pixs1,
1375  PIX *pixs2)
1376 {
1377 l_int32 w, h;
1378 
1379  PROCNAME("pixSubtract");
1380 
1381  if (!pixs1)
1382  return (PIX *)ERROR_PTR("pixs1 not defined", procName, pixd);
1383  if (!pixs2)
1384  return (PIX *)ERROR_PTR("pixs2 not defined", procName, pixd);
1385  if (pixs1 == pixs2)
1386  return (PIX *)ERROR_PTR("pixs1 and pixs2 must differ", procName, pixd);
1387  if (pixGetDepth(pixs1) != 1)
1388  return (PIX *)ERROR_PTR("pixs1 not binary", procName, pixd);
1389  if (pixGetDepth(pixs2) != 1)
1390  return (PIX *)ERROR_PTR("pixs2 not binary", procName, pixd);
1391 
1392 #if EQUAL_SIZE_WARNING
1393  if (!pixSizesEqual(pixs1, pixs2))
1394  L_WARNING("pixs1 and pixs2 not equal sizes", procName);
1395 #endif /* EQUAL_SIZE_WARNING */
1396 
1397  w = pixGetWidth(pixs1);
1398  h = pixGetHeight(pixs1);
1399 
1400  if (!pixd) {
1401  if ((pixd = pixCopy(NULL, pixs1)) == NULL)
1402  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
1403  pixRasterop(pixd, 0, 0, w, h, PIX_DST & PIX_NOT(PIX_SRC),
1404  pixs2, 0, 0); /* src1 & (~src2) */
1405  }
1406  else if (pixd == pixs1) {
1407  pixRasterop(pixd, 0, 0, w, h, PIX_DST & PIX_NOT(PIX_SRC),
1408  pixs2, 0, 0); /* src1 & (~src2) */
1409  }
1410  else if (pixd == pixs2) {
1411  pixRasterop(pixd, 0, 0, w, h, PIX_NOT(PIX_DST) & PIX_SRC,
1412  pixs1, 0, 0); /* src1 & (~src2) */
1413  }
1414  else { /* pixd != pixs1 && pixd != pixs2 */
1415  if (pixGetDepth(pixd) != 1)
1416  return (PIX *)ERROR_PTR("pixd not binary", procName, pixd);
1417 #if EQUAL_SIZE_WARNING
1418  if (!pixSizesEqual(pixd, pixs1))
1419  L_WARNING("pixd and pixs1 not equal sizes", procName);
1420 #endif /* EQUAL_SIZE_WARNING */
1421  pixRasterop(pixd, 0, 0, w, h, PIX_SRC, pixs1, 0, 0); /* copy */
1422  pixRasterop(pixd, 0, 0, w, h, PIX_DST & PIX_NOT(PIX_SRC),
1423  pixs2, 0, 0); /* src1 & (~src2) */
1424  }
1425 
1426  return pixd;
1427 }
1428 
1429 
1430 /*-------------------------------------------------------------*
1431  * Pixel counting *
1432  *-------------------------------------------------------------*/
1433 /*!
1434  * pixZero()
1435  *
1436  * Input: pix
1437  * &empty (<return> boolean: 1 if no ON pixels, 0 otherwise)
1438  * Return: 0 if OK; 1 on error
1439  */
1440 l_int32
1442  l_int32 *pempty)
1443 {
1444 l_int32 w, h, wpl, i, j, fullwords, endbits;
1445 l_uint32 endmask;
1446 l_uint32 *data, *line;
1447 
1448  PROCNAME("pixZero");
1449 
1450  if (!pix)
1451  return ERROR_INT("pix not defined", procName, 1);
1452  if (!pempty)
1453  return ERROR_INT("pempty not defined", procName, 1);
1454 
1456  h = pixGetHeight(pix);
1457  wpl = pixGetWpl(pix);
1458  data = pixGetData(pix);
1459 
1460  fullwords = w / 32;
1461  endbits = w & 31;
1462  endmask = 0xffffffff << (32 - endbits);
1463 
1464  *pempty = 1;
1465  for (i = 0; i < h; i++) {
1466  line = data + wpl * i;
1467  for (j = 0; j < fullwords; j++)
1468  if (*line++) {
1469  *pempty = 0;
1470  return 0;
1471  }
1472  if (endbits) {
1473  if (*line & endmask) {
1474  *pempty = 0;
1475  return 0;
1476  }
1477  }
1478  }
1479 
1480  return 0;
1481 }
1482 
1483 
1484 /*!
1485  * pixCountPixels()
1486  *
1487  * Input: binary pix
1488  * &count (<return> count of ON pixels)
1489  * tab8 (<optional> 8-bit pixel lookup table)
1490  * Return: 0 if OK; 1 on error
1491  */
1492 l_int32
1494  l_int32 *pcount,
1495  l_int32 *tab8)
1496 {
1497 l_uint8 endmask;
1498 l_int32 w, h, wpl, i, j;
1499 l_int32 fullbytes, endbits, sum;
1500 l_int32 *tab;
1501 l_uint32 *line, *data;
1502 
1503  PROCNAME("pixCountPixels");
1504 
1505  if (!pix)
1506  return ERROR_INT("pix not defined", procName, 1);
1507  if (!pcount)
1508  return ERROR_INT("pcount not defined", procName, 1);
1509  if (pixGetDepth(pix) != 1)
1510  return ERROR_INT("pix not 1 bpp", procName, 1);
1511 
1512  *pcount = 0;
1513 
1514  if (!tab8) {
1515  if ((tab = makePixelSumTab8()) == NULL)
1516  return ERROR_INT("tab not made", procName, 1);
1517  }
1518  else
1519  tab = tab8;
1520 
1521  w = pixGetWidth(pix);
1522  h = pixGetHeight(pix);
1523  wpl = pixGetWpl(pix);
1524  data = pixGetData(pix);
1525 
1526  fullbytes = w / 8;
1527  endbits = w & 7;
1528  endmask = 0xff << (8 - endbits);
1529 
1530  sum = 0;
1531  for (i = 0; i < h; i++) {
1532  line = data + wpl * i;
1533  for (j = 0; j < fullbytes; j++)
1534  sum += tab[GET_DATA_BYTE(line, j)];
1535  if (endbits)
1536  sum += tab[GET_DATA_BYTE(line, fullbytes) & endmask];
1537  }
1538  *pcount = sum;
1539 
1540  if (!tab8)
1541  FREE((void *)tab);
1542  return 0;
1543 }
1544 
1545 
1546 /*!
1547  * pixaCountPixels()
1548  *
1549  * Input: pixa (array of binary pix)
1550  * Return: na of ON pixels in each pix, or null on error
1551  */
1552 NUMA *
1554 {
1555 l_int32 d, i, n, count;
1556 l_int32 *tab;
1557 NUMA *na;
1558 PIX *pix;
1559 
1560  PROCNAME("pixaCountPixels");
1561 
1562  if (!pixa)
1563  return (NUMA *)ERROR_PTR("pix not defined", procName, NULL);
1564 
1565  if ((n = pixaGetCount(pixa)) == 0)
1566  return numaCreate(1);
1567 
1568  pix = pixaGetPix(pixa, 0, L_CLONE);
1569  d = pixGetDepth(pix);
1570  pixDestroy(&pix);
1571  if (d != 1)
1572  return (NUMA *)ERROR_PTR("pixa not 1 bpp", procName, NULL);
1573 
1574  if ((tab = makePixelSumTab8()) == NULL)
1575  return (NUMA *)ERROR_PTR("tab not made", procName, NULL);
1576 
1577  if ((na = numaCreate(n)) == NULL)
1578  return (NUMA *)ERROR_PTR("na not made", procName, NULL);
1579  for (i = 0; i < n; i++) {
1580  pix = pixaGetPix(pixa, i, L_CLONE);
1582  numaAddNumber(na, count);
1583  pixDestroy(&pix);
1584  }
1585 
1586  FREE((void *)tab);
1587  return na;
1588 }
1589 
1590 
1591 /*!
1592  * pixCountPixelsInRow()
1593  *
1594  * Input: binary pix
1595  * row number
1596  * &count (<return> sum of ON pixels in raster line)
1597  * tab8 (<optional> 8-bit pixel lookup table)
1598  * Return: 0 if OK; 1 on error
1599  */
1600 l_int32
1602  l_int32 row,
1603  l_int32 *pcount,
1604  l_int32 *tab8)
1605 {
1606 l_uint8 endmask;
1607 l_int32 j, w, h, wpl;
1608 l_int32 fullbytes, endbits, sum;
1609 l_int32 *tab;
1610 l_uint32 *line;
1611 
1612  PROCNAME("pixCountPixelsInRow");
1613 
1614  if (!pix)
1615  return ERROR_INT("pix not defined", procName, 1);
1616  if (!pcount)
1617  return ERROR_INT("pcount not defined", procName, 1);
1618  if (pixGetDepth(pix) != 1)
1619  return ERROR_INT("pix not 1 bpp", procName, 1);
1620 
1621  *pcount = 0;
1622 
1623  w = pixGetWidth(pix);
1624  h = pixGetHeight(pix);
1625  if (row < 0 || row >= h)
1626  return ERROR_INT("row out of bounds", procName, 1);
1627  wpl = pixGetWpl(pix);
1628  line = pixGetData(pix) + row * wpl;
1629 
1630  fullbytes = w / 8;
1631  endbits = w & 7;
1632  endmask = 0xff << (8 - endbits);
1633 
1634  if (!tab8) {
1635  if ((tab = makePixelSumTab8()) == NULL)
1636  return ERROR_INT("tab not made", procName, 1);
1637  }
1638  else
1639  tab = tab8;
1640 
1641  sum = 0;
1642  for (j = 0; j < fullbytes; j++)
1643  sum += tab[GET_DATA_BYTE(line, j)];
1644  if (endbits)
1645  sum += tab[GET_DATA_BYTE(line, fullbytes) & endmask];
1646  *pcount = sum;
1647 
1648  if (!tab8)
1649  FREE((void *)tab);
1650  return 0;
1651 }
1652 
1653 
1654 /*!
1655  * pixCountPixelsByRow()
1656  *
1657  * Input: binary pix
1658  * tab8 (<optional> 8-bit pixel lookup table)
1659  * Return: na of counts, or null on error
1660  */
1661 NUMA *
1663  l_int32 *tab8)
1664 {
1665 l_int32 w, h, i, count;
1666 l_int32 *tab;
1667 NUMA *na;
1668 
1669  PROCNAME("pixCountPixelsByRow");
1670 
1671  if (!pix)
1672  return (NUMA *)ERROR_PTR("pix not defined", procName, NULL);
1673  if (pixGetDepth(pix) != 1)
1674  return (NUMA *)ERROR_PTR("pix not 1 bpp", procName, NULL);
1675 
1676  w = pixGetWidth(pix);
1677  h = pixGetHeight(pix);
1678 
1679  if (!tab8) {
1680  if ((tab = makePixelSumTab8()) == NULL)
1681  return (NUMA *)ERROR_PTR("tab not made", procName, NULL);
1682  }
1683  else
1684  tab = tab8;
1685 
1686  if ((na = numaCreate(h)) == NULL)
1687  return (NUMA *)ERROR_PTR("na not made", procName, NULL);
1688 
1689  for (i = 0; i < h; i++) {
1691  numaAddNumber(na, count);
1692  }
1693 
1694  if (!tab8)
1695  FREE((void *)tab);
1696 
1697  return na;
1698 }
1699 
1700 
1701 /*!
1702  * pixThresholdPixels()
1703  *
1704  * Input: binary pix
1705  * threshold
1706  * &above (<return> 1 if above threshold;
1707  * 0 if equal to or less than threshold)
1708  * tab8 (8-bit pixel lookup table)
1709  * Return: 0 if OK; 1 on error
1710  *
1711  * Note: This sums the ON pixels and returns immediately if the count
1712  * goes above threshold. It is therefore more efficient
1713  * for matching images (by running this function on the xor of
1714  * the 2 images) than using pixCountPixels(), which counts all
1715  * pixels before returning.
1716  */
1717 l_int32
1719  l_int32 thresh,
1720  l_int32 *pabove,
1721  l_int32 *tab8)
1722 {
1723 l_uint8 endmask;
1724 l_int32 w, h, wpl, i, j;
1725 l_int32 fullbytes, endbits, sum;
1726 l_uint32 *line, *data;
1727 
1728  PROCNAME("pixThresholdPixels");
1729 
1730  if (!pix)
1731  return ERROR_INT("pix not defined", procName, 1);
1732  if (!pabove)
1733  return ERROR_INT("pabove not defined", procName, 1);
1734  if (!tab8)
1735  return ERROR_INT("tab8 not defined", procName, 1);
1736  if (pixGetDepth(pix) != 1)
1737  return ERROR_INT("pix not 1 bpp", procName, 1);
1738 
1739  *pabove = 0; /* init */
1740 
1741  w = pixGetWidth(pix);
1742  h = pixGetHeight(pix);
1743  wpl = pixGetWpl(pix);
1744  data = pixGetData(pix);
1745 
1746  fullbytes = w / 8;
1747  endbits = w & 7;
1748  endmask = 0xff << (8 - endbits);
1749 
1750  sum = 0;
1751  for (i = 0; i < h; i++) {
1752  line = data + wpl * i;
1753  for (j = 0; j < fullbytes; j++)
1754  sum += tab8[GET_DATA_BYTE(line, j)];
1755  if (endbits)
1756  sum += tab8[GET_DATA_BYTE(line, fullbytes) & endmask];
1757  if (sum > thresh) {
1758  *pabove = 1;
1759  return 0;
1760  }
1761  }
1762 
1763  return 0;
1764 }
1765 
1766 
1767 /*!
1768  * makePixelSumTab8()
1769  *
1770  * Input: void
1771  * Return: table of 256 l_int32, or null on error
1772  *
1773  * This table of integers gives the number of 1 bits in the 8 bit index
1774  */
1775 l_int32 *
1777 {
1778 l_uint8 byte;
1779 l_int32 i;
1780 l_int32 *tab;
1781 
1782  PROCNAME("makePixelSumTab8");
1783 
1784  if ((tab = (l_int32 *)CALLOC(256, sizeof(l_int32))) == NULL)
1785  return (l_int32 *)ERROR_PTR("tab not made", procName, NULL);
1786 
1787  for (i = 0; i < 256; i++) {
1788  byte = (l_uint8)i;
1789  tab[i] = (byte & 0x1) +
1790  ((byte >> 1) & 0x1) +
1791  ((byte >> 2) & 0x1) +
1792  ((byte >> 3) & 0x1) +
1793  ((byte >> 4) & 0x1) +
1794  ((byte >> 5) & 0x1) +
1795  ((byte >> 6) & 0x1) +
1796  ((byte >> 7) & 0x1);
1797  }
1798 
1799  return tab;
1800 }
1801 
1802 
1803 /*------------------------------------------------------------------*
1804  * Gray Histogram *
1805  *------------------------------------------------------------------*/
1806 /*!
1807  * pixGrayHistogram()
1808  *
1809  * Input: pix (1, 2, 4, 8, 16 bpp)
1810  * Return: na (histogram), or null on error
1811  */
1812 NUMA *
1814 {
1815 l_int32 i, j, w, h, d, wpl, val, size;
1816 l_uint32 *data, *line;
1817 l_float32 *array;
1818 NUMA *na;
1819 
1820  PROCNAME("pixGrayHistogram");
1821 
1822  if (!pixs)
1823  return (NUMA *)ERROR_PTR("pixs not defined", procName, NULL);
1824  d = pixGetDepth(pixs);
1825  if (d > 16)
1826  return (NUMA *)ERROR_PTR("depth not in {1,2,4,8,16}", procName, NULL);
1827 
1828  w = pixGetWidth(pixs);
1829  h = pixGetHeight(pixs);
1830  wpl = pixGetWpl(pixs);
1831  data = pixGetData(pixs);
1832 
1833  size = 1 << d;
1834 
1835  na = numaCreate(size);
1836  na->n = size; /* fake storage of zeroes */
1837  array = na->array; /* don't do this at home */
1838 
1839  for (i = 0; i < h; i++) {
1840  line = data + i * wpl;
1841  switch (d)
1842  {
1843  case 1:
1844  for (j = 0; j < w; j++) {
1845  val = GET_DATA_BIT(line, j);
1846  array[val] += 1.0;
1847  }
1848  break;
1849  case 2:
1850  for (j = 0; j < w; j++) {
1851  val = GET_DATA_DIBIT(line, j);
1852  array[val] += 1.0;
1853  }
1854  break;
1855  case 4:
1856  for (j = 0; j < w; j++) {
1857  val = GET_DATA_QBIT(line, j);
1858  array[val] += 1.0;
1859  }
1860  break;
1861  case 8:
1862  for (j = 0; j < w; j++) {
1863  val = GET_DATA_BYTE(line, j);
1864  array[val] += 1.0;
1865  }
1866  break;
1867  case 16:
1868  for (j = 0; j < w; j++) {
1870  array[val] += 1.0;
1871  }
1872  break;
1873  default:
1874  numaDestroy(&na);
1875  return (NUMA *)ERROR_PTR("illegal depth", procName, NULL);
1876  }
1877  }
1878 
1879  return na;
1880 }
1881 
1882 
1883 
1884 /*-------------------------------------------------------------*
1885  * Pixel endian conversion *
1886  *-------------------------------------------------------------*/
1887 /*!
1888  * pixEndianByteSwapNew()
1889  *
1890  * Input: pixs
1891  * Return: pixd, or null on error
1892  *
1893  * Notes:
1894  * (1) This is used to convert the data in a pix to a
1895  * serialized byte buffer in raster order, and, for RGB,
1896  * in order RGBA. This requires flipping bytes within
1897  * each 32-bit word for little-endian platforms, because the
1898  * words have a MSB-to-the-left rule, whereas byte raster-order
1899  * requires the left-most byte in each word to be byte 0.
1900  * For big-endians, no swap is necessary, so this returns a clone.
1901  * (2) Unlike pixEndianByteSwap(), which swaps the bytes in-place,
1902  * this returns a new pix (or a clone). We provide this
1903  * because often when serialization is done, the source
1904  * pix needs to be restored to canonical little-endian order,
1905  * and this requires a second byte swap. In such a situation,
1906  * it is twice as fast to make a new pix in big-endian order,
1907  * use it, and destroy it.
1908  */
1909 PIX *
1911 {
1912 l_uint32 *datas, *datad;
1913 l_int32 i, j, h, wpl;
1914 l_uint32 word;
1915 PIX *pixd;
1916 
1917  PROCNAME("pixEndianByteSwapNew");
1918 
1919 #ifdef L_BIG_ENDIAN
1920 
1921  return pixClone(pixs);
1922 
1923 #else /* L_LITTLE_ENDIAN */
1924 
1925  if (!pixs)
1926  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1927 
1928  datas = pixGetData(pixs);
1929  wpl = pixGetWpl(pixs);
1930  h = pixGetHeight(pixs);
1931  pixd = pixCreateTemplate(pixs);
1932  datad = pixGetData(pixd);
1933  for (i = 0; i < h; i++) {
1934  for (j = 0; j < wpl; j++, datas++, datad++) {
1935  word = *datas;
1936  *datad = (word >> 24) |
1937  ((word >> 8) & 0x0000ff00) |
1938  ((word << 8) & 0x00ff0000) |
1939  (word << 24);
1940  }
1941  }
1942 
1943  return pixd;
1944 
1945 #endif /* L_BIG_ENDIAN */
1946 
1947 }
1948 
1949 
1950 /*!
1951  * pixEndianByteSwap()
1952  *
1953  * Input: pix
1954  * Return: 0 if OK, 1 on error
1955  *
1956  * Note: This is used on a little-endian platform to swap the bytes
1957  * within a word, where bytes 0 and 3 are swapped, and bytes
1958  * 1 and 2 are swapped. This is required for little-endians
1959  * in situations where we convert from a serialized byte order
1960  * that is in raster order, as one typically has in file formats,
1961  * to one with MSB-to-the-left in each 32-bit word, or v.v.
1962  * See pix.h for a description of the canonical format
1963  * (MSB-to-the left) that is used for both little-endian
1964  * and big-endian platforms. For big-endians, the MSB-to-the-left
1965  * word order has the bytes in raster order when serialized,
1966  * so no byte flipping is required.
1967  */
1968 l_int32
1970 {
1971 l_uint32 *data;
1972 l_int32 i, j, h, wpl;
1973 l_uint32 word;
1974 
1975  PROCNAME("pixEndianByteSwap");
1976 
1977 #ifdef L_BIG_ENDIAN
1978 
1979  return 0;
1980 
1981 #else /* L_LITTLE_ENDIAN */
1982 
1983  if (!pix)
1984  return ERROR_INT("pix not defined", procName, 1);
1985 
1986  data = pixGetData(pix);
1987  wpl = pixGetWpl(pix);
1988  h = pixGetHeight(pix);
1989  for (i = 0; i < h; i++) {
1990  for (j = 0; j < wpl; j++, data++) {
1991  word = *data;
1992  *data = (word >> 24) |
1993  ((word >> 8) & 0x0000ff00) |
1994  ((word << 8) & 0x00ff0000) |
1995  (word << 24);
1996  }
1997  }
1998 
1999  return 0;
2000 
2001 #endif /* L_BIG_ENDIAN */
2002 
2003 }
2004 
2005 
2006 /*!
2007  * pixEndianTwoByteSwap()
2008  *
2009  * Input: pix
2010  * Return: 0 if OK, 1 on error
2011  *
2012  * Note: swaps the 2-byte entities within a 32-bit word, for
2013  * little-endian platforms only. This is equivalent to a
2014  * full byte swap, as performed by pixEndianByteSwap(),
2015  * followed by byte swaps in each of the 16-bit entities separately.
2016  */
2017 l_int32
2019 {
2020 l_uint32 *data;
2021 l_int32 i, j, h, wpl;
2022 l_uint32 word;
2023 
2024  PROCNAME("pixEndianTwoByteSwap");
2025 
2026 #ifdef L_BIG_ENDIAN
2027 
2028  return 0;
2029 
2030 #else /* L_LITTLE_ENDIAN */
2031 
2032  if (!pix)
2033  return ERROR_INT("pix not defined", procName, 1);
2034 
2035  data = pixGetData(pix);
2036  wpl = pixGetWpl(pix);
2037  h = pixGetHeight(pix);
2038  for (i = 0; i < h; i++) {
2039  for (j = 0; j < wpl; j++, data++) {
2040  word = *data;
2041  *data = ((word << 16) & 0xffff0000) |
2042  ((word >> 16) & 0x0000ffff);
2043  }
2044  }
2045 
2046  return 0;
2047 
2048 #endif /* L_BIG_ENDIAN */
2049 
2050 }
2051 
2052 
2053 /*-------------------------------------------------------------*
2054  * Color sample setting and extraction *
2055  *-------------------------------------------------------------*/
2056 /*!
2057  * pixCreateRGBImage()
2058  *
2059  * Input: 8 bpp red pix
2060  * 8 bpp green pix
2061  * 8 bpp blue pix
2062  * Return: 32 bpp pix, interleaved with 4 samples/pixel,
2063  * or null on error
2064  *
2065  * Notes:
2066  * (1) the 4th byte, sometimes called the "alpha channel",
2067  * and which is often used for blending between different
2068  * images, is left with 0 value.
2069  * (2) see Note (4) in pix.h for details on storage of
2070  * 8-bit samples within each 32-bit word.
2071  */
2072 PIX *
2074  PIX *pixg,
2075  PIX *pixb)
2076 {
2077 l_int32 w, h;
2078 PIX *pixd;
2079 
2080  PROCNAME("pixCreateRGBImage");
2081 
2082  if (!pixr)
2083  return (PIX *)ERROR_PTR("pixr not defined", procName, NULL);
2084  if (!pixg)
2085  return (PIX *)ERROR_PTR("pixg not defined", procName, NULL);
2086  if (!pixb)
2087  return (PIX *)ERROR_PTR("pixb not defined", procName, NULL);
2088  if (pixGetDepth(pixr) != 8)
2089  return (PIX *)ERROR_PTR("pixr not 8 bpp", procName, NULL);
2090  if (pixGetDepth(pixg) != 8)
2091  return (PIX *)ERROR_PTR("pixg not 8 bpp", procName, NULL);
2092  if (pixGetDepth(pixb) != 8)
2093  return (PIX *)ERROR_PTR("pixb not 8 bpp", procName, NULL);
2094 
2095  w = pixGetWidth(pixr);
2096  h = pixGetHeight(pixr);
2097  if (w != pixGetWidth(pixg) || w != pixGetWidth(pixb))
2098  return (PIX *)ERROR_PTR("widths not the same", procName, NULL);
2099  if (h != pixGetHeight(pixg) || h != pixGetHeight(pixb))
2100  return (PIX *)ERROR_PTR("heights not the same", procName, NULL);
2101 
2102  if ((pixd = pixCreate(w, h, 32)) == NULL)
2103  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
2104  pixCopyResolution(pixd, pixr);
2105  pixSetRGBComponent(pixd, pixr, COLOR_RED);
2106  pixSetRGBComponent(pixd, pixg, COLOR_GREEN);
2107  pixSetRGBComponent(pixd, pixb, COLOR_BLUE);
2108 
2109  return pixd;
2110 }
2111 
2112 
2113 /*!
2114  * pixGetRGBComponent()
2115  *
2116  * Input: pixs (32 bpp)
2117  * color (one of {COLOR_RED, COLOR_GREEN, COLOR_BLUE})
2118  * Return: pixd, the selected 8 bpp component image of the
2119  * input 32 bpp image, or null on error
2120  */
2121 PIX *
2123  l_int32 color)
2124 {
2125 l_uint8 srcbyte;
2126 l_uint32 *lines, *lined;
2127 l_uint32 *datas, *datad;
2128 l_int32 i, j, w, h;
2129 l_int32 wpls, wpld;
2130 PIX *pixd;
2131 
2132  PROCNAME("pixGetRGBComponent");
2133 
2134  if (!pixs)
2135  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
2136  if (pixGetDepth(pixs) != 32)
2137  return (PIX *)ERROR_PTR("pixs not 32 bpp", procName, NULL);
2138  if (color != COLOR_RED && color != COLOR_GREEN && color != COLOR_BLUE)
2139  return (PIX *)ERROR_PTR("invalid color", procName, NULL);
2140 
2141  w = pixGetWidth(pixs);
2142  h = pixGetHeight(pixs);
2143  if ((pixd = pixCreate(w, h, 8)) == NULL)
2144  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
2145  pixCopyResolution(pixd, pixs);
2146  wpls = pixGetWpl(pixs);
2147  wpld = pixGetWpl(pixd);
2148  datas = pixGetData(pixs);
2149  datad = pixGetData(pixd);
2150 
2151  for (i = 0; i < h; i++) {
2152  lines = datas + i * wpls;
2153  lined = datad + i * wpld;
2154  for (j = 0; j < w; j++) {
2155  srcbyte = GET_DATA_BYTE(lines + j, color);
2156  SET_DATA_BYTE(lined, j, srcbyte);
2157  }
2158  }
2159 
2160  return pixd;
2161 }
2162 
2163 
2164 /*!
2165  * pixSetRGBComponent()
2166  *
2167  * Input: pixd (32 bpp)
2168  * pixs (8 bpp)
2169  * color (one of {COLOR_RED, COLOR_GREEN, COLOR_BLUE})
2170  * Return: 0 if OK; 1 on error
2171  *
2172  * Action: places specificed 8 bpp color component interleaved
2173  * appropriately in 32 bpp dest
2174  */
2175 l_int32
2177  PIX *pixs,
2178  l_int32 color)
2179 {
2180 l_uint8 srcbyte;
2181 l_int32 i, j, w, h;
2182 l_int32 wpls, wpld;
2183 l_uint32 *lines, *lined;
2184 l_uint32 *datas, *datad;
2185 
2186  PROCNAME("pixSetRGBComponent");
2187 
2188  if (!pixd)
2189  return ERROR_INT("pixd not defined", procName, 1);
2190  if (!pixs)
2191  return ERROR_INT("pixs not defined", procName, 1);
2192 
2193  if (pixGetDepth(pixd) != 32)
2194  return ERROR_INT("pixd not 32 bpp", procName, 1);
2195  if (pixGetDepth(pixs) != 8)
2196  return ERROR_INT("pixs not 8 bpp", procName, 1);
2197  if (color != COLOR_RED && color != COLOR_GREEN && color != COLOR_BLUE)
2198  return ERROR_INT("invalid color", procName, 1);
2199  w = pixGetWidth(pixs);
2200  h = pixGetHeight(pixs);
2201  if (w != pixGetWidth(pixd) || h != pixGetHeight(pixd))
2202  return ERROR_INT("sizes not commensurate", procName, 1);
2203 
2204  datas = pixGetData(pixs);
2205  datad = pixGetData(pixd);
2206  wpls = pixGetWpl(pixs);
2207  wpld = pixGetWpl(pixd);
2208 
2209  for (i = 0; i < h; i++) {
2210  lines = datas + i * wpls;
2211  lined = datad + i * wpld;
2212  for (j = 0; j < w; j++) {
2213  srcbyte = GET_DATA_BYTE(lines, j);
2214  SET_DATA_BYTE(lined + j, color, srcbyte);
2215  }
2216  }
2217 
2218  return 0;
2219 }
2220 
2221 
2222 /*!
2223  * composeRGBPixel()
2224  *
2225  * Input: rval, gval, bval
2226  * &rgbpixel (<return> 32-bit pixel)
2227  * Return: 0 if OK; 1 on error
2228  */
2229 l_int32
2231  l_int32 gval,
2232  l_int32 bval,
2233  l_uint32 *ppixel)
2234 {
2235  PROCNAME("composeRGBPixel");
2236 
2237  if (!ppixel)
2238  return ERROR_INT("&pixel not defined", procName, 1);
2239 
2240  *ppixel = 0; /* want the alpha byte to be 0 */
2241  SET_DATA_BYTE(ppixel, COLOR_RED, rval);
2242  SET_DATA_BYTE(ppixel, COLOR_GREEN, gval);
2243  SET_DATA_BYTE(ppixel, COLOR_BLUE, bval);
2244  return 0;
2245 }
2246 
2247 
2248 /*!
2249  * pixGetRGBLine()
2250  *
2251  * Input: pixs (32 bpp)
2252  * row
2253  * bufr (array of red samples; size w bytes)
2254  * bufg (array of green samples; size w bytes)
2255  * bufb (array of blue samples; size w bytes)
2256  * Return: 0 if OK; 1 on error
2257  *
2258  * Action: puts rgb components from the input line in pixs
2259  * into the given buffers
2260  */
2261 l_int32
2263  l_int32 row,
2264  l_uint8 *bufr,
2265  l_uint8 *bufg,
2266  l_uint8 *bufb)
2267 {
2268 l_uint32 *lines;
2269 l_int32 j, w, h;
2270 l_int32 wpls;
2271 
2272  PROCNAME("pixGetRGBLine");
2273 
2274  if (!pixs)
2275  return ERROR_INT("pixs not defined", procName, 1);
2276  if (pixGetDepth(pixs) != 32)
2277  return ERROR_INT("pixs not 32 bpp", procName, 1);
2278  if (!bufr || !bufg || !bufb)
2279  return ERROR_INT("buffer not defined", procName, 1);
2280 
2281  w = pixGetWidth(pixs);
2282  h = pixGetHeight(pixs);
2283  if (row < 0 || row >= h)
2284  return ERROR_INT("row out of bounds", procName, 1);
2285  wpls = pixGetWpl(pixs);
2286  lines = pixGetData(pixs) + row * wpls;
2287 
2288  for (j = 0; j < w; j++) {
2289  bufr[j] = GET_DATA_BYTE(lines + j, COLOR_RED);
2290  bufg[j] = GET_DATA_BYTE(lines + j, COLOR_GREEN);
2291  bufb[j] = GET_DATA_BYTE(lines + j, COLOR_BLUE);
2292  }
2293 
2294  return 0;
2295 }
2296 
2297 
2298 /*-------------------------------------------------------------*
2299  * Add and remove border *
2300  *-------------------------------------------------------------*/
2301 /*!
2302  * pixAddBorder()
2303  *
2304  * Input: pix
2305  * npix (number of pixels to be added to each side)
2306  * val (value of added border pixels)
2307  * Return: pix with the input pix centered, or null on error.
2308  *
2309  * For binary images:
2310  * white: val = 0
2311  * black: val = 1
2312  * For grayscale images:
2313  * white: val = 2 ** d - 1
2314  * black: val = 0
2315  * For RGB color images:
2316  * white: val = 0xffffff00
2317  * black: val = 0
2318  */
2319 PIX *
2321  l_int32 npix,
2322  l_uint32 val)
2323 {
2324 l_int32 ws, hs, wd, hd, d;
2325 PIX *pixd;
2326 
2327  PROCNAME("pixAddBorder");
2328 
2329  if (!pixs)
2330  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
2331 
2332  if (npix == 0)
2333  return pixClone(pixs);
2334 
2335  d = pixGetDepth(pixs);
2336  ws = pixGetWidth(pixs);
2337  hs = pixGetHeight(pixs);
2338  wd = ws + 2 * npix;
2339  hd = hs + 2 * npix;
2340  if ((pixd = pixCreate(wd, hd, d)) == NULL)
2341  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
2342  pixCopyResolution(pixd, pixs);
2343  pixCopyColormap(pixd, pixs);
2344 
2345  pixSetAllArbitrary(pixd, val); /* a little extra writing ! */
2346 
2347  pixRasterop(pixd, npix, npix, ws, hs, PIX_SRC, pixs, 0, 0);
2348 
2349  return pixd;
2350 }
2351 
2352 
2353 /*!
2354  * pixRemoveBorder()
2355  *
2356  * Input: pixs
2357  * npix (number to be removed from each of the 4 sides)
2358  * Return: pixd, or null on error
2359  */
2360 PIX *
2362  l_int32 npix)
2363 {
2364 l_int32 ws, hs, wd, hd, d;
2365 PIX *pixd;
2366 
2367  PROCNAME("pixRemoveBorder");
2368 
2369  if (!pixs)
2370  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
2371 
2372  if (npix == 0)
2373  return pixClone(pixs);
2374 
2375  d = pixGetDepth(pixs);
2376  ws = pixGetWidth(pixs);
2377  hs = pixGetHeight(pixs);
2378  wd = ws - 2 * npix;
2379  hd = hs - 2 * npix;
2380  if (wd <= 0)
2381  return (PIX *)ERROR_PTR("width must be > 0", procName, NULL);
2382  if (hd <= 0)
2383  return (PIX *)ERROR_PTR("height must be > 0", procName, NULL);
2384  if ((pixd = pixCreate(wd, hd, d)) == NULL)
2385  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
2386  pixCopyResolution(pixd, pixs);
2387  pixCopyColormap(pixd, pixs);
2388 
2389  /* rasterop from the center */
2390  pixRasterop(pixd, 0, 0, wd, hd, PIX_SRC, pixs, npix, npix);
2391 
2392  return pixd;
2393 }
2394 
2395 
2396 /*!
2397  * pixAddBorderGeneral()
2398  *
2399  * Input: pix
2400  * leftpix, rightpix, toppix, bottompix (number of pixels
2401  * to be added to each side)
2402  * val (value of added border pixels)
2403  * Return: pix with the input pix placed properly, or null on error
2404  *
2405  * For binary images:
2406  * white: val = 0
2407  * black: val = 1
2408  * For grayscale images:
2409  * white: val = 2 ** d - 1
2410  * black: val = 0
2411  * For RGB color images:
2412  * white: val = 0xffffff00
2413  * black: val = 0
2414  */
2415 PIX *
2417  l_int32 leftpix,
2418  l_int32 rightpix,
2419  l_int32 toppix,
2420  l_int32 bottompix,
2421  l_uint32 val)
2422 {
2423 l_int32 ws, hs, wd, hd, d;
2424 PIX *pixd;
2425 
2426  PROCNAME("pixAddBorderGeneral");
2427 
2428  if (!pixs)
2429  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
2430 
2431  d = pixGetDepth(pixs);
2432  ws = pixGetWidth(pixs);
2433  hs = pixGetHeight(pixs);
2434  wd = ws + leftpix + rightpix;
2435  hd = hs + toppix + bottompix;
2436  if ((pixd = pixCreate(wd, hd, d)) == NULL)
2437  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
2438  pixCopyResolution(pixd, pixs);
2439  pixCopyColormap(pixd, pixs);
2440 
2441  pixSetAllArbitrary(pixd, val); /* a little extra writing ! */
2442 
2443  pixRasterop(pixd, leftpix, toppix, ws, hs, PIX_SRC, pixs, 0, 0);
2444 
2445  return pixd;
2446 }
2447 
2448 
2449 /*!
2450  * pixRemoveBorderGeneral()
2451  *
2452  * Input: pixs
2453  * leftpix, rightpix, toppix, bottompix (number of pixels
2454  * to be removed from each side)
2455  * Return: pixd with pixels removed around border, or null on error
2456  */
2457 PIX *
2459  l_int32 leftpix,
2460  l_int32 rightpix,
2461  l_int32 toppix,
2462  l_int32 bottompix)
2463 {
2464 l_int32 ws, hs, wd, hd, d;
2465 PIX *pixd;
2466 
2467  PROCNAME("pixRemoveBorderGeneral");
2468 
2469  if (!pixs)
2470  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
2471 
2472  d = pixGetDepth(pixs);
2473  ws = pixGetWidth(pixs);
2474  hs = pixGetHeight(pixs);
2475  wd = ws - leftpix - rightpix;
2476  hd = hs - toppix - bottompix;
2477  if (wd <= 0)
2478  return (PIX *)ERROR_PTR("width must be > 0", procName, NULL);
2479  if (hd <= 0)
2480  return (PIX *)ERROR_PTR("height must be > 0", procName, NULL);
2481  if ((pixd = pixCreate(wd, hd, d)) == NULL)
2482  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
2483  pixCopyResolution(pixd, pixs);
2484  pixCopyColormap(pixd, pixs);
2485 
2486  pixRasterop(pixd, 0, 0, wd, hd, PIX_SRC, pixs, leftpix, toppix);
2487 
2488  return pixd;
2489 }
2490 
2491 
2492 /*------------------------------------------------------------------*
2493  * Test for pix equality *
2494  *------------------------------------------------------------------*/
2495 /*!
2496  * pixEqual()
2497  *
2498  * Input: pix1
2499  * pix2
2500  * &same (<return> 1 if same; 0 if different)
2501  * Return: 0 if OK; 1 on error
2502  *
2503  * Notes:
2504  * (1) Equality is defined as having the same pixel values for
2505  * each respective image pixel.
2506  * (2) This works on two pix of any depth. If one or both pix
2507  * have a colormap, the depths can be different and the
2508  * two pix can still be equal.
2509  * (3) If both pix have colormaps and the depths are equal,
2510  * use the pixEqualWithCmap() function, which does a fast
2511  * comparison if the colormaps are identical and a relatively
2512  * slow comparison otherwise.
2513  * (4) In all other cases, any existing colormaps must first be
2514  * removed before doing pixel comparison. After the colormaps
2515  * are removed, the resulting two images must have the same depth.
2516  * The "lowest common denominator" is RGB, but this is only
2517  * chosen when necessary, or when both have colormaps but
2518  * different depths.
2519  * (5) For 32 bpp, ignore the bits in the 4th byte (the 'A' byte
2520  * of the RGBA pixel)
2521  * (6) For images without colormaps that are not 32 bpp, all bits
2522  * in the image part of the data array must be identical.
2523  */
2524 l_int32
2526  PIX *pix2,
2527  l_int32 *psame)
2528 {
2529 l_int32 w, h, d, d2, wpl1, wpl2, i, j, color;
2530 l_int32 fullwords, linebits, endbits;
2531 l_uint32 endmask;
2532 l_uint32 *data1, *data2, *line1, *line2;
2533 PIX *pixt1, *pixt2;
2534 PIXCMAP *cmap1, *cmap2;
2535 
2536  PROCNAME("pixEqual");
2537 
2538  if (!psame)
2539  return ERROR_INT("psamel not defined", procName, 1);
2540  *psame = 0; /* pix are different unless we exit after checking all data */
2541 
2542  if (!pix1)
2543  return ERROR_INT("pix1 not defined", procName, 1);
2544  if (!pix2)
2545  return ERROR_INT("pix2 not defined", procName, 1);
2546 
2547  w = pixGetWidth(pix1);
2548  if (w != pixGetWidth(pix2)) {
2549  L_INFO("pix widths unequal", procName);
2550  return 0;
2551  }
2552  h = pixGetHeight(pix1);
2553  if (h != pixGetHeight(pix2)) {
2554  L_INFO("pix heights unequal", procName);
2555  return 0;
2556  }
2557 
2558  cmap1 = pixGetColormap(pix1);
2559  cmap2 = pixGetColormap(pix2);
2560  d = pixGetDepth(pix1);
2561  d2 = pixGetDepth(pix2);
2562 
2563  if (!cmap1 && !cmap2 && (d != d2)) {
2564  L_INFO("pix depths unequal and no colormaps", procName);
2565  return 0;
2566  }
2567 
2568  if (cmap1 && cmap2 && (d == d2)) /* use special function */
2569  return pixEqualWithCmap(pix1, pix2, psame);
2570 
2571  /* Must remove colormaps if they exist, and in the process
2572  * end up with the resulting images having the same depth. */
2573  if (cmap1 && !cmap2) {
2574  pixcmapHasColor(cmap1, &color);
2575  if (color && d2 <= 8) /* can't be equal */
2576  return 0;
2577  if (d2 <= 8)
2579  else
2581  pixt2 = pixClone(pix2);
2582  }
2583  else if (!cmap1 && cmap2) {
2585  if (color && d <= 8) /* can't be equal */
2586  return 0;
2587  pixt1 = pixClone(pix1);
2588  if (d <= 8)
2590  else
2592  }
2593  else if (cmap1 && cmap2) { /* depths not equal; use rgb */
2596  }
2597  else { /* no colormaps */
2598  pixt1 = pixClone(pix1);
2599  pixt2 = pixClone(pix2);
2600  }
2601 
2602  d = pixGetDepth(pixt1);
2603  if (d != pixGetDepth(pixt2)) {
2604  pixDestroy(&pixt1);
2605  pixDestroy(&pixt2);
2606  L_INFO("intrinsic pix depths unequal", procName);
2607  return 0;
2608  }
2609 
2610  wpl1 = pixGetWpl(pixt1);
2611  wpl2 = pixGetWpl(pixt2);
2612  data1 = pixGetData(pixt1);
2613  data2 = pixGetData(pixt2);
2614 
2615  if (d == 32) { /* assume RGBA, with A = don't-care */
2616  for (i = 0; i < h; i++) {
2617  line1 = data1 + wpl1 * i;
2618  line2 = data2 + wpl2 * i;
2619  for (j = 0; j < wpl1; j++) {
2620  if ((*line1 ^ *line2) & 0xffffff00) {
2621  pixDestroy(&pixt1);
2622  pixDestroy(&pixt2);
2623  return 0;
2624  }
2625  line1++;
2626  line2++;
2627  }
2628  }
2629  }
2630  else { /* all bits count */
2631  linebits = d * w;
2632  fullwords = linebits / 32;
2633  endbits = linebits & 31;
2634  endmask = 0xffffffff << (32 - endbits);
2635  for (i = 0; i < h; i++) {
2636  line1 = data1 + wpl1 * i;
2637  line2 = data2 + wpl2 * i;
2638  for (j = 0; j < fullwords; j++) {
2639  if (*line1 ^ *line2) {
2640  pixDestroy(&pixt1);
2641  pixDestroy(&pixt2);
2642  return 0;
2643  }
2644  line1++;
2645  line2++;
2646  }
2647  if (endbits) {
2648  if ((*line1 ^ *line2) & endmask) {
2649  pixDestroy(&pixt1);
2650  pixDestroy(&pixt2);
2651  return 0;
2652  }
2653  }
2654  }
2655  }
2656 
2657  pixDestroy(&pixt1);
2658  pixDestroy(&pixt2);
2659  *psame = 1;
2660  return 0;
2661 }
2662 
2663 
2664 /*!
2665  * pixEqualWithCmap()
2666  *
2667  * Input: pix1
2668  * pix2
2669  * &same
2670  * Return: 0 if OK, 1 on error
2671  *
2672  * Notes:
2673  * (1) This returns same = TRUE if the images have identical content.
2674  * (2) Both pix must have a colormap, and be of equal size and depth.
2675  * If these conditions are not satisfied, it is not an error;
2676  * the returned result is same = FALSE.
2677  * (3) We then check whether the colormaps are the same; if so,
2678  * the comparison proceeds 32 bits at a time.
2679  * (4) If the colormaps are different, the comparison is done by
2680  * slow brute force.
2681  */
2682 l_int32
2684  PIX *pix2,
2685  l_int32 *psame)
2686 {
2687 l_int32 d, w, h, wpl1, wpl2, i, j, linebits, fullwords, endbits;
2688 l_int32 nc1, nc2, samecmaps;
2689 l_int32 rval1, rval2, gval1, gval2, bval1, bval2;
2690 l_uint32 endmask, val1, val2;
2691 l_uint32 *data1, *data2, *line1, *line2;
2692 PIXCMAP *cmap1, *cmap2;
2693 
2694  PROCNAME("pixEqualWithCmap");
2695 
2696  if (!psame)
2697  return ERROR_INT("&same not defined", procName, 1);
2698  *psame = 0;
2699  if (!pix1)
2700  return ERROR_INT("pix1 not defined", procName, 1);
2701  if (!pix2)
2702  return ERROR_INT("pix2 not defined", procName, 1);
2703 
2704  if (pixSizesEqual(pix1, pix2) == 0)
2705  return 0;
2706 
2707  cmap1 = pixGetColormap(pix1);
2708  cmap2 = pixGetColormap(pix2);
2709  if (!cmap1 || !cmap2) {
2710  L_INFO("both images don't have colormap", procName);
2711  return 0;
2712  }
2713  d = pixGetDepth(pix1);
2714  if (d != 1 && d != 2 && d != 4 && d != 8) {
2715  L_INFO("pix depth not in {1, 2, 4, 8}", procName);
2716  return 0;
2717  }
2718 
2719  nc1 = pixcmapGetCount(cmap1);
2720  nc2 = pixcmapGetCount(cmap2);
2721  samecmaps = TRUE;
2722  if (nc1 != nc2) {
2723  L_INFO("colormap sizes are different", procName);
2724  samecmaps = FALSE;
2725  }
2726 
2727  /* Check if colormaps are identical */
2728  if (samecmaps == TRUE) {
2729  for (i = 0; i < nc1; i++) {
2730  pixcmapGetColor(cmap1, i, &rval1, &gval1, &bval1);
2731  pixcmapGetColor(cmap2, i, &rval2, &gval2, &bval2);
2732  if (rval1 != rval2 || gval1 != gval2 || bval1 != bval2) {
2733  samecmaps = FALSE;
2734  break;
2735  }
2736  }
2737  }
2738 
2739  h = pixGetHeight(pix1);
2740  w = pixGetWidth(pix1);
2741  if (samecmaps == TRUE) { /* colormaps are identical; compare by words */
2742  linebits = d * w;
2743  wpl1 = pixGetWpl(pix1);
2744  wpl2 = pixGetWpl(pix2);
2745  data1 = pixGetData(pix1);
2746  data2 = pixGetData(pix2);
2747  fullwords = linebits / 32;
2748  endbits = linebits & 31;
2749  endmask = 0xffffffff << (32 - endbits);
2750  for (i = 0; i < h; i++) {
2751  line1 = data1 + wpl1 * i;
2752  line2 = data2 + wpl2 * i;
2753  for (j = 0; j < fullwords; j++) {
2754  if (*line1 ^ *line2)
2755  return 0;
2756  line1++;
2757  line2++;
2758  }
2759  if (endbits) {
2760  if ((*line1 ^ *line2) & endmask)
2761  return 0;
2762  }
2763  }
2764  *psame = 1;
2765  return 0;
2766  }
2767 
2768  /* Colormaps aren't identical; compare pixel by pixel */
2769  for (i = 0; i < h; i++) {
2770  for (j = 0; j < w; j++) {
2771  pixGetPixel(pix1, j, i, &val1);
2772  pixGetPixel(pix2, j, i, &val2);
2773  pixcmapGetColor(cmap1, val1, &rval1, &gval1, &bval1);
2774  pixcmapGetColor(cmap2, val2, &rval2, &gval2, &bval2);
2775  if (rval1 != rval2 || gval1 != gval2 || bval1 != bval2)
2776  return 0;
2777  }
2778  }
2779 
2780  *psame = 1;
2781  return 0;
2782 }
2783 
2784 
2785 /*-------------------------------------------------------------*
2786  * Extract rectangular region *
2787  *-------------------------------------------------------------*/
2788 /*!
2789  * pixClipRectangle()
2790  *
2791  * Input: pixs
2792  * box (requested clipping region; const)
2793  * &boxc (<optional return> actual box of clipped region)
2794  * Return: clipped pix, or null on error or if rectangle
2795  * doesn't intersect pixs
2796  *
2797  * Notes:
2798  *
2799  * This should be simple. Yet it is not, and there are choices to
2800  * be made.
2801  *
2802  * The box is defined relative to the pix coordinates. However,
2803  * if the box exceeds the pix boundaries, we have two choices:
2804  *
2805  * (1) clip the box to the pix
2806  * (2) make a new pix equal to the full box dimensions,
2807  * but let rasterop do the clipping and positioning
2808  * of the src with respect to the dest
2809  *
2810  * Choice (2) immediately brings up the problem of what pixel values
2811  * to use that were not taken from the src! For example, on a grayscale
2812  * image, do you want the pixels not taken from the src to be black
2813  * or white or something else? To implement choice 2, one needs to
2814  * specify the color of these extra pixels.
2815  *
2816  * So we adopt (1), and clip the box first, if necessary,
2817  * before making the dest pix and doing the rasterop. But there
2818  * are still problems to consider.
2819  *
2820  * First, imagine that the box has y < 0, so that some of it is
2821  * above the src. If you clip a piece of the image using this box,
2822  * you get a Pix with a height less than the box height. The trouble
2823  * comes when you then paste the Pix back in using the same box:
2824  * it will be shifted up, and clipped to the top of the dest Pix,
2825  * thus losing pixels at the top! Remember that we are first clipping
2826  * the box to the src, and then extracting the pix using the clipped
2827  * box. So to prevent the shift on replacement, it is necessary to
2828  * use the clipped box!
2829  *
2830  * Accordingly, this function has a third (optional) argument, which is
2831  * the input box clipped to the src pix.
2832  *
2833  * Now, imagine that the box extends past the bottom of the pix:
2834  * box->y > pixGetHeight(pixs) - 1
2835  * This will not cause any trouble on replacement using the
2836  * original box, because the piece clipped out will go back
2837  * in the same place when replaced.
2838  *
2839  * We're not finished! Here's a different use.
2840  *
2841  * Suppose you want to clip a small pix (pix2) to a
2842  * large one (pix1), and to preserve the alignment for some later operation.
2843  * (For example, see blend.c). The aligment of the two images is
2844  * typically given by the origin of the smaller pix2 at (x, y)
2845  * relative to the origin of the larger pix1. Here, the "box" you
2846  * use to clip pix2 is actually pix1 (properly translated), and
2847  * it is defined by:
2848  * box->x = -x
2849  * box->y = -y
2850  * box->w = pixGetWidth(pix1)
2851  * box->h = pixGetHeight(pix1)
2852  *
2853  * Consider again the two cases:
2854  * (1) pix2 overhangs pix1 at the bottom, where
2855  * y + pixGetHeight(pix2) > pixGetHeight(pix1)
2856  * Then the lower part of pix2 is clipped, and
2857  * it is properly placed with its origin at (x, y)
2858  * (2) pix2 overhangs pix1 at the top, where
2859  * y < 0
2860  * Then the upper part of the pix2 is clipped, and it is
2861  * properly placed with its origin at (x, y = 0)
2862  *
2863  * So the general prescription for this use is:
2864  * clipping: boxCreate(-x, -y, pixGetWidth(pix1), pixGetHeight(pix1))
2865  * placement: origin (x, y) of pix2 is at:
2866  * (L_MAX(0, x), L_MAX(0, y))
2867  */
2868 PIX *
2870  BOX *box,
2871  BOX **pboxc)
2872 {
2873 l_int32 w, h, overw, overh, d;
2874 BOX *boxc;
2875 PIX *pixd;
2876 
2877  PROCNAME("pixClipRectangle");
2878 
2879  if (!pixs)
2880  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
2881  if (!box)
2882  return (PIX *)ERROR_PTR("box not defined", procName, NULL);
2883  if (pboxc)
2884  *pboxc = NULL;
2885 
2886  w = pixGetWidth(pixs);
2887  h = pixGetHeight(pixs);
2888  boxc = boxCopy(box);
2889 
2890  /* Clip boxc if necessary */
2891  if (boxc->x < 0) {
2892  boxc->w += boxc->x; /* decrease the width */
2893  boxc->x = 0;
2894  }
2895  overw = boxc->x + boxc->w - w;
2896  if (overw > 0)
2897  boxc->w -= overw; /* decrease the width */
2898  if (boxc->y < 0) {
2899  boxc->h += boxc->y; /* decrease the height */
2900  boxc->y = 0;
2901  }
2902  overh = boxc->y + boxc->h - h;
2903  if (overh > 0)
2904  boxc->h -= overh; /* decrease the height */
2905 
2906  /* Check: any pixels in the box? */
2907  if (boxc->w == 0 || boxc->h == 0) { /* box outside of pix */
2908  boxDestroy(&boxc);
2909  L_WARNING("box doesn't overlap pix", procName);
2910  return NULL;
2911  }
2912 
2913  /* Now, we are guaranteed that boxc fits within pixs,
2914  * so that all pixels in pixd are written by the rasterop. */
2915  d = pixGetDepth(pixs);
2916  if ((pixd = pixCreate(boxc->w, boxc->h, d)) == NULL)
2917  return (PIX *)ERROR_PTR("pixd not made", procName, NULL);
2918  pixCopyResolution(pixd, pixs);
2919  pixCopyColormap(pixd, pixs);
2920  pixRasterop(pixd, 0, 0, boxc->w, boxc->h, PIX_SRC, pixs, boxc->x, boxc->y);
2921 
2922  if (pboxc)
2923  *pboxc = boxc;
2924  else
2925  boxDestroy(&boxc);
2926 
2927  return pixd;
2928 }
2929 
2930 
2931 /*-------------------------------------------------------------*
2932  * Extract min rectangle with ON pixels *
2933  *-------------------------------------------------------------*/
2934 /*!
2935  * pixClipToForeground()
2936  *
2937  * Input: pixs (1 bpp)
2938  * &pixd (<optional return> clipped pix returned)
2939  * &box (<optional return> bounding box)
2940  * Return: 0 if OK; 1 on error or if there are no fg pixels
2941  *
2942  * Notes:
2943  * (1) At least one of {&pixd, &box} must be specified.
2944  * (2) If there are no fg pixels, the returned ptrs are null.
2945  */
2946 l_int32
2948  PIX **ppixd,
2949  BOX **pbox)
2950 {
2951 l_int32 w, h, d, wpl, nfullwords, extra, i, j;
2952 l_int32 minx, miny, maxx, maxy;
2954 l_uint32 *data, *line;
2955 BOX *box;
2956 
2957  PROCNAME("pixClipToForeground");
2958 
2959  if (!pixs)
2960  return ERROR_INT("pixs not defined", procName, 1);
2961  if ((d = pixGetDepth(pixs)) != 1)
2962  return ERROR_INT("pixs not binary", procName, 1);
2963  if (!ppixd && !pbox)
2964  return ERROR_INT("neither &pixd nor &pbox defined", procName, 1);
2965 
2966  w = pixGetWidth(pixs);
2967  nfullwords = w / 32;
2968  extra = w & 31;
2969  mask = ~~rmask32[32 - extra];
2970  h = pixGetHeight(pixs);
2971  wpl = pixGetWpl(pixs);
2972  data = pixGetData(pixs);
2973 
2974  result = 0;
2975  for (i = 0, miny = 0; i < h; i++, miny++) {
2976  line = data + i * wpl;
2977  for (j = 0; j < nfullwords; j++)
2978  result |= line[j];
2979  if (extra)
2980  result |= (line[j] & mask);
2981  if (result)
2982  break;
2983  }
2984  if (miny == h) { /* no ON pixels */
2985  if (ppixd)
2986  *ppixd = NULL;
2987  if (pbox)
2988  *pbox = NULL;
2989  return 1;
2990  }
2991 
2992  result = 0;
2993  for (i = h - 1, maxy = h - 1; i >= 0; i--, maxy--) {
2994  line = data + i * wpl;
2995  for (j = 0; j < nfullwords; j++)
2996  result |= line[j];
2997  if (extra)
2998  result |= (line[j] & mask);
2999  if (result)
3000  break;
3001  }
3002 
3003  minx = 0;
3004  for (j = 0, minx = 0; j < w; j++, minx++) {
3005  for (i = 0; i < h; i++) {
3006  line = data + i * wpl;
3007  if (GET_DATA_BIT(line, j))
3008  goto minx_found;
3009  }
3010  }
3011 
3012 minx_found:
3013  for (j = w - 1, maxx = w - 1; j >= 0; j--, maxx--) {
3014  for (i = 0; i < h; i++) {
3015  line = data + i * wpl;
3016  if (GET_DATA_BIT(line, j))
3017  goto maxx_found;
3018  }
3019  }
3020 
3021 maxx_found:
3022  box = boxCreate(minx, miny, maxx - minx + 1, maxy - miny + 1);
3023 
3024  if (ppixd)
3025  *ppixd = pixClipRectangle(pixs, box, NULL);
3026  if (pbox)
3027  *pbox = box;
3028  else
3029  boxDestroy(&box);
3030 
3031  return 0;
3032 }
3033 
#define depth(a)
Definition: aptex-macros.h:199
#define count(a)
Definition: aptex-macros.h:781
#define box(a)
Definition: aptex-macros.h:675
#define GET_DATA_QBIT(pdata, n)
Definition: arrayaccess.h:77
#define GET_DATA_TWO_BYTES(pdata, n)
Definition: arrayaccess.h:118
#define CLEAR_DATA_QBIT(pdata, n)
Definition: arrayaccess.h:87
#define CLEAR_DATA_DIBIT(pdata, n)
Definition: arrayaccess.h:70
#define SET_DATA_BIT(pdata, n)
Definition: arrayaccess.h:50
#define SET_DATA_DIBIT(pdata, n, val)
Definition: arrayaccess.h:63
#define SET_DATA_TWO_BYTES(pdata, n, val)
Definition: arrayaccess.h:126
#define GET_DATA_BYTE(pdata, n)
Definition: arrayaccess.h:98
#define GET_DATA_DIBIT(pdata, n)
Definition: arrayaccess.h:60
#define SET_DATA_BYTE(pdata, n, val)
Definition: arrayaccess.h:106
#define CLEAR_DATA_BIT(pdata, n)
Definition: arrayaccess.h:53
#define GET_DATA_BIT(pdata, n)
Definition: arrayaccess.h:47
#define SET_DATA_QBIT(pdata, n, val)
Definition: arrayaccess.h:80
static gray maxval
Definition: asciitopgm.c:38
void boxDestroy(BOX **pbox)
Definition: box.c:192
BOX * boxCopy(BOX *box)
Definition: box.c:145
BOX * boxCreate(l_int32 x, l_int32 y, l_int32 w, l_int32 h)
Definition: box.c:102
#define n
Definition: t4ht.c:1290
l_int32 pixcmapGetCount(PIXCMAP *cmap)
Definition: colormap.c:279
l_int32 pixcmapHasColor(PIXCMAP *cmap, l_int32 *pcolor)
Definition: colormap.c:451
l_int32 pixcmapGetColor(PIXCMAP *cmap, l_int32 index, l_int32 *prval, l_int32 *pgval, l_int32 *pbval)
Definition: colormap.c:340
@ FALSE
Definition: dd.h:101
@ TRUE
Definition: dd.h:102
int w
Definition: dviconv.c:26
int h
Definition: dviconv.c:9
struct rect data
Definition: dvipdfm.c:64
#define PROCNAME(name)
Definition: environ.h:131
#define ERROR_PTR(a, b, c)
Definition: environ.h:132
unsigned int l_uint32
Definition: environ.h:33
#define L_INFO(a, b)
Definition: environ.h:138
unsigned char l_uint8
Definition: environ.h:29
#define L_WARNING(a, b)
Definition: environ.h:136
#define ERROR_INT(a, b, c)
Definition: environ.h:133
int l_int32
Definition: environ.h:32
#define L_ABS(x)
Definition: environ.h:50
#define L_WARNING_INT(a, b, c)
Definition: environ.h:137
float l_float32
Definition: environ.h:34
#define ws
#define d(n)
Definition: gpos-common.c:151
const unsigned char FREE
Definition: image.cpp:34
pix
Definition: in_pcx.cpp:383
#define byte
Definition: in_pcx.cpp:28
#define NULL
Definition: ftobjs.h:61
small capitals from c petite p scientific i
Definition: afcover.h:80
kerning y
Definition: ttdriver.c:212
static const char * tab[]
Definition: xdirtest.c:23
static int thresh
Definition: qsort.c:23
int lines
Definition: var.h:5
#define fprintf
Definition: mendex.h:64
#define CALLOC(t, n)
Definition: hash.c:21
unsigned char bitval[8]
Definition: bbox.c:60
PIX * pixUnpackBinary(PIX *pixs, l_int32 depth, l_int32 invert)
Definition: pixconv.c:965
l_uint32 * pixGetData(PIX *pix)
Definition: pix1.c:793
void pixDestroy(PIX **ppix)
Definition: pix1.c:225
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)
Definition: rop.c:172
NUMA * numaCreate(l_int32 n)
Definition: numarray.c:169
l_int32 pixGetWpl(PIX *pix)
Definition: pix1.c:477
PIX * pixRemoveColormap(PIX *pixs, l_int32 type)
Definition: pixconv.c:198
l_int32 pixSetMaskedCmap(PIX *pixs, PIX *pixm, l_int32 x, l_int32 y, l_int32 rval, l_int32 gval, l_int32 bval)
Definition: paintcmap.c:474
l_int32 pixCopyResolution(PIX *pixd, PIX *pixs)
Definition: pix1.c:567
void numaDestroy(NUMA **pna)
Definition: numarray.c:202
l_int32 pixGetDepth(PIX *pix)
Definition: pix1.c:449
PIX * pixCopy(PIX *pixd, PIX *pixs)
Definition: pix1.c:276
PIX * pixCreateTemplate(PIX *pixs)
Definition: pix1.c:148
l_int32 pixCopyColormap(PIX *pixd, PIX *pixs)
Definition: pix1.c:328
l_int32 pixaGetCount(PIXA *pixa)
Definition: pixa.c:471
l_int32 numaAddNumber(NUMA *na, l_float32 val)
Definition: numarray.c:311
PIXCMAP * pixGetColormap(PIX *pix)
Definition: pix1.c:766
l_int32 pixSizesEqual(PIX *pix1, PIX *pix2)
Definition: pix1.c:358
PIX * pixCreate(l_int32 width, l_int32 height, l_int32 depth)
Definition: pix1.c:90
PIX * pixClone(PIX *pixs)
Definition: pix1.c:197
l_int32 pixGetHeight(PIX *pix)
Definition: pix1.c:419
PIX * pixaGetPix(PIXA *pixa, l_int32 index, l_int32 accesstype)
Definition: pixa.c:511
l_int32 pixGetWidth(PIX *pix)
Definition: pix1.c:389
#define L_MIN
Definition: manifests.h:69
float x
Definition: cordic.py:15
unsigned short word
Definition: picttoppm.c:64
l_int32 pixEqualWithCmap(PIX *pix1, PIX *pix2, l_int32 *psame)
Definition: pix2.c:2683
PIX * pixRemoveBorderGeneral(PIX *pixs, l_int32 leftpix, l_int32 rightpix, l_int32 toppix, l_int32 bottompix)
Definition: pix2.c:2458
l_int32 pixEndianByteSwap(PIX *pix)
Definition: pix2.c:1969
l_int32 pixEqual(PIX *pix1, PIX *pix2, l_int32 *psame)
Definition: pix2.c:2525
l_int32 pixPaintThroughMask(PIX *pixd, PIX *pixm, l_int32 x, l_int32 y, l_uint32 val)
Definition: pix2.c:1106
static const l_uint32 rmask32[]
Definition: pix2.c:99
PIX * pixEndianByteSwapNew(PIX *pixs)
Definition: pix2.c:1910
NUMA * pixaCountPixels(PIXA *pixa)
Definition: pix2.c:1553
l_int32 pixThresholdPixels(PIX *pix, l_int32 thresh, l_int32 *pabove, l_int32 *tab8)
Definition: pix2.c:1718
l_int32 pixSetOrClearBorder(PIX *pixs, l_int32 leftpix, l_int32 rightpix, l_int32 toppix, l_int32 bottompix, l_int32 op)
Definition: pix2.c:689
PIX * pixCreateRGBImage(PIX *pixr, PIX *pixg, PIX *pixb)
Definition: pix2.c:2073
l_int32 pixSetMasked(PIX *pixd, PIX *pixm, l_uint32 val)
Definition: pix2.c:839
l_int32 pixEndianTwoByteSwap(PIX *pix)
Definition: pix2.c:2018
PIX * pixInvert(PIX *pixd, PIX *pixs)
Definition: pix2.c:1188
PIX * pixAddBorder(PIX *pixs, l_int32 npix, l_uint32 val)
Definition: pix2.c:2320
l_int32 pixSetPixel(PIX *pix, l_int32 x, l_int32 y, l_uint32 val)
Definition: pix2.c:197
l_int32 pixGetPixel(PIX *pix, l_int32 x, l_int32 y, l_uint32 *pval)
Definition: pix2.c:128
l_int32 pixSetPadBitsBand(PIX *pix, l_int32 by, l_int32 bh, l_int32 val)
Definition: pix2.c:618
PIX * pixClipRectangle(PIX *pixs, BOX *box, BOX **pboxc)
Definition: pix2.c:2869
l_int32 pixSetBorderVal(PIX *pixs, l_int32 leftpix, l_int32 rightpix, l_int32 toppix, l_int32 bottompix, l_uint32 val)
Definition: pix2.c:738
l_int32 pixClearAll(PIX *pix)
Definition: pix2.c:449
void setPixelLow(l_uint32 *line, l_int32 x, l_int32 depth, l_uint32 val)
Definition: pix2.c:400
PIX * pixOr(PIX *pixd, PIX *pixs1, PIX *pixs2)
Definition: pix2.c:1224
PIX * pixAnd(PIX *pixd, PIX *pixs1, PIX *pixs2)
Definition: pix2.c:1271
l_int32 pixSetMaskedGeneral(PIX *pixd, PIX *pixm, l_uint32 val, l_int32 x, l_int32 y)
Definition: pix2.c:948
PIX * pixRemoveBorder(PIX *pixs, l_int32 npix)
Definition: pix2.c:2361
l_int32 pixGetRGBLine(PIX *pixs, l_int32 row, l_uint8 *bufr, l_uint8 *bufg, l_uint8 *bufb)
Definition: pix2.c:2262
l_int32 pixSetRGBComponent(PIX *pixd, PIX *pixs, l_int32 color)
Definition: pix2.c:2176
l_int32 pixSetAllArbitrary(PIX *pix, l_uint32 val)
Definition: pix2.c:492
l_int32 pixCountPixels(PIX *pix, l_int32 *pcount, l_int32 *tab8)
Definition: pix2.c:1493
l_int32 composeRGBPixel(l_int32 rval, l_int32 gval, l_int32 bval, l_uint32 *ppixel)
Definition: pix2.c:2230
l_int32 * makePixelSumTab8(void)
Definition: pix2.c:1776
l_int32 pixFlipPixel(PIX *pix, l_int32 x, l_int32 y)
Definition: pix2.c:322
NUMA * pixGrayHistogram(PIX *pixs)
Definition: pix2.c:1813
l_int32 pixCombineMasked(PIX *pixd, PIX *pixs, PIX *pixm)
Definition: pix2.c:1019
PIX * pixXor(PIX *pixd, PIX *pixs1, PIX *pixs2)
Definition: pix2.c:1318
PIX * pixAddBorderGeneral(PIX *pixs, l_int32 leftpix, l_int32 rightpix, l_int32 toppix, l_int32 bottompix, l_uint32 val)
Definition: pix2.c:2416
l_int32 pixSetPadBits(PIX *pix, l_int32 val)
Definition: pix2.c:558
l_int32 pixClearPixel(PIX *pix, l_int32 x, l_int32 y)
Definition: pix2.c:262
NUMA * pixCountPixelsByRow(PIX *pix, l_int32 *tab8)
Definition: pix2.c:1662
l_int32 pixZero(PIX *pix, l_int32 *pempty)
Definition: pix2.c:1441
l_int32 pixSetAll(PIX *pix)
Definition: pix2.c:471
PIX * pixGetRGBComponent(PIX *pixs, l_int32 color)
Definition: pix2.c:2122
l_int32 pixClipToForeground(PIX *pixs, PIX **ppixd, BOX **pbox)
Definition: pix2.c:2947
PIX * pixSubtract(PIX *pixd, PIX *pixs1, PIX *pixs2)
Definition: pix2.c:1373
l_int32 pixCountPixelsInRow(PIX *pix, l_int32 row, l_int32 *pcount, l_int32 *tab8)
Definition: pix2.c:1601
#define PIX_DST
Definition: pix.h:176
@ REMOVE_CMAP_TO_FULL_COLOR
Definition: pix.h:112
@ REMOVE_CMAP_TO_GRAYSCALE
Definition: pix.h:111
#define PIX_SRC
Definition: pix.h:175
@ L_CLONE
Definition: pix.h:363
#define PIX_CLR
Definition: pix.h:178
#define PIX_NOT(op)
Definition: pix.h:177
#define PIX_SET
Definition: pix.h:179
@ COLOR_BLUE
Definition: pix.h:102
@ COLOR_RED
Definition: pix.h:100
@ COLOR_GREEN
Definition: pix.h:101
static int size
Definition: ppmlabel.c:24
char line[1024]
Definition: process_score.c:29
static int row
Definition: ps2pk.c:587
#define mask(n)
Definition: lbitlib.c:93
#define gval(n)
Definition: ltable.h:14
Definition: pix.h:292
l_int32 y
Definition: pix.h:294
l_int32 x
Definition: pix.h:293
l_int32 w
Definition: pix.h:295
l_int32 h
Definition: pix.h:296
Definition: array.h:38
l_float32 * array
Definition: array.h:42
l_int32 n
Definition: array.h:40
Definition: pix.h:51
Definition: pix.h:268
Definition: jquant2.c:258
Definition: tt_cmap.c:106
Definition: pdfdev.c:706
Definition: bdf.c:133
Definition: sh.h:1226
Definition: strexpr.c:21
int j
Definition: t4ht.c:1589
val
Definition: tex4ht.c:3227
char line2[BUFSIZ]
Definition: texfix.c:35