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