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