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
61static 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);
64static PIX *pixApplyVertDisparity(L_DEWARP *dew, PIX *pixs, l_int32 grayin);
65static PIX * pixApplyHorizDisparity(L_DEWARP *dew, PIX *pixs, l_int32 grayin);
66static BOXA *boxaApplyDisparity(L_DEWARP *dew, BOXA *boxa, l_int32 direction,
67 l_int32 mapdir);
68
69/*----------------------------------------------------------------------*
70 * Apply warping disparity array to pixa *
71 *----------------------------------------------------------------------*/
115l_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{
125L_DEWARP *dew1, *dew;
126PIX *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
215static 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{
224l_int32 ncols, debug;
225L_DEWARP *dew1, *dew2;
226PIX *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)
247 dewarpaInsertRefModels(dewa, 0, debug);
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
309static PIX *
311 PIX *pixs,
312 l_int32 grayin)
313{
314l_int32 i, j, w, h, d, fw, fh, wpld, wplf, isrc, val8;
315l_uint32 *datad, *lined;
316l_float32 *dataf, *linef;
317void **lineptrs;
318FPIX *fpix;
319PIX *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
419static PIX *
421 PIX *pixs,
422 l_int32 grayin)
423{
424l_int32 i, j, w, h, d, fw, fh, wpls, wpld, wplf, jsrc, val8;
425l_uint32 *datas, *lines, *datad, *lined;
426l_float32 *dataf, *linef;
427FPIX *fpix;
428PIX *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 *----------------------------------------------------------------------*/
538l_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{
549l_int32 debug_out;
550L_DEWARP *dew1, *dew;
551BOXA *boxav, *boxah;
552PIX *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
644static BOXA *
646 BOXA *boxa,
647 l_int32 direction,
648 l_int32 mapdir)
649{
650l_int32 x, y, w, h, ib, ip, nbox, wpl;
651l_float32 xn, yn;
652l_float32 *data, *line;
653BOX *boxs, *boxd;
654BOXA *boxad;
655FPIX *fpix;
656PTA *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 *----------------------------------------------------------------------*/
730l_ok
732{
733L_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
786l_ok
788 PIX *pix,
789 l_int32 x,
790 l_int32 y)
791{
792l_int32 width, height, fw, fh, deltaw, deltah, redfactor;
793FPIX *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)
817 }
818 if (dew->fullhdispar) {
819 fpixGetDimensions(dew->fullhdispar, &fw, &fh);
820 if (width > fw || height > fw)
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 *----------------------------------------------------------------------*/
900static FPIX *
901fpixSampledDisparity(FPIX *fpixs,
902 l_int32 sampling)
903{
904l_int32 w, h, wd, hd, i, j, is, js;
905l_float32 val;
906FPIX *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
935static const l_float32 DefaultSlopeFactor = 0.1; /* just a guess; fix it */
936
960static FPIX *
961fpixExtraHorizDisparity(FPIX *fpixv,
962 l_float32 factor,
963 l_int32 *pxwid)
964{
965l_int32 w, h, i, j, fw, wpl, maxloc;
966l_float32 val1, val2, vdisp, vdisp0, maxval;
967l_float32 *data, *line, *fadiff;
968NUMA *nadiff;
969FPIX *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
#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
BOX * boxaGetBox(BOXA *boxa, l_int32 index, l_int32 accessflag)
boxaGetBox()
Definition: boxbasic.c:779
BOXA * boxaCopy(BOXA *boxa, l_int32 copyflag)
boxaCopy()
Definition: boxbasic.c:537
void boxDestroy(BOX **pbox)
boxDestroy()
Definition: boxbasic.c:282
l_int32 boxaGetCount(BOXA *boxa)
boxaGetCount()
Definition: boxbasic.c:734
BOXA * boxaCreate(l_int32 n)
boxaCreate()
Definition: boxbasic.c:502
l_ok boxaAddBox(BOXA *boxa, BOX *box, l_int32 copyflag)
boxaAddBox()
Definition: boxbasic.c:620
void boxaDestroy(BOXA **pboxa)
boxaDestroy()
Definition: boxbasic.c:583
PTA * boxConvertToPta(BOX *box, l_int32 ncorners)
boxConvertToPta()
Definition: boxfunc4.c:861
BOX * ptaConvertToBox(PTA *pta)
ptaConvertToBox()
Definition: boxfunc4.c:903
L_DEWARP * dewarpaGetDewarp(L_DEWARPA *dewa, l_int32 index)
dewarpaGetDewarp()
Definition: dewarp1.c:911
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
static PIX * pixApplyHorizDisparity(L_DEWARP *dew, PIX *pixs, l_int32 grayin)
pixApplyHorizDisparity()
Definition: dewarp3.c:420
static PIX * pixApplyVertDisparity(L_DEWARP *dew, PIX *pixs, l_int32 grayin)
pixApplyVertDisparity()
Definition: dewarp3.c:310
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:645
l_ok dewarpMinimize(L_DEWARP *dew)
dewarpMinimize()
Definition: dewarp3.c:731
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
l_ok dewarpPopulateFullRes(L_DEWARP *dew, PIX *pix, l_int32 x, l_int32 y)
dewarpPopulateFullRes()
Definition: dewarp3.c:787
l_ok dewarpDebug(L_DEWARP *dew, const char *subdirs, l_int32 index)
dewarpDebug()
Definition: dewarp4.c:1015
l_ok dewarpaInsertRefModels(L_DEWARPA *dewa, l_int32 notests, l_int32 debug)
dewarpaInsertRefModels()
Definition: dewarp4.c:454
FPIX * fpixCreate(l_int32 width, l_int32 height)
fpixCreate()
Definition: fpix1.c:156
l_float32 * fpixGetData(FPIX *fpix)
fpixGetData()
Definition: fpix1.c:519
l_ok fpixGetDimensions(FPIX *fpix, l_int32 *pw, l_int32 *ph)
fpixGetDimensions()
Definition: fpix1.c:329
FPIX * fpixCopy(FPIX *fpixs)
fpixCopy()
Definition: fpix1.c:255
l_int32 fpixGetWpl(FPIX *fpix)
fpixGetWpl()
Definition: fpix1.c:376
l_ok fpixSetPixel(FPIX *fpix, l_int32 x, l_int32 y, l_float32 val)
fpixSetPixel()
Definition: fpix1.c:600
void fpixDestroy(FPIX **pfpix)
fpixDestroy()
Definition: fpix1.c:292
l_ok fpixGetPixel(FPIX *fpix, l_int32 x, l_int32 y, l_float32 *pval)
fpixGetPixel()
Definition: fpix1.c:563
l_ok fpixAddMultConstant(FPIX *fpix, l_float32 addc, l_float32 multc)
fpixAddMultConstant()
Definition: fpix2.c:1164
FPIX * fpixScaleByInteger(FPIX *fpixs, l_int32 factor)
fpixScaleByInteger()
Definition: fpix2.c:921
FPIX * fpixAddSlopeBorder(FPIX *fpixs, l_int32 left, l_int32 right, l_int32 top, l_int32 bot)
fpixAddSlopeBorder()
Definition: fpix2.c:1567
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 numaAddNumber(NUMA *na, l_float32 val)
numaAddNumber()
Definition: numabasic.c:478
void numaDestroy(NUMA **pna)
numaDestroy()
Definition: numabasic.c:366
l_float32 * numaGetFArray(NUMA *na, l_int32 copyflag)
numaGetFArray()
Definition: numabasic.c:892
NUMA * numaCreate(l_int32 n)
numaCreate()
Definition: numabasic.c:194
l_ok numaGetMax(NUMA *na, l_float32 *pmaxval, l_int32 *pimaxloc)
numaGetMax()
Definition: numafunc1.c:496
l_ok pixCountTextColumns(PIX *pixs, l_float32 deltafract, l_float32 peakfract, l_float32 clipfract, l_int32 *pncols, PIXA *pixadb)
pixCountTextColumns()
Definition: pageseg.c:1226
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
void ** pixGetLinePtrs(PIX *pix, l_int32 *psize)
pixGetLinePtrs()
Definition: pix1.c:1949
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:621
l_ok pixGetDimensions(const PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
Definition: pix1.c:1113
PIX * pixClone(PIX *pixs)
pixClone()
Definition: pix1.c:593
PIX * pixCreateTemplate(const PIX *pixs)
pixCreateTemplate()
Definition: pix1.c:383
l_uint32 * pixGetData(PIX *pix)
pixGetData()
Definition: pix1.c:1763
l_ok pixSetAllGray(PIX *pix, l_int32 grayval)
pixSetAllGray()
Definition: pix2.c:859
@ L_COPY
Definition: pix.h:712
@ L_CLONE
Definition: pix.h:713
@ L_NOCOPY
Definition: pix.h:710
@ L_INSERT
Definition: pix.h:711
PIX * pixConvertTo32(PIX *pixs)
pixConvertTo32()
Definition: pixconv.c:3332
PIX * pixConvertTo1(PIX *pixs, l_int32 threshold)
pixConvertTo1()
Definition: pixconv.c:3026
l_ok ptaGetIPt(PTA *pta, l_int32 index, l_int32 *px, l_int32 *py)
ptaGetIPt()
Definition: ptabasic.c:578
PTA * ptaCreate(l_int32 n)
ptaCreate()
Definition: ptabasic.c:120
l_ok ptaAddPt(PTA *pta, l_float32 x, l_float32 y)
ptaAddPt()
Definition: ptabasic.c:343
void ptaDestroy(PTA **ppta)
ptaDestroy()
Definition: ptabasic.c:195
Definition: pix.h:481
Definition: pix.h:492
Definition: pix.h:579
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
Definition: array.h:71
Definition: pix.h:139
Definition: pix.h:517
void lept_stderr(const char *fmt,...)
lept_stderr()
Definition: utils1.c:306
l_int32 lept_rmdir(const char *subdir)
lept_rmdir()
Definition: utils2.c:2295
l_int32 lept_mkdir(const char *subdir)
lept_mkdir()
Definition: utils2.c:2218