Leptonica  1.83.1
Image processing and image analysis suite
graymorph.c
Go to the documentation of this file.
1 /*====================================================================*
2  - Copyright (C) 2001 Leptonica. All rights reserved.
3  -
4  - Redistribution and use in source and binary forms, with or without
5  - modification, are permitted provided that the following conditions
6  - are met:
7  - 1. Redistributions of source code must retain the above copyright
8  - notice, this list of conditions and the following disclaimer.
9  - 2. Redistributions in binary form must reproduce the above
10  - copyright notice, this list of conditions and the following
11  - disclaimer in the documentation and/or other materials
12  - provided with the distribution.
13  -
14  - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15  - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16  - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17  - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY
18  - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  - OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
23  - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24  - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  *====================================================================*/
26 
27 
122 #ifdef HAVE_CONFIG_H
123 #include <config_auto.h>
124 #endif /* HAVE_CONFIG_H */
125 
126 #include "allheaders.h"
127 
128  /* Special static operations for 3x1, 1x3 and 3x3 structuring elements */
129 static PIX *pixErodeGray3h(PIX *pixs);
130 static PIX *pixErodeGray3v(PIX *pixs);
131 static PIX *pixDilateGray3h(PIX *pixs);
132 static PIX *pixDilateGray3v(PIX *pixs);
133 
134  /* Low-level gray morphological operations */
135 static void dilateGrayLow(l_uint32 *datad, l_int32 w, l_int32 h,
136  l_int32 wpld, l_uint32 *datas, l_int32 wpls,
137  l_int32 size, l_int32 direction, l_uint8 *buffer,
138  l_uint8 *maxarray);
139 static void erodeGrayLow(l_uint32 *datad, l_int32 w, l_int32 h,
140  l_int32 wpld, l_uint32 *datas, l_int32 wpls,
141  l_int32 size, l_int32 direction, l_uint8 *buffer,
142  l_uint8 *minarray);
143 
144 /*-----------------------------------------------------------------*
145  * Top-level grayscale morphological operations *
146  *-----------------------------------------------------------------*/
161 PIX *
163  l_int32 hsize,
164  l_int32 vsize)
165 {
166 l_uint8 *buffer, *minarray;
167 l_int32 w, h, wplb, wplt;
168 l_int32 leftpix, rightpix, toppix, bottompix, maxsize;
169 l_uint32 *datab, *datat;
170 PIX *pixb, *pixt, *pixd;
171 
172  if (!pixs)
173  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
174  if (pixGetDepth(pixs) != 8)
175  return (PIX *)ERROR_PTR("pixs not 8 bpp", __func__, NULL);
176  if (hsize < 1 || vsize < 1)
177  return (PIX *)ERROR_PTR("hsize or vsize < 1", __func__, NULL);
178  if ((hsize & 1) == 0 ) {
179  L_WARNING("horiz sel size must be odd; increasing by 1\n", __func__);
180  hsize++;
181  }
182  if ((vsize & 1) == 0 ) {
183  L_WARNING("vert sel size must be odd; increasing by 1\n", __func__);
184  vsize++;
185  }
186 
187  pixb = pixt = pixd = NULL;
188  buffer = minarray = NULL;
189 
190  if (hsize == 1 && vsize == 1)
191  return pixCopy(NULL, pixs);
192 
193  if (vsize == 1) { /* horizontal sel */
194  leftpix = (hsize + 1) / 2;
195  rightpix = (3 * hsize + 1) / 2;
196  toppix = 0;
197  bottompix = 0;
198  } else if (hsize == 1) { /* vertical sel */
199  leftpix = 0;
200  rightpix = 0;
201  toppix = (vsize + 1) / 2;
202  bottompix = (3 * vsize + 1) / 2;
203  } else {
204  leftpix = (hsize + 1) / 2;
205  rightpix = (3 * hsize + 1) / 2;
206  toppix = (vsize + 1) / 2;
207  bottompix = (3 * vsize + 1) / 2;
208  }
209 
210  pixb = pixAddBorderGeneral(pixs, leftpix, rightpix, toppix, bottompix, 255);
211  pixt = pixCreateTemplate(pixb);
212  if (!pixb || !pixt) {
213  L_ERROR("pixb and pixt not made\n", __func__);
214  goto cleanup;
215  }
216 
217  pixGetDimensions(pixt, &w, &h, NULL);
218  datab = pixGetData(pixb);
219  datat = pixGetData(pixt);
220  wplb = pixGetWpl(pixb);
221  wplt = pixGetWpl(pixt);
222 
223  buffer = (l_uint8 *)LEPT_CALLOC(L_MAX(w, h), sizeof(l_uint8));
224  maxsize = L_MAX(hsize, vsize);
225  minarray = (l_uint8 *)LEPT_CALLOC(2 * maxsize, sizeof(l_uint8));
226  if (!buffer || !minarray) {
227  L_ERROR("buffer and minarray not made\n", __func__);
228  goto cleanup;
229  }
230 
231  if (vsize == 1) {
232  erodeGrayLow(datat, w, h, wplt, datab, wplb, hsize, L_HORIZ,
233  buffer, minarray);
234  } else if (hsize == 1) {
235  erodeGrayLow(datat, w, h, wplt, datab, wplb, vsize, L_VERT,
236  buffer, minarray);
237  } else {
238  erodeGrayLow(datat, w, h, wplt, datab, wplb, hsize, L_HORIZ,
239  buffer, minarray);
240  pixSetOrClearBorder(pixt, leftpix, rightpix, toppix, bottompix,
241  PIX_SET);
242  erodeGrayLow(datab, w, h, wplb, datat, wplt, vsize, L_VERT,
243  buffer, minarray);
244  pixDestroy(&pixt);
245  pixt = pixClone(pixb);
246  }
247 
248  pixd = pixRemoveBorderGeneral(pixt, leftpix, rightpix, toppix, bottompix);
249  if (!pixd)
250  L_ERROR("pixd not made\n", __func__);
251 
252 cleanup:
253  LEPT_FREE(buffer);
254  LEPT_FREE(minarray);
255  pixDestroy(&pixb);
256  pixDestroy(&pixt);
257  return pixd;
258 }
259 
260 
275 PIX *
277  l_int32 hsize,
278  l_int32 vsize)
279 {
280 l_uint8 *buffer, *maxarray;
281 l_int32 w, h, wplb, wplt;
282 l_int32 leftpix, rightpix, toppix, bottompix, maxsize;
283 l_uint32 *datab, *datat;
284 PIX *pixb, *pixt, *pixd;
285 
286  if (!pixs)
287  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
288  if (pixGetDepth(pixs) != 8)
289  return (PIX *)ERROR_PTR("pixs not 8 bpp", __func__, NULL);
290  if (hsize < 1 || vsize < 1)
291  return (PIX *)ERROR_PTR("hsize or vsize < 1", __func__, NULL);
292  if ((hsize & 1) == 0 ) {
293  L_WARNING("horiz sel size must be odd; increasing by 1\n", __func__);
294  hsize++;
295  }
296  if ((vsize & 1) == 0 ) {
297  L_WARNING("vert sel size must be odd; increasing by 1\n", __func__);
298  vsize++;
299  }
300 
301  pixb = pixt = pixd = NULL;
302  buffer = maxarray = NULL;
303 
304  if (hsize == 1 && vsize == 1)
305  return pixCopy(NULL, pixs);
306 
307  if (vsize == 1) { /* horizontal sel */
308  leftpix = (hsize + 1) / 2;
309  rightpix = (3 * hsize + 1) / 2;
310  toppix = 0;
311  bottompix = 0;
312  } else if (hsize == 1) { /* vertical sel */
313  leftpix = 0;
314  rightpix = 0;
315  toppix = (vsize + 1) / 2;
316  bottompix = (3 * vsize + 1) / 2;
317  } else {
318  leftpix = (hsize + 1) / 2;
319  rightpix = (3 * hsize + 1) / 2;
320  toppix = (vsize + 1) / 2;
321  bottompix = (3 * vsize + 1) / 2;
322  }
323 
324  pixb = pixAddBorderGeneral(pixs, leftpix, rightpix, toppix, bottompix, 0);
325  pixt = pixCreateTemplate(pixb);
326  if (!pixb || !pixt) {
327  L_ERROR("pixb and pixt not made\n", __func__);
328  goto cleanup;
329  }
330 
331  pixGetDimensions(pixt, &w, &h, NULL);
332  datab = pixGetData(pixb);
333  datat = pixGetData(pixt);
334  wplb = pixGetWpl(pixb);
335  wplt = pixGetWpl(pixt);
336 
337  buffer = (l_uint8 *)LEPT_CALLOC(L_MAX(w, h), sizeof(l_uint8));
338  maxsize = L_MAX(hsize, vsize);
339  maxarray = (l_uint8 *)LEPT_CALLOC(2 * maxsize, sizeof(l_uint8));
340  if (!buffer || !maxarray) {
341  L_ERROR("buffer and maxarray not made\n", __func__);
342  goto cleanup;
343  }
344 
345  if (vsize == 1) {
346  dilateGrayLow(datat, w, h, wplt, datab, wplb, hsize, L_HORIZ,
347  buffer, maxarray);
348  } else if (hsize == 1) {
349  dilateGrayLow(datat, w, h, wplt, datab, wplb, vsize, L_VERT,
350  buffer, maxarray);
351  } else {
352  dilateGrayLow(datat, w, h, wplt, datab, wplb, hsize, L_HORIZ,
353  buffer, maxarray);
354  pixSetOrClearBorder(pixt, leftpix, rightpix, toppix, bottompix,
355  PIX_CLR);
356  dilateGrayLow(datab, w, h, wplb, datat, wplt, vsize, L_VERT,
357  buffer, maxarray);
358  pixDestroy(&pixt);
359  pixt = pixClone(pixb);
360  }
361 
362  pixd = pixRemoveBorderGeneral(pixt, leftpix, rightpix, toppix, bottompix);
363  if (!pixd)
364  L_ERROR("pixd not made\n", __func__);
365 
366 cleanup:
367  LEPT_FREE(buffer);
368  LEPT_FREE(maxarray);
369  pixDestroy(&pixb);
370  pixDestroy(&pixt);
371  return pixd;
372 }
373 
374 
389 PIX *
391  l_int32 hsize,
392  l_int32 vsize)
393 {
394 l_uint8 *buffer;
395 l_uint8 *array; /* used to find either min or max in interval */
396 l_int32 w, h, wplb, wplt;
397 l_int32 leftpix, rightpix, toppix, bottompix, maxsize;
398 l_uint32 *datab, *datat;
399 PIX *pixb, *pixt, *pixd;
400 
401  if (!pixs)
402  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
403  if (pixGetDepth(pixs) != 8)
404  return (PIX *)ERROR_PTR("pixs not 8 bpp", __func__, NULL);
405  if (hsize < 1 || vsize < 1)
406  return (PIX *)ERROR_PTR("hsize or vsize < 1", __func__, NULL);
407  if ((hsize & 1) == 0 ) {
408  L_WARNING("horiz sel size must be odd; increasing by 1\n", __func__);
409  hsize++;
410  }
411  if ((vsize & 1) == 0 ) {
412  L_WARNING("vert sel size must be odd; increasing by 1\n", __func__);
413  vsize++;
414  }
415 
416  pixb = pixt = pixd = NULL;
417  buffer = array = NULL;
418 
419  if (hsize == 1 && vsize == 1)
420  return pixCopy(NULL, pixs);
421 
422  if (vsize == 1) { /* horizontal sel */
423  leftpix = (hsize + 1) / 2;
424  rightpix = (3 * hsize + 1) / 2;
425  toppix = 0;
426  bottompix = 0;
427  } else if (hsize == 1) { /* vertical sel */
428  leftpix = 0;
429  rightpix = 0;
430  toppix = (vsize + 1) / 2;
431  bottompix = (3 * vsize + 1) / 2;
432  } else {
433  leftpix = (hsize + 1) / 2;
434  rightpix = (3 * hsize + 1) / 2;
435  toppix = (vsize + 1) / 2;
436  bottompix = (3 * vsize + 1) / 2;
437  }
438 
439  pixb = pixAddBorderGeneral(pixs, leftpix, rightpix, toppix, bottompix, 255);
440  pixt = pixCreateTemplate(pixb);
441  if (!pixb || !pixt) {
442  L_ERROR("pixb and pixt not made\n", __func__);
443  goto cleanup;
444  }
445 
446  pixGetDimensions(pixt, &w, &h, NULL);
447  datab = pixGetData(pixb);
448  datat = pixGetData(pixt);
449  wplb = pixGetWpl(pixb);
450  wplt = pixGetWpl(pixt);
451 
452  buffer = (l_uint8 *)LEPT_CALLOC(L_MAX(w, h), sizeof(l_uint8));
453  maxsize = L_MAX(hsize, vsize);
454  array = (l_uint8 *)LEPT_CALLOC(2 * maxsize, sizeof(l_uint8));
455  if (!buffer || !array) {
456  L_ERROR("buffer and array not made\n", __func__);
457  goto cleanup;
458  }
459 
460  if (vsize == 1) {
461  erodeGrayLow(datat, w, h, wplt, datab, wplb, hsize, L_HORIZ,
462  buffer, array);
463  pixSetOrClearBorder(pixt, leftpix, rightpix, toppix, bottompix,
464  PIX_CLR);
465  dilateGrayLow(datab, w, h, wplb, datat, wplt, hsize, L_HORIZ,
466  buffer, array);
467  }
468  else if (hsize == 1) {
469  erodeGrayLow(datat, w, h, wplt, datab, wplb, vsize, L_VERT,
470  buffer, array);
471  pixSetOrClearBorder(pixt, leftpix, rightpix, toppix, bottompix,
472  PIX_CLR);
473  dilateGrayLow(datab, w, h, wplb, datat, wplt, vsize, L_VERT,
474  buffer, array);
475  } else {
476  erodeGrayLow(datat, w, h, wplt, datab, wplb, hsize, L_HORIZ,
477  buffer, array);
478  pixSetOrClearBorder(pixt, leftpix, rightpix, toppix, bottompix,
479  PIX_SET);
480  erodeGrayLow(datab, w, h, wplb, datat, wplt, vsize, L_VERT,
481  buffer, array);
482  pixSetOrClearBorder(pixb, leftpix, rightpix, toppix, bottompix,
483  PIX_CLR);
484  dilateGrayLow(datat, w, h, wplt, datab, wplb, hsize, L_HORIZ,
485  buffer, array);
486  pixSetOrClearBorder(pixt, leftpix, rightpix, toppix, bottompix,
487  PIX_CLR);
488  dilateGrayLow(datab, w, h, wplb, datat, wplt, vsize, L_VERT,
489  buffer, array);
490  }
491 
492  pixd = pixRemoveBorderGeneral(pixb, leftpix, rightpix, toppix, bottompix);
493  if (!pixd)
494  L_ERROR("pixd not made\n", __func__);
495 
496 cleanup:
497  LEPT_FREE(buffer);
498  LEPT_FREE(array);
499  pixDestroy(&pixb);
500  pixDestroy(&pixt);
501  return pixd;
502 }
503 
504 
519 PIX *
521  l_int32 hsize,
522  l_int32 vsize)
523 {
524 l_uint8 *buffer;
525 l_uint8 *array; /* used to find either min or max in interval */
526 l_int32 w, h, wplb, wplt;
527 l_int32 leftpix, rightpix, toppix, bottompix, maxsize;
528 l_uint32 *datab, *datat;
529 PIX *pixb, *pixt, *pixd;
530 
531  if (!pixs)
532  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
533  if (pixGetDepth(pixs) != 8)
534  return (PIX *)ERROR_PTR("pixs not 8 bpp", __func__, NULL);
535  if (hsize < 1 || vsize < 1)
536  return (PIX *)ERROR_PTR("hsize or vsize < 1", __func__, NULL);
537  if ((hsize & 1) == 0 ) {
538  L_WARNING("horiz sel size must be odd; increasing by 1\n", __func__);
539  hsize++;
540  }
541  if ((vsize & 1) == 0 ) {
542  L_WARNING("vert sel size must be odd; increasing by 1\n", __func__);
543  vsize++;
544  }
545 
546  pixb = pixt = pixd = NULL;
547  buffer = array = NULL;
548 
549  if (hsize == 1 && vsize == 1)
550  return pixCopy(NULL, pixs);
551 
552  if (vsize == 1) { /* horizontal sel */
553  leftpix = (hsize + 1) / 2;
554  rightpix = (3 * hsize + 1) / 2;
555  toppix = 0;
556  bottompix = 0;
557  } else if (hsize == 1) { /* vertical sel */
558  leftpix = 0;
559  rightpix = 0;
560  toppix = (vsize + 1) / 2;
561  bottompix = (3 * vsize + 1) / 2;
562  } else {
563  leftpix = (hsize + 1) / 2;
564  rightpix = (3 * hsize + 1) / 2;
565  toppix = (vsize + 1) / 2;
566  bottompix = (3 * vsize + 1) / 2;
567  }
568 
569  pixb = pixAddBorderGeneral(pixs, leftpix, rightpix, toppix, bottompix, 0);
570  pixt = pixCreateTemplate(pixb);
571  if (!pixb || !pixt) {
572  L_ERROR("pixb and pixt not made\n", __func__);
573  goto cleanup;
574  }
575 
576  pixGetDimensions(pixt, &w, &h, NULL);
577  datab = pixGetData(pixb);
578  datat = pixGetData(pixt);
579  wplb = pixGetWpl(pixb);
580  wplt = pixGetWpl(pixt);
581 
582  buffer = (l_uint8 *)LEPT_CALLOC(L_MAX(w, h), sizeof(l_uint8));
583  maxsize = L_MAX(hsize, vsize);
584  array = (l_uint8 *)LEPT_CALLOC(2 * maxsize, sizeof(l_uint8));
585  if (!buffer || !array) {
586  L_ERROR("buffer and array not made\n", __func__);
587  goto cleanup;
588  }
589 
590  if (vsize == 1) {
591  dilateGrayLow(datat, w, h, wplt, datab, wplb, hsize, L_HORIZ,
592  buffer, array);
593  pixSetOrClearBorder(pixt, leftpix, rightpix, toppix, bottompix,
594  PIX_SET);
595  erodeGrayLow(datab, w, h, wplb, datat, wplt, hsize, L_HORIZ,
596  buffer, array);
597  } else if (hsize == 1) {
598  dilateGrayLow(datat, w, h, wplt, datab, wplb, vsize, L_VERT,
599  buffer, array);
600  pixSetOrClearBorder(pixt, leftpix, rightpix, toppix, bottompix,
601  PIX_SET);
602  erodeGrayLow(datab, w, h, wplb, datat, wplt, vsize, L_VERT,
603  buffer, array);
604  } else {
605  dilateGrayLow(datat, w, h, wplt, datab, wplb, hsize, L_HORIZ,
606  buffer, array);
607  pixSetOrClearBorder(pixt, leftpix, rightpix, toppix, bottompix,
608  PIX_CLR);
609  dilateGrayLow(datab, w, h, wplb, datat, wplt, vsize, L_VERT,
610  buffer, array);
611  pixSetOrClearBorder(pixb, leftpix, rightpix, toppix, bottompix,
612  PIX_SET);
613  erodeGrayLow(datat, w, h, wplt, datab, wplb, hsize, L_HORIZ,
614  buffer, array);
615  pixSetOrClearBorder(pixt, leftpix, rightpix, toppix, bottompix,
616  PIX_SET);
617  erodeGrayLow(datab, w, h, wplb, datat, wplt, vsize, L_VERT,
618  buffer, array);
619  }
620 
621  pixd = pixRemoveBorderGeneral(pixb, leftpix, rightpix, toppix, bottompix);
622  if (!pixd)
623  L_ERROR("pixd not made\n", __func__);
624 
625 cleanup:
626  LEPT_FREE(buffer);
627  LEPT_FREE(array);
628  pixDestroy(&pixb);
629  pixDestroy(&pixt);
630  return pixd;
631 }
632 
633 
634 /*-----------------------------------------------------------------*
635  * Special operations for 1x3, 3x1 and 3x3 Sels *
636  *-----------------------------------------------------------------*/
656 PIX *
658  l_int32 hsize,
659  l_int32 vsize)
660 {
661 PIX *pixt, *pixb, *pixbd, *pixd;
662 
663  if (!pixs)
664  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
665  if (pixGetDepth(pixs) != 8)
666  return (PIX *)ERROR_PTR("pixs not 8 bpp", __func__, NULL);
667  if (pixGetColormap(pixs))
668  return (PIX *)ERROR_PTR("pix has colormap", __func__, NULL);
669  if ((hsize != 1 && hsize != 3) ||
670  (vsize != 1 && vsize != 3))
671  return (PIX *)ERROR_PTR("invalid size: must be 1 or 3", __func__, NULL);
672 
673  if (hsize == 1 && vsize == 1)
674  return pixCopy(NULL, pixs);
675 
676  pixb = pixAddBorderGeneral(pixs, 4, 8, 2, 8, 255);
677 
678  if (vsize == 1)
679  pixbd = pixErodeGray3h(pixb);
680  else if (hsize == 1)
681  pixbd = pixErodeGray3v(pixb);
682  else { /* vize == hsize == 3 */
683  pixt = pixErodeGray3h(pixb);
684  pixbd = pixErodeGray3v(pixt);
685  pixDestroy(&pixt);
686  }
687 
688  pixd = pixRemoveBorderGeneral(pixbd, 4, 8, 2, 8);
689  pixDestroy(&pixb);
690  pixDestroy(&pixbd);
691  return pixd;
692 }
693 
694 
707 static PIX *
709 {
710 l_uint32 *datas, *datad, *lines, *lined;
711 l_int32 w, h, wpl, i, j;
712 l_int32 val0, val1, val2, val3, val4, val5, val6, val7, val8, val9, minval;
713 PIX *pixd;
714 
715  if (!pixs)
716  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
717  if (pixGetDepth(pixs) != 8)
718  return (PIX *)ERROR_PTR("pixs not 8 bpp", __func__, NULL);
719 
720  pixd = pixCreateTemplate(pixs);
721  pixGetDimensions(pixs, &w, &h, NULL);
722  datas = pixGetData(pixs);
723  datad = pixGetData(pixd);
724  wpl = pixGetWpl(pixs);
725  for (i = 0; i < h; i++) {
726  lines = datas + i * wpl;
727  lined = datad + i * wpl;
728  for (j = 1; j < w - 8; j += 8) {
729  val0 = GET_DATA_BYTE(lines, j - 1);
730  val1 = GET_DATA_BYTE(lines, j);
731  val2 = GET_DATA_BYTE(lines, j + 1);
732  val3 = GET_DATA_BYTE(lines, j + 2);
733  val4 = GET_DATA_BYTE(lines, j + 3);
734  val5 = GET_DATA_BYTE(lines, j + 4);
735  val6 = GET_DATA_BYTE(lines, j + 5);
736  val7 = GET_DATA_BYTE(lines, j + 6);
737  val8 = GET_DATA_BYTE(lines, j + 7);
738  val9 = GET_DATA_BYTE(lines, j + 8);
739  minval = L_MIN(val1, val2);
740  SET_DATA_BYTE(lined, j, L_MIN(val0, minval));
741  SET_DATA_BYTE(lined, j + 1, L_MIN(minval, val3));
742  minval = L_MIN(val3, val4);
743  SET_DATA_BYTE(lined, j + 2, L_MIN(val2, minval));
744  SET_DATA_BYTE(lined, j + 3, L_MIN(minval, val5));
745  minval = L_MIN(val5, val6);
746  SET_DATA_BYTE(lined, j + 4, L_MIN(val4, minval));
747  SET_DATA_BYTE(lined, j + 5, L_MIN(minval, val7));
748  minval = L_MIN(val7, val8);
749  SET_DATA_BYTE(lined, j + 6, L_MIN(val6, minval));
750  SET_DATA_BYTE(lined, j + 7, L_MIN(minval, val9));
751  }
752  }
753  return pixd;
754 }
755 
756 
772 static PIX *
774 {
775 l_uint32 *datas, *datad, *linesi, *linedi;
776 l_int32 w, h, wpl, i, j;
777 l_int32 val0, val1, val2, val3, val4, val5, val6, val7, val8, val9, minval;
778 PIX *pixd;
779 
780  if (!pixs)
781  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
782  if (pixGetDepth(pixs) != 8)
783  return (PIX *)ERROR_PTR("pixs not 8 bpp", __func__, NULL);
784 
785  pixd = pixCreateTemplate(pixs);
786  pixGetDimensions(pixs, &w, &h, NULL);
787  datas = pixGetData(pixs);
788  datad = pixGetData(pixd);
789  wpl = pixGetWpl(pixs);
790  for (j = 0; j < w; j++) {
791  for (i = 1; i < h - 8; i += 8) {
792  linesi = datas + i * wpl;
793  linedi = datad + i * wpl;
794  val0 = GET_DATA_BYTE(linesi - wpl, j);
795  val1 = GET_DATA_BYTE(linesi, j);
796  val2 = GET_DATA_BYTE(linesi + wpl, j);
797  val3 = GET_DATA_BYTE(linesi + 2 * wpl, j);
798  val4 = GET_DATA_BYTE(linesi + 3 * wpl, j);
799  val5 = GET_DATA_BYTE(linesi + 4 * wpl, j);
800  val6 = GET_DATA_BYTE(linesi + 5 * wpl, j);
801  val7 = GET_DATA_BYTE(linesi + 6 * wpl, j);
802  val8 = GET_DATA_BYTE(linesi + 7 * wpl, j);
803  val9 = GET_DATA_BYTE(linesi + 8 * wpl, j);
804  minval = L_MIN(val1, val2);
805  SET_DATA_BYTE(linedi, j, L_MIN(val0, minval));
806  SET_DATA_BYTE(linedi + wpl, j, L_MIN(minval, val3));
807  minval = L_MIN(val3, val4);
808  SET_DATA_BYTE(linedi + 2 * wpl, j, L_MIN(val2, minval));
809  SET_DATA_BYTE(linedi + 3 * wpl, j, L_MIN(minval, val5));
810  minval = L_MIN(val5, val6);
811  SET_DATA_BYTE(linedi + 4 * wpl, j, L_MIN(val4, minval));
812  SET_DATA_BYTE(linedi + 5 * wpl, j, L_MIN(minval, val7));
813  minval = L_MIN(val7, val8);
814  SET_DATA_BYTE(linedi + 6 * wpl, j, L_MIN(val6, minval));
815  SET_DATA_BYTE(linedi + 7 * wpl, j, L_MIN(minval, val9));
816  }
817  }
818  return pixd;
819 }
820 
821 
836 PIX *
838  l_int32 hsize,
839  l_int32 vsize)
840 {
841 PIX *pixt, *pixb, *pixbd, *pixd;
842 
843  if (!pixs)
844  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
845  if (pixGetDepth(pixs) != 8)
846  return (PIX *)ERROR_PTR("pixs not 8 bpp", __func__, NULL);
847  if (pixGetColormap(pixs))
848  return (PIX *)ERROR_PTR("pix has colormap", __func__, NULL);
849  if ((hsize != 1 && hsize != 3) ||
850  (vsize != 1 && vsize != 3))
851  return (PIX *)ERROR_PTR("invalid size: must be 1 or 3", __func__, NULL);
852 
853  if (hsize == 1 && vsize == 1)
854  return pixCopy(NULL, pixs);
855 
856  pixb = pixAddBorderGeneral(pixs, 4, 8, 2, 8, 0);
857 
858  if (vsize == 1)
859  pixbd = pixDilateGray3h(pixb);
860  else if (hsize == 1)
861  pixbd = pixDilateGray3v(pixb);
862  else { /* vize == hsize == 3 */
863  pixt = pixDilateGray3h(pixb);
864  pixbd = pixDilateGray3v(pixt);
865  pixDestroy(&pixt);
866  }
867 
868  pixd = pixRemoveBorderGeneral(pixbd, 4, 8, 2, 8);
869  pixDestroy(&pixb);
870  pixDestroy(&pixbd);
871  return pixd;
872 }
873 
874 
887 static PIX *
889 {
890 l_uint32 *datas, *datad, *lines, *lined;
891 l_int32 w, h, wpl, i, j;
892 l_int32 val0, val1, val2, val3, val4, val5, val6, val7, val8, val9, maxval;
893 PIX *pixd;
894 
895  if (!pixs)
896  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
897  if (pixGetDepth(pixs) != 8)
898  return (PIX *)ERROR_PTR("pixs not 8 bpp", __func__, NULL);
899 
900  pixd = pixCreateTemplate(pixs);
901  pixGetDimensions(pixs, &w, &h, NULL);
902  datas = pixGetData(pixs);
903  datad = pixGetData(pixd);
904  wpl = pixGetWpl(pixs);
905  for (i = 0; i < h; i++) {
906  lines = datas + i * wpl;
907  lined = datad + i * wpl;
908  for (j = 1; j < w - 8; j += 8) {
909  val0 = GET_DATA_BYTE(lines, j - 1);
910  val1 = GET_DATA_BYTE(lines, j);
911  val2 = GET_DATA_BYTE(lines, j + 1);
912  val3 = GET_DATA_BYTE(lines, j + 2);
913  val4 = GET_DATA_BYTE(lines, j + 3);
914  val5 = GET_DATA_BYTE(lines, j + 4);
915  val6 = GET_DATA_BYTE(lines, j + 5);
916  val7 = GET_DATA_BYTE(lines, j + 6);
917  val8 = GET_DATA_BYTE(lines, j + 7);
918  val9 = GET_DATA_BYTE(lines, j + 8);
919  maxval = L_MAX(val1, val2);
920  SET_DATA_BYTE(lined, j, L_MAX(val0, maxval));
921  SET_DATA_BYTE(lined, j + 1, L_MAX(maxval, val3));
922  maxval = L_MAX(val3, val4);
923  SET_DATA_BYTE(lined, j + 2, L_MAX(val2, maxval));
924  SET_DATA_BYTE(lined, j + 3, L_MAX(maxval, val5));
925  maxval = L_MAX(val5, val6);
926  SET_DATA_BYTE(lined, j + 4, L_MAX(val4, maxval));
927  SET_DATA_BYTE(lined, j + 5, L_MAX(maxval, val7));
928  maxval = L_MAX(val7, val8);
929  SET_DATA_BYTE(lined, j + 6, L_MAX(val6, maxval));
930  SET_DATA_BYTE(lined, j + 7, L_MAX(maxval, val9));
931  }
932  }
933  return pixd;
934 }
935 
936 
949 static PIX *
951 {
952 l_uint32 *datas, *datad, *linesi, *linedi;
953 l_int32 w, h, wpl, i, j;
954 l_int32 val0, val1, val2, val3, val4, val5, val6, val7, val8, val9, maxval;
955 PIX *pixd;
956 
957  if (!pixs)
958  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
959  if (pixGetDepth(pixs) != 8)
960  return (PIX *)ERROR_PTR("pixs not 8 bpp", __func__, NULL);
961 
962  pixd = pixCreateTemplate(pixs);
963  pixGetDimensions(pixs, &w, &h, NULL);
964  datas = pixGetData(pixs);
965  datad = pixGetData(pixd);
966  wpl = pixGetWpl(pixs);
967  for (j = 0; j < w; j++) {
968  for (i = 1; i < h - 8; i += 8) {
969  linesi = datas + i * wpl;
970  linedi = datad + i * wpl;
971  val0 = GET_DATA_BYTE(linesi - wpl, j);
972  val1 = GET_DATA_BYTE(linesi, j);
973  val2 = GET_DATA_BYTE(linesi + wpl, j);
974  val3 = GET_DATA_BYTE(linesi + 2 * wpl, j);
975  val4 = GET_DATA_BYTE(linesi + 3 * wpl, j);
976  val5 = GET_DATA_BYTE(linesi + 4 * wpl, j);
977  val6 = GET_DATA_BYTE(linesi + 5 * wpl, j);
978  val7 = GET_DATA_BYTE(linesi + 6 * wpl, j);
979  val8 = GET_DATA_BYTE(linesi + 7 * wpl, j);
980  val9 = GET_DATA_BYTE(linesi + 8 * wpl, j);
981  maxval = L_MAX(val1, val2);
982  SET_DATA_BYTE(linedi, j, L_MAX(val0, maxval));
983  SET_DATA_BYTE(linedi + wpl, j, L_MAX(maxval, val3));
984  maxval = L_MAX(val3, val4);
985  SET_DATA_BYTE(linedi + 2 * wpl, j, L_MAX(val2, maxval));
986  SET_DATA_BYTE(linedi + 3 * wpl, j, L_MAX(maxval, val5));
987  maxval = L_MAX(val5, val6);
988  SET_DATA_BYTE(linedi + 4 * wpl, j, L_MAX(val4, maxval));
989  SET_DATA_BYTE(linedi + 5 * wpl, j, L_MAX(maxval, val7));
990  maxval = L_MAX(val7, val8);
991  SET_DATA_BYTE(linedi + 6 * wpl, j, L_MAX(val6, maxval));
992  SET_DATA_BYTE(linedi + 7 * wpl, j, L_MAX(maxval, val9));
993  }
994  }
995  return pixd;
996 }
997 
998 
1015 PIX *
1017  l_int32 hsize,
1018  l_int32 vsize)
1019 {
1020 PIX *pixt, *pixb, *pixbd, *pixd;
1021 
1022  if (!pixs)
1023  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
1024  if (pixGetDepth(pixs) != 8)
1025  return (PIX *)ERROR_PTR("pixs not 8 bpp", __func__, NULL);
1026  if (pixGetColormap(pixs))
1027  return (PIX *)ERROR_PTR("pix has colormap", __func__, NULL);
1028  if ((hsize != 1 && hsize != 3) ||
1029  (vsize != 1 && vsize != 3))
1030  return (PIX *)ERROR_PTR("invalid size: must be 1 or 3", __func__, NULL);
1031 
1032  if (hsize == 1 && vsize == 1)
1033  return pixCopy(NULL, pixs);
1034 
1035  pixb = pixAddBorderGeneral(pixs, 4, 8, 2, 8, 255); /* set to max */
1036 
1037  if (vsize == 1) {
1038  pixt = pixErodeGray3h(pixb);
1039  pixSetBorderVal(pixt, 4, 8, 2, 8, 0); /* set to min */
1040  pixbd = pixDilateGray3h(pixt);
1041  pixDestroy(&pixt);
1042  } else if (hsize == 1) {
1043  pixt = pixErodeGray3v(pixb);
1044  pixSetBorderVal(pixt, 4, 8, 2, 8, 0);
1045  pixbd = pixDilateGray3v(pixt);
1046  pixDestroy(&pixt);
1047  } else { /* vize == hsize == 3 */
1048  pixt = pixErodeGray3h(pixb);
1049  pixbd = pixErodeGray3v(pixt);
1050  pixDestroy(&pixt);
1051  pixSetBorderVal(pixbd, 4, 8, 2, 8, 0);
1052  pixt = pixDilateGray3h(pixbd);
1053  pixDestroy(&pixbd);
1054  pixbd = pixDilateGray3v(pixt);
1055  pixDestroy(&pixt);
1056  }
1057 
1058  pixd = pixRemoveBorderGeneral(pixbd, 4, 8, 2, 8);
1059  pixDestroy(&pixb);
1060  pixDestroy(&pixbd);
1061  return pixd;
1062 }
1063 
1064 
1079 PIX *
1081  l_int32 hsize,
1082  l_int32 vsize)
1083 {
1084 PIX *pixt, *pixb, *pixbd, *pixd;
1085 
1086  if (!pixs)
1087  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
1088  if (pixGetDepth(pixs) != 8)
1089  return (PIX *)ERROR_PTR("pixs not 8 bpp", __func__, NULL);
1090  if (pixGetColormap(pixs))
1091  return (PIX *)ERROR_PTR("pix has colormap", __func__, NULL);
1092  if ((hsize != 1 && hsize != 3) ||
1093  (vsize != 1 && vsize != 3))
1094  return (PIX *)ERROR_PTR("invalid size: must be 1 or 3", __func__, NULL);
1095 
1096  if (hsize == 1 && vsize == 1)
1097  return pixCopy(NULL, pixs);
1098 
1099  pixb = pixAddBorderGeneral(pixs, 4, 8, 2, 8, 0); /* set to min */
1100 
1101  if (vsize == 1) {
1102  pixt = pixDilateGray3h(pixb);
1103  pixSetBorderVal(pixt, 4, 8, 2, 8, 255); /* set to max */
1104  pixbd = pixErodeGray3h(pixt);
1105  pixDestroy(&pixt);
1106  } else if (hsize == 1) {
1107  pixt = pixDilateGray3v(pixb);
1108  pixSetBorderVal(pixt, 4, 8, 2, 8, 255);
1109  pixbd = pixErodeGray3v(pixt);
1110  pixDestroy(&pixt);
1111  } else { /* vize == hsize == 3 */
1112  pixt = pixDilateGray3h(pixb);
1113  pixbd = pixDilateGray3v(pixt);
1114  pixDestroy(&pixt);
1115  pixSetBorderVal(pixbd, 4, 8, 2, 8, 255);
1116  pixt = pixErodeGray3h(pixbd);
1117  pixDestroy(&pixbd);
1118  pixbd = pixErodeGray3v(pixt);
1119  pixDestroy(&pixt);
1120  }
1121 
1122  pixd = pixRemoveBorderGeneral(pixbd, 4, 8, 2, 8);
1123  pixDestroy(&pixb);
1124  pixDestroy(&pixbd);
1125  return pixd;
1126 }
1127 
1128 
1129 /*-----------------------------------------------------------------*
1130  * Low-level gray morphological operations *
1131  *-----------------------------------------------------------------*/
1160 static void
1161 dilateGrayLow(l_uint32 *datad,
1162  l_int32 w,
1163  l_int32 h,
1164  l_int32 wpld,
1165  l_uint32 *datas,
1166  l_int32 wpls,
1167  l_int32 size,
1168  l_int32 direction,
1169  l_uint8 *buffer,
1170  l_uint8 *maxarray)
1171 {
1172 l_int32 i, j, k;
1173 l_int32 hsize, nsteps, startmax, startx, starty;
1174 l_uint8 maxval;
1175 l_uint32 *lines, *lined;
1176 
1177  if (direction == L_HORIZ) {
1178  hsize = size / 2;
1179  nsteps = (w - 2 * hsize) / size;
1180  for (i = 0; i < h; i++) {
1181  lines = datas + i * wpls;
1182  lined = datad + i * wpld;
1183 
1184  /* fill buffer with pixels in byte order */
1185  for (j = 0; j < w; j++)
1186  buffer[j] = GET_DATA_BYTE(lines, j);
1187 
1188  for (j = 0; j < nsteps; j++) {
1189  /* refill the minarray */
1190  startmax = (j + 1) * size - 1;
1191  maxarray[size - 1] = buffer[startmax];
1192  for (k = 1; k < size; k++) {
1193  maxarray[size - 1 - k] =
1194  L_MAX(maxarray[size - k], buffer[startmax - k]);
1195  maxarray[size - 1 + k] =
1196  L_MAX(maxarray[size + k - 2], buffer[startmax + k]);
1197  }
1198 
1199  /* compute dilation values */
1200  startx = hsize + j * size;
1201  SET_DATA_BYTE(lined, startx, maxarray[0]);
1202  SET_DATA_BYTE(lined, startx + size - 1, maxarray[2 * size - 2]);
1203  for (k = 1; k < size - 1; k++) {
1204  maxval = L_MAX(maxarray[k], maxarray[k + size - 1]);
1205  SET_DATA_BYTE(lined, startx + k, maxval);
1206  }
1207  }
1208  }
1209  } else { /* direction == L_VERT */
1210  hsize = size / 2;
1211  nsteps = (h - 2 * hsize) / size;
1212  for (j = 0; j < w; j++) {
1213  /* fill buffer with pixels in byte order */
1214  for (i = 0; i < h; i++) {
1215  lines = datas + i * wpls;
1216  buffer[i] = GET_DATA_BYTE(lines, j);
1217  }
1218 
1219  for (i = 0; i < nsteps; i++) {
1220  /* refill the minarray */
1221  startmax = (i + 1) * size - 1;
1222  maxarray[size - 1] = buffer[startmax];
1223  for (k = 1; k < size; k++) {
1224  maxarray[size - 1 - k] =
1225  L_MAX(maxarray[size - k], buffer[startmax - k]);
1226  maxarray[size - 1 + k] =
1227  L_MAX(maxarray[size + k - 2], buffer[startmax + k]);
1228  }
1229 
1230  /* compute dilation values */
1231  starty = hsize + i * size;
1232  lined = datad + starty * wpld;
1233  SET_DATA_BYTE(lined, j, maxarray[0]);
1234  SET_DATA_BYTE(lined + (size - 1) * wpld, j,
1235  maxarray[2 * size - 2]);
1236  for (k = 1; k < size - 1; k++) {
1237  maxval = L_MAX(maxarray[k], maxarray[k + size - 1]);
1238  SET_DATA_BYTE(lined + wpld * k, j, maxval);
1239  }
1240  }
1241  }
1242  }
1243 
1244  return;
1245 }
1246 
1247 
1267 static void
1268 erodeGrayLow(l_uint32 *datad,
1269  l_int32 w,
1270  l_int32 h,
1271  l_int32 wpld,
1272  l_uint32 *datas,
1273  l_int32 wpls,
1274  l_int32 size,
1275  l_int32 direction,
1276  l_uint8 *buffer,
1277  l_uint8 *minarray)
1278 {
1279 l_int32 i, j, k;
1280 l_int32 hsize, nsteps, startmin, startx, starty;
1281 l_uint8 minval;
1282 l_uint32 *lines, *lined;
1283 
1284  if (direction == L_HORIZ) {
1285  hsize = size / 2;
1286  nsteps = (w - 2 * hsize) / size;
1287  for (i = 0; i < h; i++) {
1288  lines = datas + i * wpls;
1289  lined = datad + i * wpld;
1290 
1291  /* fill buffer with pixels in byte order */
1292  for (j = 0; j < w; j++)
1293  buffer[j] = GET_DATA_BYTE(lines, j);
1294 
1295  for (j = 0; j < nsteps; j++) {
1296  /* refill the minarray */
1297  startmin = (j + 1) * size - 1;
1298  minarray[size - 1] = buffer[startmin];
1299  for (k = 1; k < size; k++) {
1300  minarray[size - 1 - k] =
1301  L_MIN(minarray[size - k], buffer[startmin - k]);
1302  minarray[size - 1 + k] =
1303  L_MIN(minarray[size + k - 2], buffer[startmin + k]);
1304  }
1305 
1306  /* compute erosion values */
1307  startx = hsize + j * size;
1308  SET_DATA_BYTE(lined, startx, minarray[0]);
1309  SET_DATA_BYTE(lined, startx + size - 1, minarray[2 * size - 2]);
1310  for (k = 1; k < size - 1; k++) {
1311  minval = L_MIN(minarray[k], minarray[k + size - 1]);
1312  SET_DATA_BYTE(lined, startx + k, minval);
1313  }
1314  }
1315  }
1316  } else { /* direction == L_VERT */
1317  hsize = size / 2;
1318  nsteps = (h - 2 * hsize) / size;
1319  for (j = 0; j < w; j++) {
1320  /* fill buffer with pixels in byte order */
1321  for (i = 0; i < h; i++) {
1322  lines = datas + i * wpls;
1323  buffer[i] = GET_DATA_BYTE(lines, j);
1324  }
1325 
1326  for (i = 0; i < nsteps; i++) {
1327  /* refill the minarray */
1328  startmin = (i + 1) * size - 1;
1329  minarray[size - 1] = buffer[startmin];
1330  for (k = 1; k < size; k++) {
1331  minarray[size - 1 - k] =
1332  L_MIN(minarray[size - k], buffer[startmin - k]);
1333  minarray[size - 1 + k] =
1334  L_MIN(minarray[size + k - 2], buffer[startmin + k]);
1335  }
1336 
1337  /* compute erosion values */
1338  starty = hsize + i * size;
1339  lined = datad + starty * wpld;
1340  SET_DATA_BYTE(lined, j, minarray[0]);
1341  SET_DATA_BYTE(lined + (size - 1) * wpld, j,
1342  minarray[2 * size - 2]);
1343  for (k = 1; k < size - 1; k++) {
1344  minval = L_MIN(minarray[k], minarray[k + size - 1]);
1345  SET_DATA_BYTE(lined + wpld * k, j, minval);
1346  }
1347  }
1348  }
1349  }
1350 
1351  return;
1352 }
#define GET_DATA_BYTE(pdata, n)
Definition: arrayaccess.h:188
#define SET_DATA_BYTE(pdata, n, val)
Definition: arrayaccess.h:198
static void erodeGrayLow(l_uint32 *datad, l_int32 w, l_int32 h, l_int32 wpld, l_uint32 *datas, l_int32 wpls, l_int32 size, l_int32 direction, l_uint8 *buffer, l_uint8 *minarray)
erodeGrayLow()
Definition: graymorph.c:1268
static void dilateGrayLow(l_uint32 *datad, l_int32 w, l_int32 h, l_int32 wpld, l_uint32 *datas, l_int32 wpls, l_int32 size, l_int32 direction, l_uint8 *buffer, l_uint8 *maxarray)
dilateGrayLow()
Definition: graymorph.c:1161
static PIX * pixErodeGray3h(PIX *pixs)
pixErodeGray3h()
Definition: graymorph.c:708
static PIX * pixErodeGray3v(PIX *pixs)
pixErodeGray3v()
Definition: graymorph.c:773
PIX * pixErodeGray3(PIX *pixs, l_int32 hsize, l_int32 vsize)
pixErodeGray3()
Definition: graymorph.c:657
static PIX * pixDilateGray3h(PIX *pixs)
pixDilateGray3h()
Definition: graymorph.c:888
PIX * pixOpenGray3(PIX *pixs, l_int32 hsize, l_int32 vsize)
pixOpenGray3()
Definition: graymorph.c:1016
PIX * pixCloseGray(PIX *pixs, l_int32 hsize, l_int32 vsize)
pixCloseGray()
Definition: graymorph.c:520
static PIX * pixDilateGray3v(PIX *pixs)
pixDilateGray3v()
Definition: graymorph.c:950
PIX * pixCloseGray3(PIX *pixs, l_int32 hsize, l_int32 vsize)
pixCloseGray3()
Definition: graymorph.c:1080
PIX * pixDilateGray(PIX *pixs, l_int32 hsize, l_int32 vsize)
pixDilateGray()
Definition: graymorph.c:276
PIX * pixOpenGray(PIX *pixs, l_int32 hsize, l_int32 vsize)
pixOpenGray()
Definition: graymorph.c:390
PIX * pixErodeGray(PIX *pixs, l_int32 hsize, l_int32 vsize)
pixErodeGray()
Definition: graymorph.c:162
PIX * pixDilateGray3(PIX *pixs, l_int32 hsize, l_int32 vsize)
pixDilateGray3()
Definition: graymorph.c:837
l_uint32 * pixGetData(PIX *pix)
pixGetData()
Definition: pix1.c:1642
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:608
l_ok pixGetDimensions(const PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
Definition: pix1.c:1074
PIX * pixCopy(PIX *pixd, const PIX *pixs)
pixCopy()
Definition: pix1.c:689
PIX * pixCreateTemplate(const PIX *pixs)
pixCreateTemplate()
Definition: pix1.c:380
PIX * pixClone(PIX *pixs)
pixClone()
Definition: pix1.c:582
PIX * pixRemoveBorderGeneral(PIX *pixs, l_int32 left, l_int32 right, l_int32 top, l_int32 bot)
pixRemoveBorderGeneral()
Definition: pix2.c:1996
PIX * pixAddBorderGeneral(PIX *pixs, l_int32 left, l_int32 right, l_int32 top, l_int32 bot, l_uint32 val)
pixAddBorderGeneral()
Definition: pix2.c:1863
l_ok pixSetBorderVal(PIX *pixs, l_int32 left, l_int32 right, l_int32 top, l_int32 bot, l_uint32 val)
pixSetBorderVal()
Definition: pix2.c:1521
l_ok pixSetOrClearBorder(PIX *pixs, l_int32 left, l_int32 right, l_int32 top, l_int32 bot, l_int32 op)
pixSetOrClearBorder()
Definition: pix2.c:1474
#define PIX_CLR
Definition: pix.h:447
#define PIX_SET
Definition: pix.h:448