Leptonica  1.77.0
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 #include "allheaders.h"
123 
124  /* Special static operations for 3x1, 1x3 and 3x3 structuring elements */
125 static PIX *pixErodeGray3h(PIX *pixs);
126 static PIX *pixErodeGray3v(PIX *pixs);
127 static PIX *pixDilateGray3h(PIX *pixs);
128 static PIX *pixDilateGray3v(PIX *pixs);
129 
130  /* Low-level gray morphological operations */
131 static void dilateGrayLow(l_uint32 *datad, l_int32 w, l_int32 h,
132  l_int32 wpld, l_uint32 *datas, l_int32 wpls,
133  l_int32 size, l_int32 direction, l_uint8 *buffer,
134  l_uint8 *maxarray);
135 static void erodeGrayLow(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 *minarray);
139 
140 /*-----------------------------------------------------------------*
141  * Top-level grayscale morphological operations *
142  *-----------------------------------------------------------------*/
157 PIX *
159  l_int32 hsize,
160  l_int32 vsize)
161 {
162 l_uint8 *buffer, *minarray;
163 l_int32 w, h, wplb, wplt;
164 l_int32 leftpix, rightpix, toppix, bottompix, maxsize;
165 l_uint32 *datab, *datat;
166 PIX *pixb, *pixt, *pixd;
167 
168  PROCNAME("pixErodeGray");
169 
170  if (!pixs)
171  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
172  if (pixGetDepth(pixs) != 8)
173  return (PIX *)ERROR_PTR("pixs not 8 bpp", procName, NULL);
174  if (hsize < 1 || vsize < 1)
175  return (PIX *)ERROR_PTR("hsize or vsize < 1", procName, NULL);
176  if ((hsize & 1) == 0 ) {
177  L_WARNING("horiz sel size must be odd; increasing by 1\n", procName);
178  hsize++;
179  }
180  if ((vsize & 1) == 0 ) {
181  L_WARNING("vert sel size must be odd; increasing by 1\n", procName);
182  vsize++;
183  }
184 
185  pixb = pixt = pixd = NULL;
186  buffer = minarray = NULL;
187 
188  if (hsize == 1 && vsize == 1)
189  return pixCopy(NULL, pixs);
190 
191  if (vsize == 1) { /* horizontal sel */
192  leftpix = (hsize + 1) / 2;
193  rightpix = (3 * hsize + 1) / 2;
194  toppix = 0;
195  bottompix = 0;
196  } else if (hsize == 1) { /* vertical sel */
197  leftpix = 0;
198  rightpix = 0;
199  toppix = (vsize + 1) / 2;
200  bottompix = (3 * vsize + 1) / 2;
201  } else {
202  leftpix = (hsize + 1) / 2;
203  rightpix = (3 * hsize + 1) / 2;
204  toppix = (vsize + 1) / 2;
205  bottompix = (3 * vsize + 1) / 2;
206  }
207 
208  pixb = pixAddBorderGeneral(pixs, leftpix, rightpix, toppix, bottompix, 255);
209  pixt = pixCreateTemplate(pixb);
210  if (!pixb || !pixt) {
211  L_ERROR("pixb and pixt not made\n", procName);
212  goto cleanup;
213  }
214 
215  pixGetDimensions(pixt, &w, &h, NULL);
216  datab = pixGetData(pixb);
217  datat = pixGetData(pixt);
218  wplb = pixGetWpl(pixb);
219  wplt = pixGetWpl(pixt);
220 
221  buffer = (l_uint8 *)LEPT_CALLOC(L_MAX(w, h), sizeof(l_uint8));
222  maxsize = L_MAX(hsize, vsize);
223  minarray = (l_uint8 *)LEPT_CALLOC(2 * maxsize, sizeof(l_uint8));
224  if (!buffer || !minarray) {
225  L_ERROR("buffer and minarray not made\n", procName);
226  goto cleanup;
227  }
228 
229  if (vsize == 1) {
230  erodeGrayLow(datat, w, h, wplt, datab, wplb, hsize, L_HORIZ,
231  buffer, minarray);
232  } else if (hsize == 1) {
233  erodeGrayLow(datat, w, h, wplt, datab, wplb, vsize, L_VERT,
234  buffer, minarray);
235  } else {
236  erodeGrayLow(datat, w, h, wplt, datab, wplb, hsize, L_HORIZ,
237  buffer, minarray);
238  pixSetOrClearBorder(pixt, leftpix, rightpix, toppix, bottompix,
239  PIX_SET);
240  erodeGrayLow(datab, w, h, wplb, datat, wplt, vsize, L_VERT,
241  buffer, minarray);
242  pixDestroy(&pixt);
243  pixt = pixClone(pixb);
244  }
245 
246  pixd = pixRemoveBorderGeneral(pixt, leftpix, rightpix, toppix, bottompix);
247  if (!pixd)
248  L_ERROR("pixd not made\n", procName);
249 
250 cleanup:
251  LEPT_FREE(buffer);
252  LEPT_FREE(minarray);
253  pixDestroy(&pixb);
254  pixDestroy(&pixt);
255  return pixd;
256 }
257 
258 
273 PIX *
275  l_int32 hsize,
276  l_int32 vsize)
277 {
278 l_uint8 *buffer, *maxarray;
279 l_int32 w, h, wplb, wplt;
280 l_int32 leftpix, rightpix, toppix, bottompix, maxsize;
281 l_uint32 *datab, *datat;
282 PIX *pixb, *pixt, *pixd;
283 
284  PROCNAME("pixDilateGray");
285 
286  if (!pixs)
287  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
288  if (pixGetDepth(pixs) != 8)
289  return (PIX *)ERROR_PTR("pixs not 8 bpp", procName, NULL);
290  if (hsize < 1 || vsize < 1)
291  return (PIX *)ERROR_PTR("hsize or vsize < 1", procName, NULL);
292  if ((hsize & 1) == 0 ) {
293  L_WARNING("horiz sel size must be odd; increasing by 1\n", procName);
294  hsize++;
295  }
296  if ((vsize & 1) == 0 ) {
297  L_WARNING("vert sel size must be odd; increasing by 1\n", procName);
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", procName);
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", procName);
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", procName);
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  PROCNAME("pixOpenGray");
402 
403  if (!pixs)
404  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
405  if (pixGetDepth(pixs) != 8)
406  return (PIX *)ERROR_PTR("pixs not 8 bpp", procName, NULL);
407  if (hsize < 1 || vsize < 1)
408  return (PIX *)ERROR_PTR("hsize or vsize < 1", procName, NULL);
409  if ((hsize & 1) == 0 ) {
410  L_WARNING("horiz sel size must be odd; increasing by 1\n", procName);
411  hsize++;
412  }
413  if ((vsize & 1) == 0 ) {
414  L_WARNING("vert sel size must be odd; increasing by 1\n", procName);
415  vsize++;
416  }
417 
418  pixb = pixt = pixd = NULL;
419  buffer = array = NULL;
420 
421  if (hsize == 1 && vsize == 1)
422  return pixCopy(NULL, pixs);
423 
424  if (vsize == 1) { /* horizontal sel */
425  leftpix = (hsize + 1) / 2;
426  rightpix = (3 * hsize + 1) / 2;
427  toppix = 0;
428  bottompix = 0;
429  } else if (hsize == 1) { /* vertical sel */
430  leftpix = 0;
431  rightpix = 0;
432  toppix = (vsize + 1) / 2;
433  bottompix = (3 * vsize + 1) / 2;
434  } else {
435  leftpix = (hsize + 1) / 2;
436  rightpix = (3 * hsize + 1) / 2;
437  toppix = (vsize + 1) / 2;
438  bottompix = (3 * vsize + 1) / 2;
439  }
440 
441  pixb = pixAddBorderGeneral(pixs, leftpix, rightpix, toppix, bottompix, 255);
442  pixt = pixCreateTemplate(pixb);
443  if (!pixb || !pixt) {
444  L_ERROR("pixb and pixt not made\n", procName);
445  goto cleanup;
446  }
447 
448  pixGetDimensions(pixt, &w, &h, NULL);
449  datab = pixGetData(pixb);
450  datat = pixGetData(pixt);
451  wplb = pixGetWpl(pixb);
452  wplt = pixGetWpl(pixt);
453 
454  buffer = (l_uint8 *)LEPT_CALLOC(L_MAX(w, h), sizeof(l_uint8));
455  maxsize = L_MAX(hsize, vsize);
456  array = (l_uint8 *)LEPT_CALLOC(2 * maxsize, sizeof(l_uint8));
457  if (!buffer || !array) {
458  L_ERROR("buffer and array not made\n", procName);
459  goto cleanup;
460  }
461 
462  if (vsize == 1) {
463  erodeGrayLow(datat, w, h, wplt, datab, wplb, hsize, L_HORIZ,
464  buffer, array);
465  pixSetOrClearBorder(pixt, leftpix, rightpix, toppix, bottompix,
466  PIX_CLR);
467  dilateGrayLow(datab, w, h, wplb, datat, wplt, hsize, L_HORIZ,
468  buffer, array);
469  }
470  else if (hsize == 1) {
471  erodeGrayLow(datat, w, h, wplt, datab, wplb, vsize, L_VERT,
472  buffer, array);
473  pixSetOrClearBorder(pixt, leftpix, rightpix, toppix, bottompix,
474  PIX_CLR);
475  dilateGrayLow(datab, w, h, wplb, datat, wplt, vsize, L_VERT,
476  buffer, array);
477  } else {
478  erodeGrayLow(datat, w, h, wplt, datab, wplb, hsize, L_HORIZ,
479  buffer, array);
480  pixSetOrClearBorder(pixt, leftpix, rightpix, toppix, bottompix,
481  PIX_SET);
482  erodeGrayLow(datab, w, h, wplb, datat, wplt, vsize, L_VERT,
483  buffer, array);
484  pixSetOrClearBorder(pixb, leftpix, rightpix, toppix, bottompix,
485  PIX_CLR);
486  dilateGrayLow(datat, w, h, wplt, datab, wplb, hsize, L_HORIZ,
487  buffer, array);
488  pixSetOrClearBorder(pixt, leftpix, rightpix, toppix, bottompix,
489  PIX_CLR);
490  dilateGrayLow(datab, w, h, wplb, datat, wplt, vsize, L_VERT,
491  buffer, array);
492  }
493 
494  pixd = pixRemoveBorderGeneral(pixb, leftpix, rightpix, toppix, bottompix);
495  if (!pixd)
496  L_ERROR("pixd not made\n", procName);
497 
498 cleanup:
499  LEPT_FREE(buffer);
500  LEPT_FREE(array);
501  pixDestroy(&pixb);
502  pixDestroy(&pixt);
503  return pixd;
504 }
505 
506 
521 PIX *
523  l_int32 hsize,
524  l_int32 vsize)
525 {
526 l_uint8 *buffer;
527 l_uint8 *array; /* used to find either min or max in interval */
528 l_int32 w, h, wplb, wplt;
529 l_int32 leftpix, rightpix, toppix, bottompix, maxsize;
530 l_uint32 *datab, *datat;
531 PIX *pixb, *pixt, *pixd;
532 
533  PROCNAME("pixCloseGray");
534 
535  if (!pixs)
536  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
537  if (pixGetDepth(pixs) != 8)
538  return (PIX *)ERROR_PTR("pixs not 8 bpp", procName, NULL);
539  if (hsize < 1 || vsize < 1)
540  return (PIX *)ERROR_PTR("hsize or vsize < 1", procName, NULL);
541  if ((hsize & 1) == 0 ) {
542  L_WARNING("horiz sel size must be odd; increasing by 1\n", procName);
543  hsize++;
544  }
545  if ((vsize & 1) == 0 ) {
546  L_WARNING("vert sel size must be odd; increasing by 1\n", procName);
547  vsize++;
548  }
549 
550  pixb = pixt = pixd = NULL;
551  buffer = array = NULL;
552 
553  if (hsize == 1 && vsize == 1)
554  return pixCopy(NULL, pixs);
555 
556  if (vsize == 1) { /* horizontal sel */
557  leftpix = (hsize + 1) / 2;
558  rightpix = (3 * hsize + 1) / 2;
559  toppix = 0;
560  bottompix = 0;
561  } else if (hsize == 1) { /* vertical sel */
562  leftpix = 0;
563  rightpix = 0;
564  toppix = (vsize + 1) / 2;
565  bottompix = (3 * vsize + 1) / 2;
566  } else {
567  leftpix = (hsize + 1) / 2;
568  rightpix = (3 * hsize + 1) / 2;
569  toppix = (vsize + 1) / 2;
570  bottompix = (3 * vsize + 1) / 2;
571  }
572 
573  pixb = pixAddBorderGeneral(pixs, leftpix, rightpix, toppix, bottompix, 0);
574  pixt = pixCreateTemplate(pixb);
575  if (!pixb || !pixt) {
576  L_ERROR("pixb and pixt not made\n", procName);
577  goto cleanup;
578  }
579 
580  pixGetDimensions(pixt, &w, &h, NULL);
581  datab = pixGetData(pixb);
582  datat = pixGetData(pixt);
583  wplb = pixGetWpl(pixb);
584  wplt = pixGetWpl(pixt);
585 
586  buffer = (l_uint8 *)LEPT_CALLOC(L_MAX(w, h), sizeof(l_uint8));
587  maxsize = L_MAX(hsize, vsize);
588  array = (l_uint8 *)LEPT_CALLOC(2 * maxsize, sizeof(l_uint8));
589  if (!buffer || !array) {
590  L_ERROR("buffer and array not made\n", procName);
591  goto cleanup;
592  }
593 
594  if (vsize == 1) {
595  dilateGrayLow(datat, w, h, wplt, datab, wplb, hsize, L_HORIZ,
596  buffer, array);
597  pixSetOrClearBorder(pixt, leftpix, rightpix, toppix, bottompix,
598  PIX_SET);
599  erodeGrayLow(datab, w, h, wplb, datat, wplt, hsize, L_HORIZ,
600  buffer, array);
601  } else if (hsize == 1) {
602  dilateGrayLow(datat, w, h, wplt, datab, wplb, vsize, L_VERT,
603  buffer, array);
604  pixSetOrClearBorder(pixt, leftpix, rightpix, toppix, bottompix,
605  PIX_SET);
606  erodeGrayLow(datab, w, h, wplb, datat, wplt, vsize, L_VERT,
607  buffer, array);
608  } else {
609  dilateGrayLow(datat, w, h, wplt, datab, wplb, hsize, L_HORIZ,
610  buffer, array);
611  pixSetOrClearBorder(pixt, leftpix, rightpix, toppix, bottompix,
612  PIX_CLR);
613  dilateGrayLow(datab, w, h, wplb, datat, wplt, vsize, L_VERT,
614  buffer, array);
615  pixSetOrClearBorder(pixb, leftpix, rightpix, toppix, bottompix,
616  PIX_SET);
617  erodeGrayLow(datat, w, h, wplt, datab, wplb, hsize, L_HORIZ,
618  buffer, array);
619  pixSetOrClearBorder(pixt, leftpix, rightpix, toppix, bottompix,
620  PIX_SET);
621  erodeGrayLow(datab, w, h, wplb, datat, wplt, vsize, L_VERT,
622  buffer, array);
623  }
624 
625  pixd = pixRemoveBorderGeneral(pixb, leftpix, rightpix, toppix, bottompix);
626  if (!pixd)
627  L_ERROR("pixd not made\n", procName);
628 
629 cleanup:
630  LEPT_FREE(buffer);
631  LEPT_FREE(array);
632  pixDestroy(&pixb);
633  pixDestroy(&pixt);
634  return pixd;
635 }
636 
637 
638 /*-----------------------------------------------------------------*
639  * Special operations for 1x3, 3x1 and 3x3 Sels *
640  *-----------------------------------------------------------------*/
660 PIX *
662  l_int32 hsize,
663  l_int32 vsize)
664 {
665 PIX *pixt, *pixb, *pixbd, *pixd;
666 
667  PROCNAME("pixErodeGray3");
668 
669  if (!pixs)
670  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
671  if (pixGetDepth(pixs) != 8)
672  return (PIX *)ERROR_PTR("pixs not 8 bpp", procName, NULL);
673  if (pixGetColormap(pixs))
674  return (PIX *)ERROR_PTR("pix has colormap", procName, NULL);
675  if ((hsize != 1 && hsize != 3) ||
676  (vsize != 1 && vsize != 3))
677  return (PIX *)ERROR_PTR("invalid size: must be 1 or 3", procName, NULL);
678 
679  if (hsize == 1 && vsize == 1)
680  return pixCopy(NULL, pixs);
681 
682  pixb = pixAddBorderGeneral(pixs, 4, 8, 2, 8, 255);
683 
684  if (vsize == 1)
685  pixbd = pixErodeGray3h(pixb);
686  else if (hsize == 1)
687  pixbd = pixErodeGray3v(pixb);
688  else { /* vize == hsize == 3 */
689  pixt = pixErodeGray3h(pixb);
690  pixbd = pixErodeGray3v(pixt);
691  pixDestroy(&pixt);
692  }
693 
694  pixd = pixRemoveBorderGeneral(pixbd, 4, 8, 2, 8);
695  pixDestroy(&pixb);
696  pixDestroy(&pixbd);
697  return pixd;
698 }
699 
700 
713 static PIX *
715 {
716 l_uint32 *datas, *datad, *lines, *lined;
717 l_int32 w, h, wpl, i, j;
718 l_int32 val0, val1, val2, val3, val4, val5, val6, val7, val8, val9, minval;
719 PIX *pixd;
720 
721  PROCNAME("pixErodeGray3h");
722 
723  if (!pixs)
724  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
725  if (pixGetDepth(pixs) != 8)
726  return (PIX *)ERROR_PTR("pixs not 8 bpp", procName, NULL);
727 
728  pixd = pixCreateTemplate(pixs);
729  pixGetDimensions(pixs, &w, &h, NULL);
730  datas = pixGetData(pixs);
731  datad = pixGetData(pixd);
732  wpl = pixGetWpl(pixs);
733  for (i = 0; i < h; i++) {
734  lines = datas + i * wpl;
735  lined = datad + i * wpl;
736  for (j = 1; j < w - 8; j += 8) {
737  val0 = GET_DATA_BYTE(lines, j - 1);
738  val1 = GET_DATA_BYTE(lines, j);
739  val2 = GET_DATA_BYTE(lines, j + 1);
740  val3 = GET_DATA_BYTE(lines, j + 2);
741  val4 = GET_DATA_BYTE(lines, j + 3);
742  val5 = GET_DATA_BYTE(lines, j + 4);
743  val6 = GET_DATA_BYTE(lines, j + 5);
744  val7 = GET_DATA_BYTE(lines, j + 6);
745  val8 = GET_DATA_BYTE(lines, j + 7);
746  val9 = GET_DATA_BYTE(lines, j + 8);
747  minval = L_MIN(val1, val2);
748  SET_DATA_BYTE(lined, j, L_MIN(val0, minval));
749  SET_DATA_BYTE(lined, j + 1, L_MIN(minval, val3));
750  minval = L_MIN(val3, val4);
751  SET_DATA_BYTE(lined, j + 2, L_MIN(val2, minval));
752  SET_DATA_BYTE(lined, j + 3, L_MIN(minval, val5));
753  minval = L_MIN(val5, val6);
754  SET_DATA_BYTE(lined, j + 4, L_MIN(val4, minval));
755  SET_DATA_BYTE(lined, j + 5, L_MIN(minval, val7));
756  minval = L_MIN(val7, val8);
757  SET_DATA_BYTE(lined, j + 6, L_MIN(val6, minval));
758  SET_DATA_BYTE(lined, j + 7, L_MIN(minval, val9));
759  }
760  }
761  return pixd;
762 }
763 
764 
780 static PIX *
782 {
783 l_uint32 *datas, *datad, *linesi, *linedi;
784 l_int32 w, h, wpl, i, j;
785 l_int32 val0, val1, val2, val3, val4, val5, val6, val7, val8, val9, minval;
786 PIX *pixd;
787 
788  PROCNAME("pixErodeGray3v");
789 
790  if (!pixs)
791  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
792  if (pixGetDepth(pixs) != 8)
793  return (PIX *)ERROR_PTR("pixs not 8 bpp", procName, NULL);
794 
795  pixd = pixCreateTemplate(pixs);
796  pixGetDimensions(pixs, &w, &h, NULL);
797  datas = pixGetData(pixs);
798  datad = pixGetData(pixd);
799  wpl = pixGetWpl(pixs);
800  for (j = 0; j < w; j++) {
801  for (i = 1; i < h - 8; i += 8) {
802  linesi = datas + i * wpl;
803  linedi = datad + i * wpl;
804  val0 = GET_DATA_BYTE(linesi - wpl, j);
805  val1 = GET_DATA_BYTE(linesi, j);
806  val2 = GET_DATA_BYTE(linesi + wpl, j);
807  val3 = GET_DATA_BYTE(linesi + 2 * wpl, j);
808  val4 = GET_DATA_BYTE(linesi + 3 * wpl, j);
809  val5 = GET_DATA_BYTE(linesi + 4 * wpl, j);
810  val6 = GET_DATA_BYTE(linesi + 5 * wpl, j);
811  val7 = GET_DATA_BYTE(linesi + 6 * wpl, j);
812  val8 = GET_DATA_BYTE(linesi + 7 * wpl, j);
813  val9 = GET_DATA_BYTE(linesi + 8 * wpl, j);
814  minval = L_MIN(val1, val2);
815  SET_DATA_BYTE(linedi, j, L_MIN(val0, minval));
816  SET_DATA_BYTE(linedi + wpl, j, L_MIN(minval, val3));
817  minval = L_MIN(val3, val4);
818  SET_DATA_BYTE(linedi + 2 * wpl, j, L_MIN(val2, minval));
819  SET_DATA_BYTE(linedi + 3 * wpl, j, L_MIN(minval, val5));
820  minval = L_MIN(val5, val6);
821  SET_DATA_BYTE(linedi + 4 * wpl, j, L_MIN(val4, minval));
822  SET_DATA_BYTE(linedi + 5 * wpl, j, L_MIN(minval, val7));
823  minval = L_MIN(val7, val8);
824  SET_DATA_BYTE(linedi + 6 * wpl, j, L_MIN(val6, minval));
825  SET_DATA_BYTE(linedi + 7 * wpl, j, L_MIN(minval, val9));
826  }
827  }
828  return pixd;
829 }
830 
831 
846 PIX *
848  l_int32 hsize,
849  l_int32 vsize)
850 {
851 PIX *pixt, *pixb, *pixbd, *pixd;
852 
853  PROCNAME("pixDilateGray3");
854 
855  if (!pixs)
856  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
857  if (pixGetDepth(pixs) != 8)
858  return (PIX *)ERROR_PTR("pixs not 8 bpp", procName, NULL);
859  if (pixGetColormap(pixs))
860  return (PIX *)ERROR_PTR("pix has colormap", procName, NULL);
861  if ((hsize != 1 && hsize != 3) ||
862  (vsize != 1 && vsize != 3))
863  return (PIX *)ERROR_PTR("invalid size: must be 1 or 3", procName, NULL);
864 
865  if (hsize == 1 && vsize == 1)
866  return pixCopy(NULL, pixs);
867 
868  pixb = pixAddBorderGeneral(pixs, 4, 8, 2, 8, 0);
869 
870  if (vsize == 1)
871  pixbd = pixDilateGray3h(pixb);
872  else if (hsize == 1)
873  pixbd = pixDilateGray3v(pixb);
874  else { /* vize == hsize == 3 */
875  pixt = pixDilateGray3h(pixb);
876  pixbd = pixDilateGray3v(pixt);
877  pixDestroy(&pixt);
878  }
879 
880  pixd = pixRemoveBorderGeneral(pixbd, 4, 8, 2, 8);
881  pixDestroy(&pixb);
882  pixDestroy(&pixbd);
883  return pixd;
884 }
885 
886 
899 static PIX *
901 {
902 l_uint32 *datas, *datad, *lines, *lined;
903 l_int32 w, h, wpl, i, j;
904 l_int32 val0, val1, val2, val3, val4, val5, val6, val7, val8, val9, maxval;
905 PIX *pixd;
906 
907  PROCNAME("pixDilateGray3h");
908 
909  if (!pixs)
910  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
911  if (pixGetDepth(pixs) != 8)
912  return (PIX *)ERROR_PTR("pixs not 8 bpp", procName, NULL);
913 
914  pixd = pixCreateTemplate(pixs);
915  pixGetDimensions(pixs, &w, &h, NULL);
916  datas = pixGetData(pixs);
917  datad = pixGetData(pixd);
918  wpl = pixGetWpl(pixs);
919  for (i = 0; i < h; i++) {
920  lines = datas + i * wpl;
921  lined = datad + i * wpl;
922  for (j = 1; j < w - 8; j += 8) {
923  val0 = GET_DATA_BYTE(lines, j - 1);
924  val1 = GET_DATA_BYTE(lines, j);
925  val2 = GET_DATA_BYTE(lines, j + 1);
926  val3 = GET_DATA_BYTE(lines, j + 2);
927  val4 = GET_DATA_BYTE(lines, j + 3);
928  val5 = GET_DATA_BYTE(lines, j + 4);
929  val6 = GET_DATA_BYTE(lines, j + 5);
930  val7 = GET_DATA_BYTE(lines, j + 6);
931  val8 = GET_DATA_BYTE(lines, j + 7);
932  val9 = GET_DATA_BYTE(lines, j + 8);
933  maxval = L_MAX(val1, val2);
934  SET_DATA_BYTE(lined, j, L_MAX(val0, maxval));
935  SET_DATA_BYTE(lined, j + 1, L_MAX(maxval, val3));
936  maxval = L_MAX(val3, val4);
937  SET_DATA_BYTE(lined, j + 2, L_MAX(val2, maxval));
938  SET_DATA_BYTE(lined, j + 3, L_MAX(maxval, val5));
939  maxval = L_MAX(val5, val6);
940  SET_DATA_BYTE(lined, j + 4, L_MAX(val4, maxval));
941  SET_DATA_BYTE(lined, j + 5, L_MAX(maxval, val7));
942  maxval = L_MAX(val7, val8);
943  SET_DATA_BYTE(lined, j + 6, L_MAX(val6, maxval));
944  SET_DATA_BYTE(lined, j + 7, L_MAX(maxval, val9));
945  }
946  }
947  return pixd;
948 }
949 
950 
963 static PIX *
965 {
966 l_uint32 *datas, *datad, *linesi, *linedi;
967 l_int32 w, h, wpl, i, j;
968 l_int32 val0, val1, val2, val3, val4, val5, val6, val7, val8, val9, maxval;
969 PIX *pixd;
970 
971  PROCNAME("pixDilateGray3v");
972 
973  if (!pixs)
974  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
975  if (pixGetDepth(pixs) != 8)
976  return (PIX *)ERROR_PTR("pixs not 8 bpp", procName, NULL);
977 
978  pixd = pixCreateTemplate(pixs);
979  pixGetDimensions(pixs, &w, &h, NULL);
980  datas = pixGetData(pixs);
981  datad = pixGetData(pixd);
982  wpl = pixGetWpl(pixs);
983  for (j = 0; j < w; j++) {
984  for (i = 1; i < h - 8; i += 8) {
985  linesi = datas + i * wpl;
986  linedi = datad + i * wpl;
987  val0 = GET_DATA_BYTE(linesi - wpl, j);
988  val1 = GET_DATA_BYTE(linesi, j);
989  val2 = GET_DATA_BYTE(linesi + wpl, j);
990  val3 = GET_DATA_BYTE(linesi + 2 * wpl, j);
991  val4 = GET_DATA_BYTE(linesi + 3 * wpl, j);
992  val5 = GET_DATA_BYTE(linesi + 4 * wpl, j);
993  val6 = GET_DATA_BYTE(linesi + 5 * wpl, j);
994  val7 = GET_DATA_BYTE(linesi + 6 * wpl, j);
995  val8 = GET_DATA_BYTE(linesi + 7 * wpl, j);
996  val9 = GET_DATA_BYTE(linesi + 8 * wpl, j);
997  maxval = L_MAX(val1, val2);
998  SET_DATA_BYTE(linedi, j, L_MAX(val0, maxval));
999  SET_DATA_BYTE(linedi + wpl, j, L_MAX(maxval, val3));
1000  maxval = L_MAX(val3, val4);
1001  SET_DATA_BYTE(linedi + 2 * wpl, j, L_MAX(val2, maxval));
1002  SET_DATA_BYTE(linedi + 3 * wpl, j, L_MAX(maxval, val5));
1003  maxval = L_MAX(val5, val6);
1004  SET_DATA_BYTE(linedi + 4 * wpl, j, L_MAX(val4, maxval));
1005  SET_DATA_BYTE(linedi + 5 * wpl, j, L_MAX(maxval, val7));
1006  maxval = L_MAX(val7, val8);
1007  SET_DATA_BYTE(linedi + 6 * wpl, j, L_MAX(val6, maxval));
1008  SET_DATA_BYTE(linedi + 7 * wpl, j, L_MAX(maxval, val9));
1009  }
1010  }
1011  return pixd;
1012 }
1013 
1014 
1031 PIX *
1033  l_int32 hsize,
1034  l_int32 vsize)
1035 {
1036 PIX *pixt, *pixb, *pixbd, *pixd;
1037 
1038  PROCNAME("pixOpenGray3");
1039 
1040  if (!pixs)
1041  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1042  if (pixGetDepth(pixs) != 8)
1043  return (PIX *)ERROR_PTR("pixs not 8 bpp", procName, NULL);
1044  if (pixGetColormap(pixs))
1045  return (PIX *)ERROR_PTR("pix has colormap", procName, NULL);
1046  if ((hsize != 1 && hsize != 3) ||
1047  (vsize != 1 && vsize != 3))
1048  return (PIX *)ERROR_PTR("invalid size: must be 1 or 3", procName, NULL);
1049 
1050  if (hsize == 1 && vsize == 1)
1051  return pixCopy(NULL, pixs);
1052 
1053  pixb = pixAddBorderGeneral(pixs, 4, 8, 2, 8, 255); /* set to max */
1054 
1055  if (vsize == 1) {
1056  pixt = pixErodeGray3h(pixb);
1057  pixSetBorderVal(pixt, 4, 8, 2, 8, 0); /* set to min */
1058  pixbd = pixDilateGray3h(pixt);
1059  pixDestroy(&pixt);
1060  } else if (hsize == 1) {
1061  pixt = pixErodeGray3v(pixb);
1062  pixSetBorderVal(pixt, 4, 8, 2, 8, 0);
1063  pixbd = pixDilateGray3v(pixt);
1064  pixDestroy(&pixt);
1065  } else { /* vize == hsize == 3 */
1066  pixt = pixErodeGray3h(pixb);
1067  pixbd = pixErodeGray3v(pixt);
1068  pixDestroy(&pixt);
1069  pixSetBorderVal(pixbd, 4, 8, 2, 8, 0);
1070  pixt = pixDilateGray3h(pixbd);
1071  pixDestroy(&pixbd);
1072  pixbd = pixDilateGray3v(pixt);
1073  pixDestroy(&pixt);
1074  }
1075 
1076  pixd = pixRemoveBorderGeneral(pixbd, 4, 8, 2, 8);
1077  pixDestroy(&pixb);
1078  pixDestroy(&pixbd);
1079  return pixd;
1080 }
1081 
1082 
1097 PIX *
1099  l_int32 hsize,
1100  l_int32 vsize)
1101 {
1102 PIX *pixt, *pixb, *pixbd, *pixd;
1103 
1104  PROCNAME("pixCloseGray3");
1105 
1106  if (!pixs)
1107  return (PIX *)ERROR_PTR("pixs not defined", procName, NULL);
1108  if (pixGetDepth(pixs) != 8)
1109  return (PIX *)ERROR_PTR("pixs not 8 bpp", procName, NULL);
1110  if (pixGetColormap(pixs))
1111  return (PIX *)ERROR_PTR("pix has colormap", procName, NULL);
1112  if ((hsize != 1 && hsize != 3) ||
1113  (vsize != 1 && vsize != 3))
1114  return (PIX *)ERROR_PTR("invalid size: must be 1 or 3", procName, NULL);
1115 
1116  if (hsize == 1 && vsize == 1)
1117  return pixCopy(NULL, pixs);
1118 
1119  pixb = pixAddBorderGeneral(pixs, 4, 8, 2, 8, 0); /* set to min */
1120 
1121  if (vsize == 1) {
1122  pixt = pixDilateGray3h(pixb);
1123  pixSetBorderVal(pixt, 4, 8, 2, 8, 255); /* set to max */
1124  pixbd = pixErodeGray3h(pixt);
1125  pixDestroy(&pixt);
1126  } else if (hsize == 1) {
1127  pixt = pixDilateGray3v(pixb);
1128  pixSetBorderVal(pixt, 4, 8, 2, 8, 255);
1129  pixbd = pixErodeGray3v(pixt);
1130  pixDestroy(&pixt);
1131  } else { /* vize == hsize == 3 */
1132  pixt = pixDilateGray3h(pixb);
1133  pixbd = pixDilateGray3v(pixt);
1134  pixDestroy(&pixt);
1135  pixSetBorderVal(pixbd, 4, 8, 2, 8, 255);
1136  pixt = pixErodeGray3h(pixbd);
1137  pixDestroy(&pixbd);
1138  pixbd = pixErodeGray3v(pixt);
1139  pixDestroy(&pixt);
1140  }
1141 
1142  pixd = pixRemoveBorderGeneral(pixbd, 4, 8, 2, 8);
1143  pixDestroy(&pixb);
1144  pixDestroy(&pixbd);
1145  return pixd;
1146 }
1147 
1148 
1149 /*-----------------------------------------------------------------*
1150  * Low-level gray morphological operations *
1151  *-----------------------------------------------------------------*/
1177 static void
1178 dilateGrayLow(l_uint32 *datad,
1179  l_int32 w,
1180  l_int32 h,
1181  l_int32 wpld,
1182  l_uint32 *datas,
1183  l_int32 wpls,
1184  l_int32 size,
1185  l_int32 direction,
1186  l_uint8 *buffer,
1187  l_uint8 *maxarray)
1188 {
1189 l_int32 i, j, k;
1190 l_int32 hsize, nsteps, startmax, startx, starty;
1191 l_uint8 maxval;
1192 l_uint32 *lines, *lined;
1193 
1194  if (direction == L_HORIZ) {
1195  hsize = size / 2;
1196  nsteps = (w - 2 * hsize) / size;
1197  for (i = 0; i < h; i++) {
1198  lines = datas + i * wpls;
1199  lined = datad + i * wpld;
1200 
1201  /* fill buffer with pixels in byte order */
1202  for (j = 0; j < w; j++)
1203  buffer[j] = GET_DATA_BYTE(lines, j);
1204 
1205  for (j = 0; j < nsteps; j++) {
1206  /* refill the minarray */
1207  startmax = (j + 1) * size - 1;
1208  maxarray[size - 1] = buffer[startmax];
1209  for (k = 1; k < size; k++) {
1210  maxarray[size - 1 - k] =
1211  L_MAX(maxarray[size - k], buffer[startmax - k]);
1212  maxarray[size - 1 + k] =
1213  L_MAX(maxarray[size + k - 2], buffer[startmax + k]);
1214  }
1215 
1216  /* compute dilation values */
1217  startx = hsize + j * size;
1218  SET_DATA_BYTE(lined, startx, maxarray[0]);
1219  SET_DATA_BYTE(lined, startx + size - 1, maxarray[2 * size - 2]);
1220  for (k = 1; k < size - 1; k++) {
1221  maxval = L_MAX(maxarray[k], maxarray[k + size - 1]);
1222  SET_DATA_BYTE(lined, startx + k, maxval);
1223  }
1224  }
1225  }
1226  } else { /* direction == L_VERT */
1227  hsize = size / 2;
1228  nsteps = (h - 2 * hsize) / size;
1229  for (j = 0; j < w; j++) {
1230  /* fill buffer with pixels in byte order */
1231  for (i = 0; i < h; i++) {
1232  lines = datas + i * wpls;
1233  buffer[i] = GET_DATA_BYTE(lines, j);
1234  }
1235 
1236  for (i = 0; i < nsteps; i++) {
1237  /* refill the minarray */
1238  startmax = (i + 1) * size - 1;
1239  maxarray[size - 1] = buffer[startmax];
1240  for (k = 1; k < size; k++) {
1241  maxarray[size - 1 - k] =
1242  L_MAX(maxarray[size - k], buffer[startmax - k]);
1243  maxarray[size - 1 + k] =
1244  L_MAX(maxarray[size + k - 2], buffer[startmax + k]);
1245  }
1246 
1247  /* compute dilation values */
1248  starty = hsize + i * size;
1249  lined = datad + starty * wpld;
1250  SET_DATA_BYTE(lined, j, maxarray[0]);
1251  SET_DATA_BYTE(lined + (size - 1) * wpld, j,
1252  maxarray[2 * size - 2]);
1253  for (k = 1; k < size - 1; k++) {
1254  maxval = L_MAX(maxarray[k], maxarray[k + size - 1]);
1255  SET_DATA_BYTE(lined + wpld * k, j, maxval);
1256  }
1257  }
1258  }
1259  }
1260 
1261  return;
1262 }
1263 
1264 
1281 static void
1282 erodeGrayLow(l_uint32 *datad,
1283  l_int32 w,
1284  l_int32 h,
1285  l_int32 wpld,
1286  l_uint32 *datas,
1287  l_int32 wpls,
1288  l_int32 size,
1289  l_int32 direction,
1290  l_uint8 *buffer,
1291  l_uint8 *minarray)
1292 {
1293 l_int32 i, j, k;
1294 l_int32 hsize, nsteps, startmin, startx, starty;
1295 l_uint8 minval;
1296 l_uint32 *lines, *lined;
1297 
1298  if (direction == L_HORIZ) {
1299  hsize = size / 2;
1300  nsteps = (w - 2 * hsize) / size;
1301  for (i = 0; i < h; i++) {
1302  lines = datas + i * wpls;
1303  lined = datad + i * wpld;
1304 
1305  /* fill buffer with pixels in byte order */
1306  for (j = 0; j < w; j++)
1307  buffer[j] = GET_DATA_BYTE(lines, j);
1308 
1309  for (j = 0; j < nsteps; j++) {
1310  /* refill the minarray */
1311  startmin = (j + 1) * size - 1;
1312  minarray[size - 1] = buffer[startmin];
1313  for (k = 1; k < size; k++) {
1314  minarray[size - 1 - k] =
1315  L_MIN(minarray[size - k], buffer[startmin - k]);
1316  minarray[size - 1 + k] =
1317  L_MIN(minarray[size + k - 2], buffer[startmin + k]);
1318  }
1319 
1320  /* compute erosion values */
1321  startx = hsize + j * size;
1322  SET_DATA_BYTE(lined, startx, minarray[0]);
1323  SET_DATA_BYTE(lined, startx + size - 1, minarray[2 * size - 2]);
1324  for (k = 1; k < size - 1; k++) {
1325  minval = L_MIN(minarray[k], minarray[k + size - 1]);
1326  SET_DATA_BYTE(lined, startx + k, minval);
1327  }
1328  }
1329  }
1330  } else { /* direction == L_VERT */
1331  hsize = size / 2;
1332  nsteps = (h - 2 * hsize) / size;
1333  for (j = 0; j < w; j++) {
1334  /* fill buffer with pixels in byte order */
1335  for (i = 0; i < h; i++) {
1336  lines = datas + i * wpls;
1337  buffer[i] = GET_DATA_BYTE(lines, j);
1338  }
1339 
1340  for (i = 0; i < nsteps; i++) {
1341  /* refill the minarray */
1342  startmin = (i + 1) * size - 1;
1343  minarray[size - 1] = buffer[startmin];
1344  for (k = 1; k < size; k++) {
1345  minarray[size - 1 - k] =
1346  L_MIN(minarray[size - k], buffer[startmin - k]);
1347  minarray[size - 1 + k] =
1348  L_MIN(minarray[size + k - 2], buffer[startmin + k]);
1349  }
1350 
1351  /* compute erosion values */
1352  starty = hsize + i * size;
1353  lined = datad + starty * wpld;
1354  SET_DATA_BYTE(lined, j, minarray[0]);
1355  SET_DATA_BYTE(lined + (size - 1) * wpld, j,
1356  minarray[2 * size - 2]);
1357  for (k = 1; k < size - 1; k++) {
1358  minval = L_MIN(minarray[k], minarray[k + size - 1]);
1359  SET_DATA_BYTE(lined + wpld * k, j, minval);
1360  }
1361  }
1362  }
1363  }
1364 
1365  return;
1366 }
PIX * pixCloseGray3(PIX *pixs, l_int32 hsize, l_int32 vsize)
pixCloseGray3()
Definition: graymorph.c:1098
PIX * pixDilateGray(PIX *pixs, l_int32 hsize, l_int32 vsize)
pixDilateGray()
Definition: graymorph.c:274
static PIX * pixErodeGray3h(PIX *pixs)
pixErodeGray3h()
Definition: graymorph.c:714
#define PIX_CLR
Definition: pix.h:330
PIX * pixRemoveBorderGeneral(PIX *pixs, l_int32 left, l_int32 right, l_int32 top, l_int32 bot)
pixRemoveBorderGeneral()
Definition: pix2.c:1918
PIX * pixOpenGray3(PIX *pixs, l_int32 hsize, l_int32 vsize)
pixOpenGray3()
Definition: graymorph.c:1032
static PIX * pixDilateGray3h(PIX *pixs)
pixDilateGray3h()
Definition: graymorph.c:900
PIX * pixCloseGray(PIX *pixs, l_int32 hsize, l_int32 vsize)
pixCloseGray()
Definition: graymorph.c:522
l_uint32 * pixGetData(PIX *pix)
pixGetData()
Definition: pix1.c:1624
PIX * pixCreateTemplate(PIX *pixs)
pixCreateTemplate()
Definition: pix1.c:367
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:1178
l_ok pixSetOrClearBorder(PIX *pixs, l_int32 left, l_int32 right, l_int32 top, l_int32 bot, l_int32 op)
pixSetOrClearBorder()
Definition: pix2.c:1439
l_ok pixSetBorderVal(PIX *pixs, l_int32 left, l_int32 right, l_int32 top, l_int32 bot, l_uint32 val)
pixSetBorderVal()
Definition: pix2.c:1488
#define PIX_SET
Definition: pix.h:331
static PIX * pixDilateGray3v(PIX *pixs)
pixDilateGray3v()
Definition: graymorph.c:964
#define SET_DATA_BYTE(pdata, n, val)
Definition: arrayaccess.h:198
#define GET_DATA_BYTE(pdata, n)
Definition: arrayaccess.h:188
PIX * pixClone(PIX *pixs)
pixClone()
Definition: pix1.c:515
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:543
l_ok pixGetDimensions(const PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
Definition: pix1.c:1065
static PIX * pixErodeGray3v(PIX *pixs)
pixErodeGray3v()
Definition: graymorph.c:781
Definition: pix.h:134
PIX * pixDilateGray3(PIX *pixs, l_int32 hsize, l_int32 vsize)
pixDilateGray3()
Definition: graymorph.c:847
PIX * pixCopy(PIX *pixd, PIX *pixs)
pixCopy()
Definition: pix1.c:628
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:158
PIX * pixErodeGray3(PIX *pixs, l_int32 hsize, l_int32 vsize)
pixErodeGray3()
Definition: graymorph.c:661
PIX * pixAddBorderGeneral(PIX *pixs, l_int32 left, l_int32 right, l_int32 top, l_int32 bot, l_uint32 val)
pixAddBorderGeneral()
Definition: pix2.c:1842
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:1282