Leptonica  1.83.1
Image processing and image analysis suite
dewarp1.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 
412 #ifdef HAVE_CONFIG_H
413 #include <config_auto.h>
414 #endif /* HAVE_CONFIG_H */
415 
416 #include <math.h>
417 #include "allheaders.h"
418 
419 static l_int32 dewarpaExtendArraysToSize(L_DEWARPA *dewa, l_int32 size);
420 
421  /* Parameter values used in dewarpaCreate() */
422 static const l_int32 InitialPtrArraySize = 20; /* n'import quoi */
423 static const l_int32 MaxPtrArraySize = 10000;
424 static const l_int32 DefaultArraySampling = 30;
425 static const l_int32 MinArraySampling = 8;
426 static const l_int32 DefaultMinLines = 15;
427 static const l_int32 MinMinLines = 4;
428 static const l_int32 DefaultMaxRefDist = 16;
429 static const l_int32 DefaultUseBoth = TRUE;
430 static const l_int32 DefaultCheckColumns = TRUE;
431 
432  /* Parameter values used in dewarpaSetCurvatures() */
433 static const l_int32 DefaultMaxLineCurv = 150;
434 static const l_int32 DefaultMinDiffLineCurv = 0;
435 static const l_int32 DefaultMaxDiffLineCurv = 170;
436 static const l_int32 DefaultMaxEdgeCurv = 50;
437 static const l_int32 DefaultMaxDiffEdgeCurv = 40;
438 static const l_int32 DefaultMaxEdgeSlope = 80;
439 
440 /*----------------------------------------------------------------------*
441  * Create/destroy Dewarp *
442  *----------------------------------------------------------------------*/
458 L_DEWARP *
460  l_int32 pageno)
461 {
462 L_DEWARP *dew;
463 
464  if (!pixs)
465  return (L_DEWARP *)ERROR_PTR("pixs not defined", __func__, NULL);
466  if (pixGetDepth(pixs) != 1)
467  return (L_DEWARP *)ERROR_PTR("pixs not 1 bpp", __func__, NULL);
468 
469  dew = (L_DEWARP *)LEPT_CALLOC(1, sizeof(L_DEWARP));
470  dew->pixs = pixClone(pixs);
471  dew->pageno = pageno;
472  dew->w = pixGetWidth(pixs);
473  dew->h = pixGetHeight(pixs);
474  return dew;
475 }
476 
477 
495 L_DEWARP *
496 dewarpCreateRef(l_int32 pageno,
497  l_int32 refpage)
498 {
499 L_DEWARP *dew;
500 
501  dew = (L_DEWARP *)LEPT_CALLOC(1, sizeof(L_DEWARP));
502  dew->pageno = pageno;
503  dew->hasref = 1;
504  dew->refpage = refpage;
505  return dew;
506 }
507 
508 
515 void
517 {
518 L_DEWARP *dew;
519 
520  if (pdew == NULL) {
521  L_WARNING("ptr address is null!\n", __func__);
522  return;
523  }
524  if ((dew = *pdew) == NULL)
525  return;
526 
527  pixDestroy(&dew->pixs);
528  fpixDestroy(&dew->sampvdispar);
529  fpixDestroy(&dew->samphdispar);
530  fpixDestroy(&dew->sampydispar);
531  fpixDestroy(&dew->fullvdispar);
532  fpixDestroy(&dew->fullhdispar);
533  fpixDestroy(&dew->fullydispar);
534  numaDestroy(&dew->namidys);
535  numaDestroy(&dew->nacurves);
536  LEPT_FREE(dew);
537  *pdew = NULL;
538 }
539 
540 
541 /*----------------------------------------------------------------------*
542  * Create/destroy Dewarpa *
543  *----------------------------------------------------------------------*/
575 L_DEWARPA *
576 dewarpaCreate(l_int32 nptrs,
577  l_int32 sampling,
578  l_int32 redfactor,
579  l_int32 minlines,
580  l_int32 maxdist)
581 {
582 L_DEWARPA *dewa;
583 
584  if (nptrs <= 0)
585  nptrs = InitialPtrArraySize;
586  if (nptrs > MaxPtrArraySize)
587  return (L_DEWARPA *)ERROR_PTR("too many pages", __func__, NULL);
588  if (redfactor != 1 && redfactor != 2)
589  return (L_DEWARPA *)ERROR_PTR("redfactor not in {1,2}",
590  __func__, NULL);
591  if (sampling == 0) {
592  sampling = DefaultArraySampling;
593  } else if (sampling < MinArraySampling) {
594  L_WARNING("sampling too small; setting to %d\n", __func__,
595  MinArraySampling);
596  sampling = MinArraySampling;
597  }
598  if (minlines == 0) {
599  minlines = DefaultMinLines;
600  } else if (minlines < MinMinLines) {
601  L_WARNING("minlines too small; setting to %d\n", __func__,
602  MinMinLines);
603  minlines = DefaultMinLines;
604  }
605  if (maxdist < 0)
606  maxdist = DefaultMaxRefDist;
607 
608  dewa = (L_DEWARPA *)LEPT_CALLOC(1, sizeof(L_DEWARPA));
609  dewa->dewarp = (L_DEWARP **)LEPT_CALLOC(nptrs, sizeof(L_DEWARPA *));
610  dewa->dewarpcache = (L_DEWARP **)LEPT_CALLOC(nptrs, sizeof(L_DEWARPA *));
611  if (!dewa->dewarp || !dewa->dewarpcache) {
612  dewarpaDestroy(&dewa);
613  return (L_DEWARPA *)ERROR_PTR("dewarp ptrs not made", __func__, NULL);
614  }
615  dewa->nalloc = nptrs;
616  dewa->sampling = sampling;
617  dewa->redfactor = redfactor;
618  dewa->minlines = minlines;
619  dewa->maxdist = maxdist;
620  dewa->max_linecurv = DefaultMaxLineCurv;
621  dewa->min_diff_linecurv = DefaultMinDiffLineCurv;
622  dewa->max_diff_linecurv = DefaultMaxDiffLineCurv;
623  dewa->max_edgeslope = DefaultMaxEdgeSlope;
624  dewa->max_edgecurv = DefaultMaxEdgeCurv;
625  dewa->max_diff_edgecurv = DefaultMaxDiffEdgeCurv;
626  dewa->check_columns = DefaultCheckColumns;
627  dewa->useboth = DefaultUseBoth;
628  return dewa;
629 }
630 
631 
662 L_DEWARPA *
664  l_int32 useboth,
665  l_int32 sampling,
666  l_int32 minlines,
667  l_int32 maxdist)
668 {
669 l_int32 i, nptrs, pageno;
670 L_DEWARP *dew;
671 L_DEWARPA *dewa;
672 PIX *pixt;
673 
674  if (!pixac)
675  return (L_DEWARPA *)ERROR_PTR("pixac not defined", __func__, NULL);
676 
677  nptrs = pixacompGetCount(pixac);
678  if ((dewa = dewarpaCreate(pixacompGetOffset(pixac) + nptrs,
679  sampling, 1, minlines, maxdist)) == NULL)
680  return (L_DEWARPA *)ERROR_PTR("dewa not made", __func__, NULL);
681  dewarpaUseBothArrays(dewa, useboth);
682 
683  for (i = 0; i < nptrs; i++) {
684  pageno = pixacompGetOffset(pixac) + i; /* index into pixacomp */
685  pixt = pixacompGetPix(pixac, pageno);
686  if (pixt && (pixGetWidth(pixt) > 1)) {
687  dew = dewarpCreate(pixt, pageno);
688  pixDestroy(&pixt);
689  if (!dew) {
690  ERROR_INT("unable to make dew!", __func__, 1);
691  continue;
692  }
693 
694  /* Insert into dewa for this page */
695  dewarpaInsertDewarp(dewa, dew);
696 
697  /* Build disparity arrays for this page */
698  dewarpBuildPageModel(dew, NULL);
699  if (!dew->vsuccess) { /* will need to use model from nearby page */
700  dewarpaDestroyDewarp(dewa, pageno);
701  L_ERROR("unable to build model for page %d\n", __func__, i);
702  continue;
703  }
704  /* Remove all extraneous data */
705  dewarpMinimize(dew);
706  }
707  pixDestroy(&pixt);
708  }
709  dewarpaInsertRefModels(dewa, 0, 0);
710 
711  return dewa;
712 }
713 
714 
721 void
723 {
724 l_int32 i;
725 L_DEWARP *dew;
726 L_DEWARPA *dewa;
727 
728  if (pdewa == NULL) {
729  L_WARNING("ptr address is null!\n", __func__);
730  return;
731  }
732  if ((dewa = *pdewa) == NULL)
733  return;
734 
735  for (i = 0; i < dewa->nalloc; i++) {
736  if ((dew = dewa->dewarp[i]) != NULL)
737  dewarpDestroy(&dew);
738  if ((dew = dewa->dewarpcache[i]) != NULL)
739  dewarpDestroy(&dew);
740  }
741  numaDestroy(&dewa->namodels);
742  numaDestroy(&dewa->napages);
743 
744  LEPT_FREE(dewa->dewarp);
745  LEPT_FREE(dewa->dewarpcache);
746  LEPT_FREE(dewa);
747  *pdewa = NULL;
748 }
749 
750 
758 l_ok
760  l_int32 pageno)
761 {
762 L_DEWARP *dew;
763 
764  if (!dewa)
765  return ERROR_INT("dewa or dew not defined", __func__, 1);
766  if (pageno < 0 || pageno > dewa->maxpage)
767  return ERROR_INT("page out of bounds", __func__, 1);
768  if ((dew = dewa->dewarp[pageno]) == NULL)
769  return ERROR_INT("dew not defined", __func__, 1);
770 
771  dewarpDestroy(&dew);
772  dewa->dewarp[pageno] = NULL;
773  return 0;
774 }
775 
776 
777 /*----------------------------------------------------------------------*
778  * Dewarpa insertion/extraction *
779  *----------------------------------------------------------------------*/
799 l_ok
801  L_DEWARP *dew)
802 {
803 l_int32 pageno, n, newsize;
804 L_DEWARP *prevdew;
805 
806  if (!dewa)
807  return ERROR_INT("dewa not defined", __func__, 1);
808  if (!dew)
809  return ERROR_INT("dew not defined", __func__, 1);
810 
811  dew->dewa = dewa;
812  pageno = dew->pageno;
813  if (pageno > MaxPtrArraySize)
814  return ERROR_INT("too many pages", __func__, 1);
815  if (pageno > dewa->maxpage)
816  dewa->maxpage = pageno;
817  dewa->modelsready = 0; /* force re-evaluation at application time */
818 
819  /* Extend ptr array if necessary */
820  n = dewa->nalloc;
821  newsize = n;
822  if (pageno >= 2 * n)
823  newsize = 2 * pageno;
824  else if (pageno >= n)
825  newsize = 2 * n;
826  if (newsize > n) {
827  if (dewarpaExtendArraysToSize(dewa, newsize))
828  return ERROR_INT("extension failed", __func__, 1);
829  }
830 
831  if ((prevdew = dewarpaGetDewarp(dewa, pageno)) != NULL)
832  dewarpDestroy(&prevdew);
833  dewa->dewarp[pageno] = dew;
834 
835  dew->sampling = dewa->sampling;
836  dew->redfactor = dewa->redfactor;
837  dew->minlines = dewa->minlines;
838 
839  /* Get the dimensions of the sampled array. This will be
840  * stored in an fpix, and the input resolution version is
841  * guaranteed to be larger than pixs. However, if you
842  * want to apply the disparity to an image with a width
843  * w > nx * s - 2 * s + 2
844  * you will need to extend the input res fpix.
845  * And similarly for h. */
846  dew->nx = (dew->w + 2 * dew->sampling - 2) / dew->sampling;
847  dew->ny = (dew->h + 2 * dew->sampling - 2) / dew->sampling;
848  return 0;
849 }
850 
851 
864 static l_int32
866  l_int32 size)
867 {
868  if (!dewa)
869  return ERROR_INT("dewa not defined", __func__, 1);
870 
871  if (size > dewa->nalloc) {
872  if ((dewa->dewarp = (L_DEWARP **)reallocNew((void **)&dewa->dewarp,
873  sizeof(L_DEWARP *) * dewa->nalloc,
874  size * sizeof(L_DEWARP *))) == NULL)
875  return ERROR_INT("new ptr array not returned", __func__, 1);
876  if ((dewa->dewarpcache =
877  (L_DEWARP **)reallocNew((void **)&dewa->dewarpcache,
878  sizeof(L_DEWARP *) * dewa->nalloc,
879  size * sizeof(L_DEWARP *))) == NULL)
880  return ERROR_INT("new ptr cache array not returned", __func__, 1);
881  dewa->nalloc = size;
882  }
883  return 0;
884 }
885 
886 
894 L_DEWARP *
896  l_int32 index)
897 {
898  if (!dewa)
899  return (L_DEWARP *)ERROR_PTR("dewa not defined", __func__, NULL);
900  if (index < 0 || index > dewa->maxpage) {
901  L_ERROR("index = %d is invalid; max index = %d\n",
902  __func__, index, dewa->maxpage);
903  return NULL;
904  }
905 
906  return dewa->dewarp[index];
907 }
908 
909 
910 /*----------------------------------------------------------------------*
911  * Setting parameters to control rendering from the model *
912  *----------------------------------------------------------------------*/
961 l_ok
963  l_int32 max_linecurv,
964  l_int32 min_diff_linecurv,
965  l_int32 max_diff_linecurv,
966  l_int32 max_edgecurv,
967  l_int32 max_diff_edgecurv,
968  l_int32 max_edgeslope)
969 {
970  if (!dewa)
971  return ERROR_INT("dewa not defined", __func__, 1);
972 
973  if (max_linecurv == -1)
974  dewa->max_linecurv = DefaultMaxLineCurv;
975  else
976  dewa->max_linecurv = L_ABS(max_linecurv);
977 
978  if (min_diff_linecurv == -1)
979  dewa->min_diff_linecurv = DefaultMinDiffLineCurv;
980  else
981  dewa->min_diff_linecurv = L_ABS(min_diff_linecurv);
982 
983  if (max_diff_linecurv == -1)
984  dewa->max_diff_linecurv = DefaultMaxDiffLineCurv;
985  else
986  dewa->max_diff_linecurv = L_ABS(max_diff_linecurv);
987 
988  if (max_edgecurv == -1)
989  dewa->max_edgecurv = DefaultMaxEdgeCurv;
990  else
991  dewa->max_edgecurv = L_ABS(max_edgecurv);
992 
993  if (max_diff_edgecurv == -1)
994  dewa->max_diff_edgecurv = DefaultMaxDiffEdgeCurv;
995  else
996  dewa->max_diff_edgecurv = L_ABS(max_diff_edgecurv);
997 
998  if (max_edgeslope == -1)
999  dewa->max_edgeslope = DefaultMaxEdgeSlope;
1000  else
1001  dewa->max_edgeslope = L_ABS(max_edgeslope);
1002 
1003  dewa->modelsready = 0; /* force validation */
1004  return 0;
1005 }
1006 
1007 
1023 l_ok
1025  l_int32 useboth)
1026 {
1027  if (!dewa)
1028  return ERROR_INT("dewa not defined", __func__, 1);
1029 
1030  dewa->useboth = useboth;
1031  dewa->modelsready = 0; /* force validation */
1032  return 0;
1033 }
1034 
1035 
1060 l_ok
1062  l_int32 check_columns)
1063 {
1064  if (!dewa)
1065  return ERROR_INT("dewa not defined", __func__, 1);
1066 
1067  dewa->check_columns = check_columns;
1068  return 0;
1069 }
1070 
1071 
1084 l_ok
1086  l_int32 maxdist)
1087 {
1088  if (!dewa)
1089  return ERROR_INT("dewa not defined", __func__, 1);
1090 
1091  dewa->maxdist = maxdist;
1092  dewa->modelsready = 0; /* force validation */
1093  return 0;
1094 }
1095 
1096 
1097 /*----------------------------------------------------------------------*
1098  * Dewarp serialized I/O *
1099  *----------------------------------------------------------------------*/
1106 L_DEWARP *
1107 dewarpRead(const char *filename)
1108 {
1109 FILE *fp;
1110 L_DEWARP *dew;
1111 
1112  if (!filename)
1113  return (L_DEWARP *)ERROR_PTR("filename not defined", __func__, NULL);
1114  if ((fp = fopenReadStream(filename)) == NULL)
1115  return (L_DEWARP *)ERROR_PTR("stream not opened", __func__, NULL);
1116 
1117  if ((dew = dewarpReadStream(fp)) == NULL) {
1118  fclose(fp);
1119  return (L_DEWARP *)ERROR_PTR("dew not read", __func__, NULL);
1120  }
1121 
1122  fclose(fp);
1123  return dew;
1124 }
1125 
1126 
1144 L_DEWARP *
1146 {
1147 l_int32 version, sampling, redfactor, minlines, pageno, hasref, refpage;
1148 l_int32 w, h, nx, ny, vdispar, hdispar, nlines;
1149 l_int32 mincurv, maxcurv, leftslope, rightslope, leftcurv, rightcurv;
1150 L_DEWARP *dew;
1151 FPIX *fpixv, *fpixh;
1152 
1153  if (!fp)
1154  return (L_DEWARP *)ERROR_PTR("stream not defined", __func__, NULL);
1155 
1156  if (fscanf(fp, "\nDewarp Version %d\n", &version) != 1)
1157  return (L_DEWARP *)ERROR_PTR("not a dewarp file", __func__, NULL);
1158  if (version != DEWARP_VERSION_NUMBER)
1159  return (L_DEWARP *)ERROR_PTR("invalid dewarp version", __func__, NULL);
1160  if (fscanf(fp, "pageno = %d\n", &pageno) != 1)
1161  return (L_DEWARP *)ERROR_PTR("read fail for pageno", __func__, NULL);
1162  if (fscanf(fp, "hasref = %d, refpage = %d\n", &hasref, &refpage) != 2)
1163  return (L_DEWARP *)ERROR_PTR("read fail for hasref, refpage",
1164  __func__, NULL);
1165  if (fscanf(fp, "sampling = %d, redfactor = %d\n", &sampling, &redfactor)
1166  != 2)
1167  return (L_DEWARP *)ERROR_PTR("read fail for sampling/redfactor",
1168  __func__, NULL);
1169  if (fscanf(fp, "nlines = %d, minlines = %d\n", &nlines, &minlines) != 2)
1170  return (L_DEWARP *)ERROR_PTR("read fail for nlines/minlines",
1171  __func__, NULL);
1172  if (fscanf(fp, "w = %d, h = %d\n", &w, &h) != 2)
1173  return (L_DEWARP *)ERROR_PTR("read fail for w, h", __func__, NULL);
1174  if (fscanf(fp, "nx = %d, ny = %d\n", &nx, &ny) != 2)
1175  return (L_DEWARP *)ERROR_PTR("read fail for nx, ny", __func__, NULL);
1176  if (fscanf(fp, "vert_dispar = %d, horiz_dispar = %d\n", &vdispar, &hdispar)
1177  != 2)
1178  return (L_DEWARP *)ERROR_PTR("read fail for flags", __func__, NULL);
1179  if (vdispar) {
1180  if (fscanf(fp, "min line curvature = %d, max line curvature = %d\n",
1181  &mincurv, &maxcurv) != 2)
1182  return (L_DEWARP *)ERROR_PTR("read fail for mincurv & maxcurv",
1183  __func__, NULL);
1184  }
1185  if (hdispar) {
1186  if (fscanf(fp, "left edge slope = %d, right edge slope = %d\n",
1187  &leftslope, &rightslope) != 2)
1188  return (L_DEWARP *)ERROR_PTR("read fail for leftslope & rightslope",
1189  __func__, NULL);
1190  if (fscanf(fp, "left edge curvature = %d, right edge curvature = %d\n",
1191  &leftcurv, &rightcurv) != 2)
1192  return (L_DEWARP *)ERROR_PTR("read fail for leftcurv & rightcurv",
1193  __func__, NULL);
1194  }
1195  if (vdispar) {
1196  if ((fpixv = fpixReadStream(fp)) == NULL)
1197  return (L_DEWARP *)ERROR_PTR("read fail for vdispar",
1198  __func__, NULL);
1199  }
1200  if (hdispar) {
1201  if ((fpixh = fpixReadStream(fp)) == NULL)
1202  return (L_DEWARP *)ERROR_PTR("read fail for hdispar",
1203  __func__, NULL);
1204  }
1205  getc(fp);
1206 
1207  dew = (L_DEWARP *)LEPT_CALLOC(1, sizeof(L_DEWARP));
1208  dew->w = w;
1209  dew->h = h;
1210  dew->pageno = pageno;
1211  dew->sampling = sampling;
1212  dew->redfactor = redfactor;
1213  dew->minlines = minlines;
1214  dew->nlines = nlines;
1215  dew->hasref = hasref;
1216  dew->refpage = refpage;
1217  if (hasref == 0) /* any dew without a ref has an actual model */
1218  dew->vsuccess = 1;
1219  dew->nx = nx;
1220  dew->ny = ny;
1221  if (vdispar) {
1222  dew->mincurv = mincurv;
1223  dew->maxcurv = maxcurv;
1224  dew->vsuccess = 1;
1225  dew->sampvdispar = fpixv;
1226  }
1227  if (hdispar) {
1228  dew->leftslope = leftslope;
1229  dew->rightslope = rightslope;
1230  dew->leftcurv = leftcurv;
1231  dew->rightcurv = rightcurv;
1232  dew->hsuccess = 1;
1233  dew->samphdispar = fpixh;
1234  }
1235 
1236  return dew;
1237 }
1238 
1239 
1247 L_DEWARP *
1248 dewarpReadMem(const l_uint8 *data,
1249  size_t size)
1250 {
1251 FILE *fp;
1252 L_DEWARP *dew;
1253 
1254  if (!data)
1255  return (L_DEWARP *)ERROR_PTR("data not defined", __func__, NULL);
1256  if ((fp = fopenReadFromMemory(data, size)) == NULL)
1257  return (L_DEWARP *)ERROR_PTR("stream not opened", __func__, NULL);
1258 
1259  dew = dewarpReadStream(fp);
1260  fclose(fp);
1261  if (!dew) L_ERROR("dew not read\n", __func__);
1262  return dew;
1263 }
1264 
1265 
1273 l_ok
1274 dewarpWrite(const char *filename,
1275  L_DEWARP *dew)
1276 {
1277 l_int32 ret;
1278 FILE *fp;
1279 
1280  if (!filename)
1281  return ERROR_INT("filename not defined", __func__, 1);
1282  if (!dew)
1283  return ERROR_INT("dew not defined", __func__, 1);
1284 
1285  if ((fp = fopenWriteStream(filename, "wb")) == NULL)
1286  return ERROR_INT("stream not opened", __func__, 1);
1287  ret = dewarpWriteStream(fp, dew);
1288  fclose(fp);
1289  if (ret)
1290  return ERROR_INT("dew not written to stream", __func__, 1);
1291  return 0;
1292 }
1293 
1294 
1309 l_ok
1311  L_DEWARP *dew)
1312 {
1313 l_int32 vdispar, hdispar;
1314 
1315  if (!fp)
1316  return ERROR_INT("stream not defined", __func__, 1);
1317  if (!dew)
1318  return ERROR_INT("dew not defined", __func__, 1);
1319 
1320  fprintf(fp, "\nDewarp Version %d\n", DEWARP_VERSION_NUMBER);
1321  fprintf(fp, "pageno = %d\n", dew->pageno);
1322  fprintf(fp, "hasref = %d, refpage = %d\n", dew->hasref, dew->refpage);
1323  fprintf(fp, "sampling = %d, redfactor = %d\n",
1324  dew->sampling, dew->redfactor);
1325  fprintf(fp, "nlines = %d, minlines = %d\n", dew->nlines, dew->minlines);
1326  fprintf(fp, "w = %d, h = %d\n", dew->w, dew->h);
1327  fprintf(fp, "nx = %d, ny = %d\n", dew->nx, dew->ny);
1328  vdispar = (dew->sampvdispar) ? 1 : 0;
1329  hdispar = (dew->samphdispar) ? 1 : 0;
1330  fprintf(fp, "vert_dispar = %d, horiz_dispar = %d\n", vdispar, hdispar);
1331  if (vdispar)
1332  fprintf(fp, "min line curvature = %d, max line curvature = %d\n",
1333  dew->mincurv, dew->maxcurv);
1334  if (hdispar) {
1335  fprintf(fp, "left edge slope = %d, right edge slope = %d\n",
1336  dew->leftslope, dew->rightslope);
1337  fprintf(fp, "left edge curvature = %d, right edge curvature = %d\n",
1338  dew->leftcurv, dew->rightcurv);
1339  }
1340  if (vdispar) fpixWriteStream(fp, dew->sampvdispar);
1341  if (hdispar) fpixWriteStream(fp, dew->samphdispar);
1342  fprintf(fp, "\n");
1343 
1344  if (!vdispar)
1345  L_WARNING("no disparity arrays!\n", __func__);
1346  return 0;
1347 }
1348 
1349 
1363 l_ok
1364 dewarpWriteMem(l_uint8 **pdata,
1365  size_t *psize,
1366  L_DEWARP *dew)
1367 {
1368 l_int32 ret;
1369 FILE *fp;
1370 
1371  if (pdata) *pdata = NULL;
1372  if (psize) *psize = 0;
1373  if (!pdata)
1374  return ERROR_INT("&data not defined", __func__, 1);
1375  if (!psize)
1376  return ERROR_INT("&size not defined", __func__, 1);
1377  if (!dew)
1378  return ERROR_INT("dew not defined", __func__, 1);
1379 
1380 #if HAVE_FMEMOPEN
1381  if ((fp = open_memstream((char **)pdata, psize)) == NULL)
1382  return ERROR_INT("stream not opened", __func__, 1);
1383  ret = dewarpWriteStream(fp, dew);
1384  fputc('\0', fp);
1385  fclose(fp);
1386  *psize = *psize - 1;
1387 #else
1388  L_INFO("work-around: writing to a temp file\n", __func__);
1389  #ifdef _WIN32
1390  if ((fp = fopenWriteWinTempfile()) == NULL)
1391  return ERROR_INT("tmpfile stream not opened", __func__, 1);
1392  #else
1393  if ((fp = tmpfile()) == NULL)
1394  return ERROR_INT("tmpfile stream not opened", __func__, 1);
1395  #endif /* _WIN32 */
1396  ret = dewarpWriteStream(fp, dew);
1397  rewind(fp);
1398  *pdata = l_binaryReadStream(fp, psize);
1399  fclose(fp);
1400 #endif /* HAVE_FMEMOPEN */
1401  return ret;
1402 }
1403 
1404 
1405 /*----------------------------------------------------------------------*
1406  * Dewarpa serialized I/O *
1407  *----------------------------------------------------------------------*/
1414 L_DEWARPA *
1415 dewarpaRead(const char *filename)
1416 {
1417 FILE *fp;
1418 L_DEWARPA *dewa;
1419 
1420  if (!filename)
1421  return (L_DEWARPA *)ERROR_PTR("filename not defined", __func__, NULL);
1422  if ((fp = fopenReadStream(filename)) == NULL)
1423  return (L_DEWARPA *)ERROR_PTR("stream not opened", __func__, NULL);
1424 
1425  if ((dewa = dewarpaReadStream(fp)) == NULL) {
1426  fclose(fp);
1427  return (L_DEWARPA *)ERROR_PTR("dewa not read", __func__, NULL);
1428  }
1429 
1430  fclose(fp);
1431  return dewa;
1432 }
1433 
1434 
1449 L_DEWARPA *
1451 {
1452 l_int32 i, version, ndewarp, maxpage;
1453 l_int32 sampling, redfactor, minlines, maxdist, useboth;
1454 l_int32 max_linecurv, min_diff_linecurv, max_diff_linecurv;
1455 l_int32 max_edgeslope, max_edgecurv, max_diff_edgecurv;
1456 L_DEWARP *dew;
1457 L_DEWARPA *dewa;
1458 NUMA *namodels;
1459 
1460  if (!fp)
1461  return (L_DEWARPA *)ERROR_PTR("stream not defined", __func__, NULL);
1462 
1463  if (fscanf(fp, "\nDewarpa Version %d\n", &version) != 1)
1464  return (L_DEWARPA *)ERROR_PTR("not a dewarpa file", __func__, NULL);
1465  if (version != DEWARP_VERSION_NUMBER)
1466  return (L_DEWARPA *)ERROR_PTR("invalid dewarp version", __func__, NULL);
1467 
1468  if (fscanf(fp, "ndewarp = %d, maxpage = %d\n", &ndewarp, &maxpage) != 2)
1469  return (L_DEWARPA *)ERROR_PTR("read fail for maxpage+", __func__, NULL);
1470  if (ndewarp < 1)
1471  return (L_DEWARPA *)ERROR_PTR("pages not >= 1", __func__, NULL);
1472  if (ndewarp > MaxPtrArraySize)
1473  return (L_DEWARPA *)ERROR_PTR("too many pages", __func__, NULL);
1474  if (fscanf(fp,
1475  "sampling = %d, redfactor = %d, minlines = %d, maxdist = %d\n",
1476  &sampling, &redfactor, &minlines, &maxdist) != 4)
1477  return (L_DEWARPA *)ERROR_PTR("read fail for 4 params", __func__, NULL);
1478  if (fscanf(fp,
1479  "max_linecurv = %d, min_diff_linecurv = %d, max_diff_linecurv = %d\n",
1480  &max_linecurv, &min_diff_linecurv, &max_diff_linecurv) != 3)
1481  return (L_DEWARPA *)ERROR_PTR("read fail for linecurv", __func__, NULL);
1482  if (fscanf(fp,
1483  "max_edgeslope = %d, max_edgecurv = %d, max_diff_edgecurv = %d\n",
1484  &max_edgeslope, &max_edgecurv, &max_diff_edgecurv) != 3)
1485  return (L_DEWARPA *)ERROR_PTR("read fail for edgecurv", __func__, NULL);
1486  if (fscanf(fp, "fullmodel = %d\n", &useboth) != 1)
1487  return (L_DEWARPA *)ERROR_PTR("read fail for useboth", __func__, NULL);
1488 
1489  dewa = dewarpaCreate(maxpage + 1, sampling, redfactor, minlines, maxdist);
1490  dewa->maxpage = maxpage;
1491  dewa->max_linecurv = max_linecurv;
1492  dewa->min_diff_linecurv = min_diff_linecurv;
1493  dewa->max_diff_linecurv = max_diff_linecurv;
1494  dewa->max_edgeslope = max_edgeslope;
1495  dewa->max_edgecurv = max_edgecurv;
1496  dewa->max_diff_edgecurv = max_diff_edgecurv;
1497  dewa->useboth = useboth;
1498  namodels = numaCreate(ndewarp);
1499  dewa->namodels = namodels;
1500  for (i = 0; i < ndewarp; i++) {
1501  if ((dew = dewarpReadStream(fp)) == NULL) {
1502  L_ERROR("read fail for dew[%d]\n", __func__, i);
1503  dewarpaDestroy(&dewa);
1504  return NULL;
1505  }
1506  dewarpaInsertDewarp(dewa, dew);
1507  numaAddNumber(namodels, dew->pageno);
1508  }
1509 
1510  /* Validate the models and insert reference models */
1511  dewarpaInsertRefModels(dewa, 0, 0);
1512  return dewa;
1513 }
1514 
1515 
1523 L_DEWARPA *
1524 dewarpaReadMem(const l_uint8 *data,
1525  size_t size)
1526 {
1527 FILE *fp;
1528 L_DEWARPA *dewa;
1529 
1530  if (!data)
1531  return (L_DEWARPA *)ERROR_PTR("data not defined", __func__, NULL);
1532  if ((fp = fopenReadFromMemory(data, size)) == NULL)
1533  return (L_DEWARPA *)ERROR_PTR("stream not opened", __func__, NULL);
1534 
1535  dewa = dewarpaReadStream(fp);
1536  fclose(fp);
1537  if (!dewa) L_ERROR("dewa not read\n", __func__);
1538  return dewa;
1539 }
1540 
1541 
1549 l_ok
1550 dewarpaWrite(const char *filename,
1551  L_DEWARPA *dewa)
1552 {
1553 l_int32 ret;
1554 FILE *fp;
1555 
1556  if (!filename)
1557  return ERROR_INT("filename not defined", __func__, 1);
1558  if (!dewa)
1559  return ERROR_INT("dewa not defined", __func__, 1);
1560 
1561  if ((fp = fopenWriteStream(filename, "wb")) == NULL)
1562  return ERROR_INT("stream not opened", __func__, 1);
1563  ret = dewarpaWriteStream(fp, dewa);
1564  fclose(fp);
1565  if (ret)
1566  return ERROR_INT("dewa not written to stream", __func__, 1);
1567  return 0;
1568 }
1569 
1570 
1578 l_ok
1580  L_DEWARPA *dewa)
1581 {
1582 l_int32 ndewarp, i, pageno;
1583 
1584  if (!fp)
1585  return ERROR_INT("stream not defined", __func__, 1);
1586  if (!dewa)
1587  return ERROR_INT("dewa not defined", __func__, 1);
1588 
1589  /* Generate the list of page numbers for which a model exists.
1590  * Note that no attempt is made to determine if the model is
1591  * valid, because that determination is associated with
1592  * using the model to remove the warping, which typically
1593  * can happen later, after all the models have been built. */
1594  dewarpaListPages(dewa);
1595  if (!dewa->namodels)
1596  return ERROR_INT("dewa->namodels not made", __func__, 1);
1597  ndewarp = numaGetCount(dewa->namodels); /* with actual page models */
1598 
1599  fprintf(fp, "\nDewarpa Version %d\n", DEWARP_VERSION_NUMBER);
1600  fprintf(fp, "ndewarp = %d, maxpage = %d\n", ndewarp, dewa->maxpage);
1601  fprintf(fp, "sampling = %d, redfactor = %d, minlines = %d, maxdist = %d\n",
1602  dewa->sampling, dewa->redfactor, dewa->minlines, dewa->maxdist);
1603  fprintf(fp,
1604  "max_linecurv = %d, min_diff_linecurv = %d, max_diff_linecurv = %d\n",
1605  dewa->max_linecurv, dewa->min_diff_linecurv, dewa->max_diff_linecurv);
1606  fprintf(fp,
1607  "max_edgeslope = %d, max_edgecurv = %d, max_diff_edgecurv = %d\n",
1608  dewa->max_edgeslope, dewa->max_edgecurv, dewa->max_diff_edgecurv);
1609  fprintf(fp, "fullmodel = %d\n", dewa->useboth);
1610  for (i = 0; i < ndewarp; i++) {
1611  numaGetIValue(dewa->namodels, i, &pageno);
1612  dewarpWriteStream(fp, dewarpaGetDewarp(dewa, pageno));
1613  }
1614 
1615  return 0;
1616 }
1617 
1618 
1632 l_ok
1633 dewarpaWriteMem(l_uint8 **pdata,
1634  size_t *psize,
1635  L_DEWARPA *dewa)
1636 {
1637 l_int32 ret;
1638 FILE *fp;
1639 
1640  if (pdata) *pdata = NULL;
1641  if (psize) *psize = 0;
1642  if (!pdata)
1643  return ERROR_INT("&data not defined", __func__, 1);
1644  if (!psize)
1645  return ERROR_INT("&size not defined", __func__, 1);
1646  if (!dewa)
1647  return ERROR_INT("dewa not defined", __func__, 1);
1648 
1649 #if HAVE_FMEMOPEN
1650  if ((fp = open_memstream((char **)pdata, psize)) == NULL)
1651  return ERROR_INT("stream not opened", __func__, 1);
1652  ret = dewarpaWriteStream(fp, dewa);
1653  fputc('\0', fp);
1654  fclose(fp);
1655  *psize = *psize - 1;
1656 #else
1657  L_INFO("work-around: writing to a temp file\n", __func__);
1658  #ifdef _WIN32
1659  if ((fp = fopenWriteWinTempfile()) == NULL)
1660  return ERROR_INT("tmpfile stream not opened", __func__, 1);
1661  #else
1662  if ((fp = tmpfile()) == NULL)
1663  return ERROR_INT("tmpfile stream not opened", __func__, 1);
1664  #endif /* _WIN32 */
1665  ret = dewarpaWriteStream(fp, dewa);
1666  rewind(fp);
1667  *pdata = l_binaryReadStream(fp, psize);
1668  fclose(fp);
1669 #endif /* HAVE_FMEMOPEN */
1670  return ret;
1671 }
L_DEWARPA * dewarpaRead(const char *filename)
dewarpaRead()
Definition: dewarp1.c:1415
L_DEWARPA * dewarpaReadStream(FILE *fp)
dewarpaReadStream()
Definition: dewarp1.c:1450
l_ok dewarpaUseBothArrays(L_DEWARPA *dewa, l_int32 useboth)
dewarpaUseBothArrays()
Definition: dewarp1.c:1024
l_ok dewarpaSetMaxDistance(L_DEWARPA *dewa, l_int32 maxdist)
dewarpaSetMaxDistance()
Definition: dewarp1.c:1085
L_DEWARP * dewarpCreateRef(l_int32 pageno, l_int32 refpage)
dewarpCreateRef()
Definition: dewarp1.c:496
void dewarpaDestroy(L_DEWARPA **pdewa)
dewarpaDestroy()
Definition: dewarp1.c:722
static l_int32 dewarpaExtendArraysToSize(L_DEWARPA *dewa, l_int32 size)
dewarpaExtendArraysToSize()
Definition: dewarp1.c:865
l_ok dewarpWriteStream(FILE *fp, L_DEWARP *dew)
dewarpWriteStream()
Definition: dewarp1.c:1310
l_ok dewarpaDestroyDewarp(L_DEWARPA *dewa, l_int32 pageno)
dewarpaDestroyDewarp()
Definition: dewarp1.c:759
l_ok dewarpaInsertDewarp(L_DEWARPA *dewa, L_DEWARP *dew)
dewarpaInsertDewarp()
Definition: dewarp1.c:800
void dewarpDestroy(L_DEWARP **pdew)
dewarpDestroy()
Definition: dewarp1.c:516
l_ok dewarpWrite(const char *filename, L_DEWARP *dew)
dewarpWrite()
Definition: dewarp1.c:1274
L_DEWARP * dewarpReadStream(FILE *fp)
dewarpReadStream()
Definition: dewarp1.c:1145
L_DEWARPA * dewarpaCreateFromPixacomp(PIXAC *pixac, l_int32 useboth, l_int32 sampling, l_int32 minlines, l_int32 maxdist)
dewarpaCreateFromPixacomp()
Definition: dewarp1.c:663
l_ok dewarpaSetCheckColumns(L_DEWARPA *dewa, l_int32 check_columns)
dewarpaSetCheckColumns()
Definition: dewarp1.c:1061
L_DEWARPA * dewarpaReadMem(const l_uint8 *data, size_t size)
dewarpaReadMem()
Definition: dewarp1.c:1524
l_ok dewarpaWriteStream(FILE *fp, L_DEWARPA *dewa)
dewarpaWriteStream()
Definition: dewarp1.c:1579
l_ok dewarpWriteMem(l_uint8 **pdata, size_t *psize, L_DEWARP *dew)
dewarpWriteMem()
Definition: dewarp1.c:1364
L_DEWARP * dewarpaGetDewarp(L_DEWARPA *dewa, l_int32 index)
dewarpaGetDewarp()
Definition: dewarp1.c:895
L_DEWARPA * dewarpaCreate(l_int32 nptrs, l_int32 sampling, l_int32 redfactor, l_int32 minlines, l_int32 maxdist)
dewarpaCreate()
Definition: dewarp1.c:576
L_DEWARP * dewarpCreate(PIX *pixs, l_int32 pageno)
dewarpCreate()
Definition: dewarp1.c:459
l_ok dewarpaWrite(const char *filename, L_DEWARPA *dewa)
dewarpaWrite()
Definition: dewarp1.c:1550
L_DEWARP * dewarpReadMem(const l_uint8 *data, size_t size)
dewarpReadMem()
Definition: dewarp1.c:1248
l_ok dewarpaWriteMem(l_uint8 **pdata, size_t *psize, L_DEWARPA *dewa)
dewarpaWriteMem()
Definition: dewarp1.c:1633
l_ok dewarpaSetCurvatures(L_DEWARPA *dewa, l_int32 max_linecurv, l_int32 min_diff_linecurv, l_int32 max_diff_linecurv, l_int32 max_edgecurv, l_int32 max_diff_edgecurv, l_int32 max_edgeslope)
dewarpaSetCurvatures()
Definition: dewarp1.c:962
L_DEWARP * dewarpRead(const char *filename)
dewarpRead()
Definition: dewarp1.c:1107
l_ok dewarpBuildPageModel(L_DEWARP *dew, const char *debugfile)
dewarpBuildPageModel()
Definition: dewarp2.c:156
l_ok dewarpMinimize(L_DEWARP *dew)
dewarpMinimize()
Definition: dewarp3.c:719
l_ok dewarpaListPages(L_DEWARPA *dewa)
dewarpaListPages()
Definition: dewarp4.c:290
l_ok dewarpaInsertRefModels(L_DEWARPA *dewa, l_int32 notests, l_int32 debug)
dewarpaInsertRefModels()
Definition: dewarp4.c:444
#define DEWARP_VERSION_NUMBER
Definition: dewarp.h:110
l_ok fpixWriteStream(FILE *fp, FPIX *fpix)
fpixWriteStream()
Definition: fpix1.c:1492
void fpixDestroy(FPIX **pfpix)
fpixDestroy()
Definition: fpix1.c:280
FPIX * fpixReadStream(FILE *fp)
fpixReadStream()
Definition: fpix1.c:1386
l_ok numaAddNumber(NUMA *na, l_float32 val)
numaAddNumber()
Definition: numabasic.c:460
NUMA * numaCreate(l_int32 n)
numaCreate()
Definition: numabasic.c:193
void numaDestroy(NUMA **pna)
numaDestroy()
Definition: numabasic.c:357
l_int32 numaGetCount(NUMA *na)
numaGetCount()
Definition: numabasic.c:630
l_ok numaGetIValue(NUMA *na, l_int32 index, l_int32 *pival)
numaGetIValue()
Definition: numabasic.c:720
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:608
PIX * pixClone(PIX *pixs)
pixClone()
Definition: pix1.c:582
l_int32 pixacompGetOffset(PIXAC *pixac)
pixacompGetOffset()
Definition: pixcomp.c:1383
l_int32 pixacompGetCount(PIXAC *pixac)
pixacompGetCount()
Definition: pixcomp.c:1121
PIX * pixacompGetPix(PIXAC *pixac, l_int32 index)
pixacompGetPix()
Definition: pixcomp.c:1182
l_int32 minlines
Definition: dewarp.h:168
struct FPix * fullvdispar
Definition: dewarp.h:158
l_int32 mincurv
Definition: dewarp.h:170
l_int32 pageno
Definition: dewarp.h:165
l_int32 vsuccess
Definition: dewarp.h:180
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 leftcurv
Definition: dewarp.h:174
l_int32 w
Definition: dewarp.h:163
struct FPix * fullydispar
Definition: dewarp.h:160
l_int32 redfactor
Definition: dewarp.h:167
struct Pix * pixs
Definition: dewarp.h:154
l_int32 nx
Definition: dewarp.h:176
l_int32 nlines
Definition: dewarp.h:169
l_int32 maxcurv
Definition: dewarp.h:171
l_int32 refpage
Definition: dewarp.h:179
struct FPix * fullhdispar
Definition: dewarp.h:159
struct FPix * sampydispar
Definition: dewarp.h:157
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 rightcurv
Definition: dewarp.h:175
l_int32 leftslope
Definition: dewarp.h:172
l_int32 rightslope
Definition: dewarp.h:173
l_int32 min_diff_linecurv
Definition: dewarp.h:129
l_int32 maxdist
Definition: dewarp.h:126
struct L_Dewarp ** dewarp
Definition: dewarp.h:117
l_int32 max_diff_linecurv
Definition: dewarp.h:131
l_int32 sampling
Definition: dewarp.h:124
l_int32 max_edgeslope
Definition: dewarp.h:133
l_int32 maxpage
Definition: dewarp.h:116
l_int32 max_edgecurv
Definition: dewarp.h:135
struct L_Dewarp ** dewarpcache
Definition: dewarp.h:118
l_int32 minlines
Definition: dewarp.h:125
l_int32 nalloc
Definition: dewarp.h:115
struct Numa * namodels
Definition: dewarp.h:119
l_int32 max_diff_edgecurv
Definition: dewarp.h:137
l_int32 max_linecurv
Definition: dewarp.h:127
l_int32 check_columns
Definition: dewarp.h:141
struct Numa * napages
Definition: dewarp.h:121
l_int32 redfactor
Definition: dewarp.h:123
l_int32 modelsready
Definition: dewarp.h:144
l_int32 useboth
Definition: dewarp.h:139
l_uint8 * l_binaryReadStream(FILE *fp, size_t *pnbytes)
l_binaryReadStream()
Definition: utils2.c:1358
FILE * fopenReadFromMemory(const l_uint8 *data, size_t size)
fopenReadFromMemory()
Definition: utils2.c:1937
FILE * fopenWriteStream(const char *filename, const char *modestring)
fopenWriteStream()
Definition: utils2.c:1905
void * reallocNew(void **pindata, size_t oldsize, size_t newsize)
reallocNew()
Definition: utils2.c:1262
FILE * fopenWriteWinTempfile(void)
fopenWriteWinTempfile()
Definition: utils2.c:1981
FILE * fopenReadStream(const char *filename)
fopenReadStream()
Definition: utils2.c:1864