Leptonica  1.83.1
Image processing and image analysis suite
dewarp3.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 
54 #ifdef HAVE_CONFIG_H
55 #include <config_auto.h>
56 #endif /* HAVE_CONFIG_H */
57 
58 #include <math.h>
59 #include "allheaders.h"
60 
61 static l_int32 dewarpaApplyInit(L_DEWARPA *dewa, l_int32 pageno, PIX *pixs,
62  l_int32 x, l_int32 y, L_DEWARP **pdew,
63  const char *debugfile);
64 static PIX *pixApplyVertDisparity(L_DEWARP *dew, PIX *pixs, l_int32 grayin);
65 static PIX * pixApplyHorizDisparity(L_DEWARP *dew, PIX *pixs, l_int32 grayin);
66 static BOXA *boxaApplyDisparity(L_DEWARP *dew, BOXA *boxa, l_int32 direction,
67  l_int32 mapdir);
68 
69 /*----------------------------------------------------------------------*
70  * Apply warping disparity array to pixa *
71  *----------------------------------------------------------------------*/
115 l_ok
117  l_int32 pageno,
118  PIX *pixs,
119  l_int32 grayin,
120  l_int32 x,
121  l_int32 y,
122  PIX **ppixd,
123  const char *debugfile)
124 {
125 L_DEWARP *dew1, *dew;
126 PIX *pixv, *pixh;
127 
128  /* Initialize the output with the input, so we'll have that
129  * in case we can't apply the page model. */
130  if (!ppixd)
131  return ERROR_INT("&pixd not defined", __func__, 1);
132  *ppixd = pixClone(pixs);
133  if (grayin > 255) {
134  L_WARNING("invalid grayin = %d; clipping at 255\n", __func__, grayin);
135  grayin = 255;
136  }
137 
138  /* Find the appropriate dew to use and fully populate its array(s) */
139  if (dewarpaApplyInit(dewa, pageno, pixs, x, y, &dew, debugfile))
140  return ERROR_INT("no model available", __func__, 1);
141 
142  /* Correct for vertical disparity and save the result */
143  if ((pixv = pixApplyVertDisparity(dew, pixs, grayin)) == NULL) {
144  dewarpMinimize(dew);
145  return ERROR_INT("pixv not made", __func__, 1);
146  }
147  pixDestroy(ppixd);
148  *ppixd = pixv;
149  if (debugfile) {
150  pixDisplayWithTitle(pixv, 300, 0, "pixv", 1);
151  lept_rmdir("lept/dewapply"); /* remove previous images */
152  lept_mkdir("lept/dewapply");
153  pixWriteDebug("/tmp/lept/dewapply/001.png", pixs, IFF_PNG);
154  pixWriteDebug("/tmp/lept/dewapply/002.png", pixv, IFF_PNG);
155  }
156 
157  /* Optionally, correct for horizontal disparity */
158  if (dewa->useboth && dew->hsuccess && !dew->skip_horiz) {
159  if (dew->hvalid == FALSE) {
160  L_INFO("invalid horiz model for page %d\n", __func__, pageno);
161  } else {
162  if ((pixh = pixApplyHorizDisparity(dew, pixv, grayin)) != NULL) {
163  pixDestroy(ppixd);
164  *ppixd = pixh;
165  if (debugfile) {
166  pixDisplayWithTitle(pixh, 600, 0, "pixh", 1);
167  pixWriteDebug("/tmp/lept/dewapply/003.png", pixh, IFF_PNG);
168  }
169  } else {
170  L_ERROR("horiz disparity failed on page %d\n",
171  __func__, pageno);
172  }
173  }
174  }
175 
176  if (debugfile) {
177  dew1 = dewarpaGetDewarp(dewa, pageno);
178  dewarpDebug(dew1, "lept/dewapply", 0);
179  convertFilesToPdf("/tmp/lept/dewapply", NULL, 250, 1.0, 0, 0,
180  "Dewarp Apply Disparity", debugfile);
181  lept_stderr("pdf file: %s\n", debugfile);
182  }
183 
184  /* Get rid of the large full res disparity arrays */
185  dewarpMinimize(dew);
186 
187  return 0;
188 }
189 
190 
213 static l_int32
215  l_int32 pageno,
216  PIX *pixs,
217  l_int32 x,
218  l_int32 y,
219  L_DEWARP **pdew,
220  const char *debugfile)
221 {
222 l_int32 ncols, debug;
223 L_DEWARP *dew1, *dew2;
224 PIX *pix1;
225 
226  if (!pdew)
227  return ERROR_INT("&dew not defined", __func__, 1);
228  *pdew = NULL;
229 
230  if (!dewa)
231  return ERROR_INT("dewa not defined", __func__, 1);
232  if (pageno < 0 || pageno > dewa->maxpage)
233  return ERROR_INT("invalid pageno", __func__, 1);
234  if (!pixs)
235  return ERROR_INT("pixs not defined", __func__, 1);
236  if (x < 0) x = 0;
237  if (y < 0) y = 0;
238  debug = (debugfile) ? 1 : 0;
239 
240  /* Make sure all models are valid and all refmodels have
241  * been added to dewa */
242  if (dewa->modelsready == FALSE)
243  dewarpaInsertRefModels(dewa, 0, debug);
244 
245  /* Check for the existence of a valid model; we don't expect
246  * all pages to have them. */
247  if ((dew1 = dewarpaGetDewarp(dewa, pageno)) == NULL) {
248  L_INFO("no valid dew model for page %d\n", __func__, pageno);
249  return 1;
250  }
251 
252  /* Get the page model that we will use and sanity-check that
253  * it is valid. The ultimate result will be put in dew1->pixd. */
254  if (dew1->hasref) /* point to another page with a model */
255  dew2 = dewarpaGetDewarp(dewa, dew1->refpage);
256  else
257  dew2 = dew1;
258  if (dew2->vvalid == FALSE)
259  return ERROR_INT("no model; shouldn't happen", __func__, 1);
260  *pdew = dew2;
261 
262  /* If check_columns is TRUE and useboth is TRUE, check for
263  * multiple columns. If there is more than one column, we
264  * only apply vertical disparity. */
265  if (dewa->useboth && dewa->check_columns) {
266  pix1 = pixConvertTo1(pixs, 140);
267  pixCountTextColumns(pix1, 0.3, 0.5, 0.1, &ncols, NULL);
268  pixDestroy(&pix1);
269  if (ncols > 1) {
270  L_INFO("found %d columns; not correcting horiz disparity\n",
271  __func__, ncols);
272  dew2->skip_horiz = TRUE;
273  } else {
274  dew2->skip_horiz = FALSE;
275  }
276  }
277 
278  /* Generate the full res disparity arrays if they don't exist
279  * (e.g., if they've been minimized or read from file), or if
280  * they are too small for the current image. */
281  dewarpPopulateFullRes(dew2, pixs, x, y);
282  return 0;
283 }
284 
285 
305 static PIX *
307  PIX *pixs,
308  l_int32 grayin)
309 {
310 l_int32 i, j, w, h, d, fw, fh, wpld, wplf, isrc, val8;
311 l_uint32 *datad, *lined;
312 l_float32 *dataf, *linef;
313 void **lineptrs;
314 FPIX *fpix;
315 PIX *pixd;
316 
317  if (!dew)
318  return (PIX *)ERROR_PTR("dew not defined", __func__, NULL);
319  if (!pixs)
320  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
321  pixGetDimensions(pixs, &w, &h, &d);
322  if (d != 1 && d != 8 && d != 32)
323  return (PIX *)ERROR_PTR("pix not 1, 8 or 32 bpp", __func__, NULL);
324  if ((fpix = dew->fullvdispar) == NULL)
325  return (PIX *)ERROR_PTR("fullvdispar not defined", __func__, NULL);
326  fpixGetDimensions(fpix, &fw, &fh);
327  if (fw < w || fh < h) {
328  lept_stderr("fw = %d, w = %d, fh = %d, h = %d\n", fw, w, fh, h);
329  return (PIX *)ERROR_PTR("invalid fpix size", __func__, NULL);
330  }
331 
332  /* Two choices for requested pixels outside pixs: (1) use pixels'
333  * from the boundary of pixs; use white or light gray pixels. */
334  pixd = pixCreateTemplate(pixs);
335  if (grayin >= 0)
336  pixSetAllGray(pixd, grayin);
337  datad = pixGetData(pixd);
338  dataf = fpixGetData(fpix);
339  wpld = pixGetWpl(pixd);
340  wplf = fpixGetWpl(fpix);
341  if (d == 1) {
342  lineptrs = pixGetLinePtrs(pixs, NULL);
343  for (i = 0; i < h; i++) {
344  lined = datad + i * wpld;
345  linef = dataf + i * wplf;
346  for (j = 0; j < w; j++) {
347  isrc = (l_int32)(i - linef[j] + 0.5);
348  if (grayin < 0) /* use value at boundary if outside */
349  isrc = L_MIN(L_MAX(isrc, 0), h - 1);
350  if (isrc >= 0 && isrc < h) { /* remains gray if outside */
351  if (GET_DATA_BIT(lineptrs[isrc], j))
352  SET_DATA_BIT(lined, j);
353  }
354  }
355  }
356  } else if (d == 8) {
357  lineptrs = pixGetLinePtrs(pixs, NULL);
358  for (i = 0; i < h; i++) {
359  lined = datad + i * wpld;
360  linef = dataf + i * wplf;
361  for (j = 0; j < w; j++) {
362  isrc = (l_int32)(i - linef[j] + 0.5);
363  if (grayin < 0)
364  isrc = L_MIN(L_MAX(isrc, 0), h - 1);
365  if (isrc >= 0 && isrc < h) {
366  val8 = GET_DATA_BYTE(lineptrs[isrc], j);
367  SET_DATA_BYTE(lined, j, val8);
368  }
369  }
370  }
371  } else { /* d == 32 */
372  lineptrs = pixGetLinePtrs(pixs, NULL);
373  for (i = 0; i < h; i++) {
374  lined = datad + i * wpld;
375  linef = dataf + i * wplf;
376  for (j = 0; j < w; j++) {
377  isrc = (l_int32)(i - linef[j] + 0.5);
378  if (grayin < 0)
379  isrc = L_MIN(L_MAX(isrc, 0), h - 1);
380  if (isrc >= 0 && isrc < h)
381  lined[j] = GET_DATA_FOUR_BYTES(lineptrs[isrc], j);
382  }
383  }
384  }
385 
386  LEPT_FREE(lineptrs);
387  return pixd;
388 }
389 
390 
413 static PIX *
415  PIX *pixs,
416  l_int32 grayin)
417 {
418 l_int32 i, j, w, h, d, fw, fh, wpls, wpld, wplf, jsrc, val8;
419 l_uint32 *datas, *lines, *datad, *lined;
420 l_float32 *dataf, *linef;
421 FPIX *fpix;
422 PIX *pixd;
423 
424  if (!dew)
425  return (PIX *)ERROR_PTR("dew not defined", __func__, pixs);
426  if (!pixs)
427  return (PIX *)ERROR_PTR("pixs not defined", __func__, NULL);
428  pixGetDimensions(pixs, &w, &h, &d);
429  if (d != 1 && d != 8 && d != 32)
430  return (PIX *)ERROR_PTR("pix not 1, 8 or 32 bpp", __func__, NULL);
431  if ((fpix = dew->fullhdispar) == NULL)
432  return (PIX *)ERROR_PTR("fullhdispar not defined", __func__, NULL);
433  fpixGetDimensions(fpix, &fw, &fh);
434  if (fw < w || fh < h) {
435  lept_stderr("fw = %d, w = %d, fh = %d, h = %d\n", fw, w, fh, h);
436  return (PIX *)ERROR_PTR("invalid fpix size", __func__, NULL);
437  }
438 
439  /* Two choices for requested pixels outside pixs: (1) use pixels'
440  * from the boundary of pixs; use white or light gray pixels. */
441  pixd = pixCreateTemplate(pixs);
442  if (grayin >= 0)
443  pixSetAllGray(pixd, grayin);
444  datas = pixGetData(pixs);
445  datad = pixGetData(pixd);
446  dataf = fpixGetData(fpix);
447  wpls = pixGetWpl(pixs);
448  wpld = pixGetWpl(pixd);
449  wplf = fpixGetWpl(fpix);
450  if (d == 1) {
451  for (i = 0; i < h; i++) {
452  lines = datas + i * wpls;
453  lined = datad + i * wpld;
454  linef = dataf + i * wplf;
455  for (j = 0; j < w; j++) {
456  jsrc = (l_int32)(j - linef[j] + 0.5);
457  if (grayin < 0) /* use value at boundary if outside */
458  jsrc = L_MIN(L_MAX(jsrc, 0), w - 1);
459  if (jsrc >= 0 && jsrc < w) { /* remains gray if outside */
460  if (GET_DATA_BIT(lines, jsrc))
461  SET_DATA_BIT(lined, j);
462  }
463  }
464  }
465  } else if (d == 8) {
466  for (i = 0; i < h; i++) {
467  lines = datas + i * wpls;
468  lined = datad + i * wpld;
469  linef = dataf + i * wplf;
470  for (j = 0; j < w; j++) {
471  jsrc = (l_int32)(j - linef[j] + 0.5);
472  if (grayin < 0)
473  jsrc = L_MIN(L_MAX(jsrc, 0), w - 1);
474  if (jsrc >= 0 && jsrc < w) {
475  val8 = GET_DATA_BYTE(lines, jsrc);
476  SET_DATA_BYTE(lined, j, val8);
477  }
478  }
479  }
480  } else { /* d == 32 */
481  for (i = 0; i < h; i++) {
482  lines = datas + i * wpls;
483  lined = datad + i * wpld;
484  linef = dataf + i * wplf;
485  for (j = 0; j < w; j++) {
486  jsrc = (l_int32)(j - linef[j] + 0.5);
487  if (grayin < 0)
488  jsrc = L_MIN(L_MAX(jsrc, 0), w - 1);
489  if (jsrc >= 0 && jsrc < w)
490  lined[j] = lines[jsrc];
491  }
492  }
493  }
494 
495  return pixd;
496 }
497 
498 
499 /*----------------------------------------------------------------------*
500  * Apply warping disparity array to boxa *
501  *----------------------------------------------------------------------*/
530 l_ok
532  l_int32 pageno,
533  PIX *pixs,
534  BOXA *boxas,
535  l_int32 mapdir,
536  l_int32 x,
537  l_int32 y,
538  BOXA **pboxad,
539  const char *debugfile)
540 {
541 l_int32 debug_out;
542 L_DEWARP *dew1, *dew;
543 BOXA *boxav, *boxah;
544 PIX *pixv, *pixh;
545 
546  /* Initialize the output with the input, so we'll have that
547  * in case we can't apply the page model. */
548  if (!pboxad)
549  return ERROR_INT("&boxad not defined", __func__, 1);
550  *pboxad = boxaCopy(boxas, L_CLONE);
551 
552  /* Find the appropriate dew to use and fully populate its array(s) */
553  if (dewarpaApplyInit(dewa, pageno, pixs, x, y, &dew, debugfile))
554  return ERROR_INT("no model available", __func__, 1);
555 
556  /* Correct for vertical disparity and save the result */
557  if ((boxav = boxaApplyDisparity(dew, boxas, L_VERT, mapdir)) == NULL) {
558  dewarpMinimize(dew);
559  return ERROR_INT("boxa1 not made", __func__, 1);
560  }
561  boxaDestroy(pboxad);
562  *pboxad = boxav;
563  pixv = NULL;
564  pixh = NULL;
565  if (debugfile && mapdir != 1)
566  L_INFO("Reverse map direction; no debug output\n", __func__);
567  debug_out = debugfile && (mapdir == 1);
568  if (debug_out) {
569  PIX *pix1;
570  lept_rmdir("lept/dewboxa"); /* remove previous images */
571  lept_mkdir("lept/dewboxa");
572  pix1 = pixConvertTo32(pixs);
573  pixRenderBoxaArb(pix1, boxas, 2, 255, 0, 0);
574  pixWriteDebug("/tmp/lept/dewboxa/01.png", pix1, IFF_PNG);
575  pixDestroy(&pix1);
576  pixv = pixApplyVertDisparity(dew, pixs, 255);
577  pix1 = pixConvertTo32(pixv);
578  pixRenderBoxaArb(pix1, boxav, 2, 0, 255, 0);
579  pixWriteDebug("/tmp/lept/dewboxa/02.png", pix1, IFF_PNG);
580  pixDestroy(&pix1);
581  }
582 
583  /* Optionally, correct for horizontal disparity */
584  if (dewa->useboth && dew->hsuccess && !dew->skip_horiz) {
585  if (dew->hvalid == FALSE) {
586  L_INFO("invalid horiz model for page %d\n", __func__, pageno);
587  } else {
588  boxah = boxaApplyDisparity(dew, boxav, L_HORIZ, mapdir);
589  if (!boxah) {
590  L_ERROR("horiz disparity fails on page %d\n", __func__, pageno);
591  } else {
592  boxaDestroy(pboxad);
593  *pboxad = boxah;
594  if (debug_out) {
595  PIX *pix1;
596  pixh = pixApplyHorizDisparity(dew, pixv, 255);
597  pix1 = pixConvertTo32(pixh);
598  pixRenderBoxaArb(pix1, boxah, 2, 0, 0, 255);
599  pixWriteDebug("/tmp/lept/dewboxa/03.png", pix1, IFF_PNG);
600  pixDestroy(&pixh);
601  pixDestroy(&pix1);
602  }
603  }
604  }
605  }
606 
607  if (debug_out) {
608  pixDestroy(&pixv);
609  dew1 = dewarpaGetDewarp(dewa, pageno);
610  dewarpDebug(dew1, "lept/dewapply", 0);
611  convertFilesToPdf("/tmp/lept/dewboxa", NULL, 135, 1.0, 0, 0,
612  "Dewarp Apply Disparity Boxa", debugfile);
613  lept_stderr("Dewarp Apply Disparity Boxa pdf file: %s\n",
614  debugfile);
615  }
616 
617  /* Get rid of the large full res disparity arrays */
618  dewarpMinimize(dew);
619 
620  return 0;
621 }
622 
623 
634 static BOXA *
636  BOXA *boxa,
637  l_int32 direction,
638  l_int32 mapdir)
639 {
640 l_int32 x, y, w, h, ib, ip, nbox, wpl;
641 l_float32 xn, yn;
642 l_float32 *data, *line;
643 BOX *boxs, *boxd;
644 BOXA *boxad;
645 FPIX *fpix;
646 PTA *ptas, *ptad;
647 
648  if (!dew)
649  return (BOXA *)ERROR_PTR("dew not defined", __func__, NULL);
650  if (!boxa)
651  return (BOXA *)ERROR_PTR("boxa not defined", __func__, NULL);
652  if (direction == L_VERT)
653  fpix = dew->fullvdispar;
654  else if (direction == L_HORIZ)
655  fpix = dew->fullhdispar;
656  else
657  return (BOXA *)ERROR_PTR("invalid direction", __func__, NULL);
658  if (!fpix)
659  return (BOXA *)ERROR_PTR("full disparity not defined", __func__, NULL);
660  fpixGetDimensions(fpix, &w, &h);
661 
662  /* Clip the output to the positive quadrant because all box
663  * coordinates must be non-negative. */
664  data = fpixGetData(fpix);
665  wpl = fpixGetWpl(fpix);
666  nbox = boxaGetCount(boxa);
667  boxad = boxaCreate(nbox);
668  for (ib = 0; ib < nbox; ib++) {
669  boxs = boxaGetBox(boxa, ib, L_COPY);
670  ptas = boxConvertToPta(boxs, 4);
671  ptad = ptaCreate(4);
672  for (ip = 0; ip < 4; ip++) {
673  ptaGetIPt(ptas, ip, &x, &y);
674  line = data + y * wpl;
675  if (direction == L_VERT) {
676  if (mapdir == 0)
677  yn = y - line[x];
678  else
679  yn = y + line[x];
680  yn = L_MAX(0, yn);
681  ptaAddPt(ptad, x, yn);
682  } else { /* direction == L_HORIZ */
683  if (mapdir == 0)
684  xn = x - line[x];
685  else
686  xn = x + line[x];
687  xn = L_MAX(0, xn);
688  ptaAddPt(ptad, xn, y);
689  }
690  }
691  boxd = ptaConvertToBox(ptad);
692  boxaAddBox(boxad, boxd, L_INSERT);
693  boxDestroy(&boxs);
694  ptaDestroy(&ptas);
695  ptaDestroy(&ptad);
696  }
697 
698  return boxad;
699 }
700 
701 
702 /*----------------------------------------------------------------------*
703  * Stripping out data and populating full res disparity *
704  *----------------------------------------------------------------------*/
718 l_ok
720 {
721 L_DEWARP *dewt;
722 
723  if (!dew)
724  return ERROR_INT("dew not defined", __func__, 1);
725 
726  /* If dew is a ref, minimize the actual dewarp */
727  if (dew->hasref)
728  dewt = dewarpaGetDewarp(dew->dewa, dew->refpage);
729  else
730  dewt = dew;
731  if (!dewt)
732  return ERROR_INT("dewt not found", __func__, 1);
733 
734  pixDestroy(&dewt->pixs);
735  fpixDestroy(&dewt->fullvdispar);
736  fpixDestroy(&dewt->fullhdispar);
737  numaDestroy(&dewt->namidys);
738  numaDestroy(&dewt->nacurves);
739  return 0;
740 }
741 
742 
772 l_ok
774  PIX *pix,
775  l_int32 x,
776  l_int32 y)
777 {
778 l_int32 width, height, fw, fh, deltaw, deltah, redfactor;
779 FPIX *fpixt1, *fpixt2;
780 
781  if (!dew)
782  return ERROR_INT("dew not defined", __func__, 1);
783  if (!dew->sampvdispar)
784  return ERROR_INT("no sampled vert disparity", __func__, 1);
785  if (x < 0) x = 0;
786  if (y < 0) y = 0;
787 
788  /* Establish the target size for the full res arrays */
789  if (pix)
790  pixGetDimensions(pix, &width, &height, NULL);
791  else {
792  width = dew->w;
793  height = dew->h;
794  }
795 
796  /* Destroy the existing arrays if they are too small */
797  if (dew->fullvdispar) {
798  fpixGetDimensions(dew->fullvdispar, &fw, &fh);
799  if (width > fw || height > fw)
800  fpixDestroy(&dew->fullvdispar);
801  }
802  if (dew->fullhdispar) {
803  fpixGetDimensions(dew->fullhdispar, &fw, &fh);
804  if (width > fw || height > fw)
805  fpixDestroy(&dew->fullhdispar);
806  }
807 
808  /* Find the required width and height expansion deltas */
809  deltaw = width - dew->sampling * (dew->nx - 1) + 2;
810  deltah = height - dew->sampling * (dew->ny - 1) + 2;
811  redfactor = dew->redfactor;
812  deltaw = redfactor * L_MAX(0, deltaw);
813  deltah = redfactor * L_MAX(0, deltah);
814 
815  /* Generate the full res vertical array if it doesn't exist,
816  * extending it as required to make it big enough. Use x,y
817  * to determine the amounts on each side. */
818  if (!dew->fullvdispar) {
819  fpixt1 = fpixCopy(dew->sampvdispar);
820  if (redfactor == 2)
821  fpixAddMultConstant(fpixt1, 0.0, (l_float32)redfactor);
822  fpixt2 = fpixScaleByInteger(fpixt1, dew->sampling * redfactor);
823  fpixDestroy(&fpixt1);
824  if (deltah == 0 && deltaw == 0) {
825  dew->fullvdispar = fpixt2;
826  }
827  else {
828  dew->fullvdispar = fpixAddSlopeBorder(fpixt2, x, deltaw - x,
829  y, deltah - y);
830  fpixDestroy(&fpixt2);
831  }
832  }
833 
834  /* Similarly, generate the full res horizontal array if it
835  * doesn't exist. Do this even if useboth == 1, but
836  * not if required to skip running horizontal disparity. */
837  if (!dew->fullhdispar && dew->samphdispar && !dew->skip_horiz) {
838  fpixt1 = fpixCopy(dew->samphdispar);
839  if (redfactor == 2)
840  fpixAddMultConstant(fpixt1, 0.0, (l_float32)redfactor);
841  fpixt2 = fpixScaleByInteger(fpixt1, dew->sampling * redfactor);
842  fpixDestroy(&fpixt1);
843  if (deltah == 0 && deltaw == 0) {
844  dew->fullhdispar = fpixt2;
845  }
846  else {
847  dew->fullhdispar = fpixAddSlopeBorder(fpixt2, x, deltaw - x,
848  y, deltah - y);
849  fpixDestroy(&fpixt2);
850  }
851  }
852 
853  return 0;
854 }
855 
856 
857 #if 0
858 /*----------------------------------------------------------------------*
859  * Static functions not presently in use *
860  *----------------------------------------------------------------------*/
884 static FPIX *
885 fpixSampledDisparity(FPIX *fpixs,
886  l_int32 sampling)
887 {
888 l_int32 w, h, wd, hd, i, j, is, js;
889 l_float32 val;
890 FPIX *fpixd;
891 
892  if (!fpixs)
893  return (FPIX *)ERROR_PTR("fpixs not defined", __func__, NULL);
894  if (sampling < 1)
895  return (FPIX *)ERROR_PTR("sampling < 1", __func__, NULL);
896 
897  fpixGetDimensions(fpixs, &w, &h);
898  wd = 1 + (w + sampling - 2) / sampling;
899  hd = 1 + (h + sampling - 2) / sampling;
900  if (wd < 3 || hd < 3)
901  return (FPIX *)ERROR_PTR("wd < 3 or hd < 3", __func__, NULL);
902  fpixd = fpixCreate(wd, hd);
903  for (i = 0; i < hd; i++) {
904  is = sampling * i;
905  if (is >= h) continue;
906  for (j = 0; j < wd; j++) {
907  js = sampling * j;
908  if (js >= w) continue;
909  fpixGetPixel(fpixs, js, is, &val);
910  fpixSetPixel(fpixd, j, i, val);
911  }
912  }
913 
914  return fpixd;
915 }
916 
917 static const l_float32 DefaultSlopeFactor = 0.1; /* just a guess; fix it */
918 
942 static FPIX *
943 fpixExtraHorizDisparity(FPIX *fpixv,
944  l_float32 factor,
945  l_int32 *pxwid)
946 {
947 l_int32 w, h, i, j, fw, wpl, maxloc;
948 l_float32 val1, val2, vdisp, vdisp0, maxval;
949 l_float32 *data, *line, *fadiff;
950 NUMA *nadiff;
951 FPIX *fpixh;
952 
953  if (!fpixv)
954  return (FPIX *)ERROR_PTR("fpixv not defined", __func__, NULL);
955  if (!pxwid)
956  return (FPIX *)ERROR_PTR("&xwid not defined", __func__, NULL);
957  if (factor == 0.0)
958  factor = DefaultSlopeFactor;
959 
960  /* Estimate horizontal disparity from the vertical disparity
961  * difference between the top and bottom, normalized to the
962  * image height. Add the maximum value to the width of the
963  * output image, so that all src pixels can be mapped
964  * into the dest. */
965  fpixGetDimensions(fpixv, &w, &h);
966  nadiff = numaCreate(w);
967  for (j = 0; j < w; j++) {
968  fpixGetPixel(fpixv, j, 0, &val1);
969  fpixGetPixel(fpixv, j, h - 1, &val2);
970  vdisp = factor * (val2 - val1) / (l_float32)h;
971  if (j == 0) vdisp0 = vdisp;
972  vdisp = vdisp0 - vdisp;
973  numaAddNumber(nadiff, vdisp);
974  }
975  numaGetMax(nadiff, &maxval, &maxloc);
976  *pxwid = (l_int32)(maxval + 0.5);
977 
978  fw = w + *pxwid;
979  fpixh = fpixCreate(fw, h);
980  data = fpixGetData(fpixh);
981  wpl = fpixGetWpl(fpixh);
982  fadiff = numaGetFArray(nadiff, L_NOCOPY);
983  for (i = 0; i < h; i++) {
984  line = data + i * wpl;
985  for (j = 0; j < fw; j++) {
986  if (j < maxloc) /* this may not work for even pages */
987  line[j] = fadiff[j];
988  else /* keep it at the max value the rest of the way across */
989  line[j] = maxval;
990  }
991  }
992 
993  numaDestroy(&nadiff);
994  return fpixh;
995 }
996 #endif
#define SET_DATA_BIT(pdata, n)
Definition: arrayaccess.h:127
#define GET_DATA_BYTE(pdata, n)
Definition: arrayaccess.h:188
#define GET_DATA_FOUR_BYTES(pdata, n)
Definition: arrayaccess.h:231
#define SET_DATA_BYTE(pdata, n, val)
Definition: arrayaccess.h:198
#define GET_DATA_BIT(pdata, n)
Definition: arrayaccess.h:123
BOXA * boxaCopy(BOXA *boxa, l_int32 copyflag)
boxaCopy()
Definition: boxbasic.c:475
void boxDestroy(BOX **pbox)
boxDestroy()
Definition: boxbasic.c:273
l_ok boxaAddBox(BOXA *boxa, BOX *box, l_int32 copyflag)
boxaAddBox()
Definition: boxbasic.c:553
void boxaDestroy(BOXA **pboxa)
boxaDestroy()
Definition: boxbasic.c:519
l_int32 boxaGetCount(const BOXA *boxa)
boxaGetCount()
Definition: boxbasic.c:661
BOX * boxaGetBox(BOXA *boxa, l_int32 index, l_int32 accessflag)
boxaGetBox()
Definition: boxbasic.c:702
BOXA * boxaCreate(l_int32 n)
boxaCreate()
Definition: boxbasic.c:442
PTA * boxConvertToPta(BOX *box, l_int32 ncorners)
boxConvertToPta()
Definition: boxfunc4.c:834
BOX * ptaConvertToBox(PTA *pta)
ptaConvertToBox()
Definition: boxfunc4.c:874
L_DEWARP * dewarpaGetDewarp(L_DEWARPA *dewa, l_int32 index)
dewarpaGetDewarp()
Definition: dewarp1.c:895
static l_int32 dewarpaApplyInit(L_DEWARPA *dewa, l_int32 pageno, PIX *pixs, l_int32 x, l_int32 y, L_DEWARP **pdew, const char *debugfile)
dewarpaApplyInit()
Definition: dewarp3.c:214
static PIX * pixApplyHorizDisparity(L_DEWARP *dew, PIX *pixs, l_int32 grayin)
pixApplyHorizDisparity()
Definition: dewarp3.c:414
static PIX * pixApplyVertDisparity(L_DEWARP *dew, PIX *pixs, l_int32 grayin)
pixApplyVertDisparity()
Definition: dewarp3.c:306
l_ok dewarpaApplyDisparity(L_DEWARPA *dewa, l_int32 pageno, PIX *pixs, l_int32 grayin, l_int32 x, l_int32 y, PIX **ppixd, const char *debugfile)
dewarpaApplyDisparity()
Definition: dewarp3.c:116
static BOXA * boxaApplyDisparity(L_DEWARP *dew, BOXA *boxa, l_int32 direction, l_int32 mapdir)
boxaApplyDisparity()
Definition: dewarp3.c:635
l_ok dewarpMinimize(L_DEWARP *dew)
dewarpMinimize()
Definition: dewarp3.c:719
l_ok dewarpaApplyDisparityBoxa(L_DEWARPA *dewa, l_int32 pageno, PIX *pixs, BOXA *boxas, l_int32 mapdir, l_int32 x, l_int32 y, BOXA **pboxad, const char *debugfile)
dewarpaApplyDisparityBoxa()
Definition: dewarp3.c:531
l_ok dewarpPopulateFullRes(L_DEWARP *dew, PIX *pix, l_int32 x, l_int32 y)
dewarpPopulateFullRes()
Definition: dewarp3.c:773
l_ok dewarpDebug(L_DEWARP *dew, const char *subdirs, l_int32 index)
dewarpDebug()
Definition: dewarp4.c:991
l_ok dewarpaInsertRefModels(L_DEWARPA *dewa, l_int32 notests, l_int32 debug)
dewarpaInsertRefModels()
Definition: dewarp4.c:444
l_ok fpixGetDimensions(FPIX *fpix, l_int32 *pw, l_int32 *ph)
fpixGetDimensions()
Definition: fpix1.c:314
l_int32 fpixGetWpl(FPIX *fpix)
fpixGetWpl()
Definition: fpix1.c:357
l_ok fpixSetPixel(FPIX *fpix, l_int32 x, l_int32 y, l_float32 val)
fpixSetPixel()
Definition: fpix1.c:527
void fpixDestroy(FPIX **pfpix)
fpixDestroy()
Definition: fpix1.c:280
FPIX * fpixCreate(l_int32 width, l_int32 height)
fpixCreate()
Definition: fpix1.c:152
l_ok fpixGetPixel(FPIX *fpix, l_int32 x, l_int32 y, l_float32 *pval)
fpixGetPixel()
Definition: fpix1.c:492
l_float32 * fpixGetData(FPIX *fpix)
fpixGetData()
Definition: fpix1.c:452
FPIX * fpixCopy(FPIX *fpixs)
fpixCopy()
Definition: fpix1.c:245
FPIX * fpixAddSlopeBorder(FPIX *fpixs, l_int32 left, l_int32 right, l_int32 top, l_int32 bot)
fpixAddSlopeBorder()
Definition: fpix2.c:1521
FPIX * fpixScaleByInteger(FPIX *fpixs, l_int32 factor)
fpixScaleByInteger()
Definition: fpix2.c:899
l_ok fpixAddMultConstant(FPIX *fpix, l_float32 addc, l_float32 multc)
fpixAddMultConstant()
Definition: fpix2.c:1136
l_ok pixRenderBoxaArb(PIX *pix, BOXA *boxa, l_int32 width, l_uint8 rval, l_uint8 gval, l_uint8 bval)
pixRenderBoxaArb()
Definition: graphics.c:1717
l_ok numaAddNumber(NUMA *na, l_float32 val)
numaAddNumber()
Definition: numabasic.c:460
NUMA * numaCreate(l_int32 n)
numaCreate()
Definition: numabasic.c:193
void numaDestroy(NUMA **pna)
numaDestroy()
Definition: numabasic.c:357
l_float32 * numaGetFArray(NUMA *na, l_int32 copyflag)
numaGetFArray()
Definition: numabasic.c:850
l_ok numaGetMax(NUMA *na, l_float32 *pmaxval, l_int32 *pimaxloc)
numaGetMax()
Definition: numafunc1.c:485
l_ok pixCountTextColumns(PIX *pixs, l_float32 deltafract, l_float32 peakfract, l_float32 clipfract, l_int32 *pncols, PIXA *pixadb)
pixCountTextColumns()
Definition: pageseg.c:1209
l_ok convertFilesToPdf(const char *dirname, const char *substr, l_int32 res, l_float32 scalefactor, l_int32 type, l_int32 quality, const char *title, const char *fileout)
convertFilesToPdf()
Definition: pdfio1.c:252
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 * pixCreateTemplate(const PIX *pixs)
pixCreateTemplate()
Definition: pix1.c:380
PIX * pixClone(PIX *pixs)
pixClone()
Definition: pix1.c:582
void ** pixGetLinePtrs(PIX *pix, l_int32 *psize)
pixGetLinePtrs()
Definition: pix1.c:1844
l_ok pixSetAllGray(PIX *pix, l_int32 grayval)
pixSetAllGray()
Definition: pix2.c:839
@ L_COPY
Definition: pix.h:505
@ L_CLONE
Definition: pix.h:506
@ L_NOCOPY
Definition: pix.h:503
@ L_INSERT
Definition: pix.h:504
PIX * pixConvertTo1(PIX *pixs, l_int32 threshold)
pixConvertTo1()
Definition: pixconv.c:2952
PIX * pixConvertTo32(PIX *pixs)
pixConvertTo32()
Definition: pixconv.c:3246
l_ok ptaGetIPt(PTA *pta, l_int32 index, l_int32 *px, l_int32 *py)
ptaGetIPt()
Definition: ptabasic.c:527
l_ok ptaAddPt(PTA *pta, l_float32 x, l_float32 y)
ptaAddPt()
Definition: ptabasic.c:328
PTA * ptaCreate(l_int32 n)
ptaCreate()
Definition: ptabasic.c:120
void ptaDestroy(PTA **ppta)
ptaDestroy()
Definition: ptabasic.c:191
struct FPix * fullvdispar
Definition: dewarp.h:158
l_int32 skip_horiz
Definition: dewarp.h:185
struct L_Dewarpa * dewa
Definition: dewarp.h:153
l_int32 hasref
Definition: dewarp.h:178
l_int32 h
Definition: dewarp.h:164
l_int32 sampling
Definition: dewarp.h:166
l_int32 hsuccess
Definition: dewarp.h:181
l_int32 vvalid
Definition: dewarp.h:183
l_int32 w
Definition: dewarp.h:163
l_int32 redfactor
Definition: dewarp.h:167
struct Pix * pixs
Definition: dewarp.h:154
l_int32 nx
Definition: dewarp.h:176
l_int32 hvalid
Definition: dewarp.h:184
l_int32 refpage
Definition: dewarp.h:179
struct FPix * fullhdispar
Definition: dewarp.h:159
struct FPix * sampvdispar
Definition: dewarp.h:155
struct Numa * nacurves
Definition: dewarp.h:162
l_int32 ny
Definition: dewarp.h:177
struct Numa * namidys
Definition: dewarp.h:161
struct FPix * samphdispar
Definition: dewarp.h:156
l_int32 maxpage
Definition: dewarp.h:116
l_int32 check_columns
Definition: dewarp.h:141
l_int32 modelsready
Definition: dewarp.h:144
l_int32 useboth
Definition: dewarp.h:139
void lept_stderr(const char *fmt,...)
lept_stderr()
Definition: utils1.c:306
l_int32 lept_rmdir(const char *subdir)
lept_rmdir()
Definition: utils2.c:2213
l_int32 lept_mkdir(const char *subdir)
lept_mkdir()
Definition: utils2.c:2138