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