Leptonica  1.82.0
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  PROCNAME("dewarpCreate");
465 
466  if (!pixs)
467  return (L_DEWARP *)ERROR_PTR("pixs not defined", procName, NULL);
468  if (pixGetDepth(pixs) != 1)
469  return (L_DEWARP *)ERROR_PTR("pixs not 1 bpp", procName, NULL);
470 
471  dew = (L_DEWARP *)LEPT_CALLOC(1, sizeof(L_DEWARP));
472  dew->pixs = pixClone(pixs);
473  dew->pageno = pageno;
474  dew->w = pixGetWidth(pixs);
475  dew->h = pixGetHeight(pixs);
476  return dew;
477 }
478 
479 
497 L_DEWARP *
498 dewarpCreateRef(l_int32 pageno,
499  l_int32 refpage)
500 {
501 L_DEWARP *dew;
502 
503  dew = (L_DEWARP *)LEPT_CALLOC(1, sizeof(L_DEWARP));
504  dew->pageno = pageno;
505  dew->hasref = 1;
506  dew->refpage = refpage;
507  return dew;
508 }
509 
510 
517 void
519 {
520 L_DEWARP *dew;
521 
522  PROCNAME("dewarpDestroy");
523 
524  if (pdew == NULL) {
525  L_WARNING("ptr address is null!\n", procName);
526  return;
527  }
528  if ((dew = *pdew) == NULL)
529  return;
530 
531  pixDestroy(&dew->pixs);
532  fpixDestroy(&dew->sampvdispar);
533  fpixDestroy(&dew->samphdispar);
534  fpixDestroy(&dew->sampydispar);
535  fpixDestroy(&dew->fullvdispar);
536  fpixDestroy(&dew->fullhdispar);
537  fpixDestroy(&dew->fullydispar);
538  numaDestroy(&dew->namidys);
539  numaDestroy(&dew->nacurves);
540  LEPT_FREE(dew);
541  *pdew = NULL;
542 }
543 
544 
545 /*----------------------------------------------------------------------*
546  * Create/destroy Dewarpa *
547  *----------------------------------------------------------------------*/
579 L_DEWARPA *
580 dewarpaCreate(l_int32 nptrs,
581  l_int32 sampling,
582  l_int32 redfactor,
583  l_int32 minlines,
584  l_int32 maxdist)
585 {
586 L_DEWARPA *dewa;
587 
588  PROCNAME("dewarpaCreate");
589 
590  if (nptrs <= 0)
591  nptrs = InitialPtrArraySize;
592  if (nptrs > MaxPtrArraySize)
593  return (L_DEWARPA *)ERROR_PTR("too many pages", procName, NULL);
594  if (redfactor != 1 && redfactor != 2)
595  return (L_DEWARPA *)ERROR_PTR("redfactor not in {1,2}",
596  procName, NULL);
597  if (sampling == 0) {
598  sampling = DefaultArraySampling;
599  } else if (sampling < MinArraySampling) {
600  L_WARNING("sampling too small; setting to %d\n", procName,
601  MinArraySampling);
602  sampling = MinArraySampling;
603  }
604  if (minlines == 0) {
605  minlines = DefaultMinLines;
606  } else if (minlines < MinMinLines) {
607  L_WARNING("minlines too small; setting to %d\n", procName,
608  MinMinLines);
609  minlines = DefaultMinLines;
610  }
611  if (maxdist < 0)
612  maxdist = DefaultMaxRefDist;
613 
614  dewa = (L_DEWARPA *)LEPT_CALLOC(1, sizeof(L_DEWARPA));
615  dewa->dewarp = (L_DEWARP **)LEPT_CALLOC(nptrs, sizeof(L_DEWARPA *));
616  dewa->dewarpcache = (L_DEWARP **)LEPT_CALLOC(nptrs, sizeof(L_DEWARPA *));
617  if (!dewa->dewarp || !dewa->dewarpcache) {
618  dewarpaDestroy(&dewa);
619  return (L_DEWARPA *)ERROR_PTR("dewarp ptrs not made", procName, NULL);
620  }
621  dewa->nalloc = nptrs;
622  dewa->sampling = sampling;
623  dewa->redfactor = redfactor;
624  dewa->minlines = minlines;
625  dewa->maxdist = maxdist;
626  dewa->max_linecurv = DefaultMaxLineCurv;
627  dewa->min_diff_linecurv = DefaultMinDiffLineCurv;
628  dewa->max_diff_linecurv = DefaultMaxDiffLineCurv;
629  dewa->max_edgeslope = DefaultMaxEdgeSlope;
630  dewa->max_edgecurv = DefaultMaxEdgeCurv;
631  dewa->max_diff_edgecurv = DefaultMaxDiffEdgeCurv;
632  dewa->check_columns = DefaultCheckColumns;
633  dewa->useboth = DefaultUseBoth;
634  return dewa;
635 }
636 
637 
668 L_DEWARPA *
670  l_int32 useboth,
671  l_int32 sampling,
672  l_int32 minlines,
673  l_int32 maxdist)
674 {
675 l_int32 i, nptrs, pageno;
676 L_DEWARP *dew;
677 L_DEWARPA *dewa;
678 PIX *pixt;
679 
680  PROCNAME("dewarpaCreateFromPixacomp");
681 
682  if (!pixac)
683  return (L_DEWARPA *)ERROR_PTR("pixac not defined", procName, NULL);
684 
685  nptrs = pixacompGetCount(pixac);
686  if ((dewa = dewarpaCreate(pixacompGetOffset(pixac) + nptrs,
687  sampling, 1, minlines, maxdist)) == NULL)
688  return (L_DEWARPA *)ERROR_PTR("dewa not made", procName, NULL);
689  dewarpaUseBothArrays(dewa, useboth);
690 
691  for (i = 0; i < nptrs; i++) {
692  pageno = pixacompGetOffset(pixac) + i; /* index into pixacomp */
693  pixt = pixacompGetPix(pixac, pageno);
694  if (pixt && (pixGetWidth(pixt) > 1)) {
695  dew = dewarpCreate(pixt, pageno);
696  pixDestroy(&pixt);
697  if (!dew) {
698  ERROR_INT("unable to make dew!", procName, 1);
699  continue;
700  }
701 
702  /* Insert into dewa for this page */
703  dewarpaInsertDewarp(dewa, dew);
704 
705  /* Build disparity arrays for this page */
706  dewarpBuildPageModel(dew, NULL);
707  if (!dew->vsuccess) { /* will need to use model from nearby page */
708  dewarpaDestroyDewarp(dewa, pageno);
709  L_ERROR("unable to build model for page %d\n", procName, i);
710  continue;
711  }
712  /* Remove all extraneous data */
713  dewarpMinimize(dew);
714  }
715  pixDestroy(&pixt);
716  }
717  dewarpaInsertRefModels(dewa, 0, 0);
718 
719  return dewa;
720 }
721 
722 
729 void
731 {
732 l_int32 i;
733 L_DEWARP *dew;
734 L_DEWARPA *dewa;
735 
736  PROCNAME("dewarpaDestroy");
737 
738  if (pdewa == NULL) {
739  L_WARNING("ptr address is null!\n", procName);
740  return;
741  }
742  if ((dewa = *pdewa) == NULL)
743  return;
744 
745  for (i = 0; i < dewa->nalloc; i++) {
746  if ((dew = dewa->dewarp[i]) != NULL)
747  dewarpDestroy(&dew);
748  if ((dew = dewa->dewarpcache[i]) != NULL)
749  dewarpDestroy(&dew);
750  }
751  numaDestroy(&dewa->namodels);
752  numaDestroy(&dewa->napages);
753 
754  LEPT_FREE(dewa->dewarp);
755  LEPT_FREE(dewa->dewarpcache);
756  LEPT_FREE(dewa);
757  *pdewa = NULL;
758 }
759 
760 
768 l_ok
770  l_int32 pageno)
771 {
772 L_DEWARP *dew;
773 
774  PROCNAME("dewarpaDestroyDewarp");
775 
776  if (!dewa)
777  return ERROR_INT("dewa or dew not defined", procName, 1);
778  if (pageno < 0 || pageno > dewa->maxpage)
779  return ERROR_INT("page out of bounds", procName, 1);
780  if ((dew = dewa->dewarp[pageno]) == NULL)
781  return ERROR_INT("dew not defined", procName, 1);
782 
783  dewarpDestroy(&dew);
784  dewa->dewarp[pageno] = NULL;
785  return 0;
786 }
787 
788 
789 /*----------------------------------------------------------------------*
790  * Dewarpa insertion/extraction *
791  *----------------------------------------------------------------------*/
811 l_ok
813  L_DEWARP *dew)
814 {
815 l_int32 pageno, n, newsize;
816 L_DEWARP *prevdew;
817 
818  PROCNAME("dewarpaInsertDewarp");
819 
820  if (!dewa)
821  return ERROR_INT("dewa not defined", procName, 1);
822  if (!dew)
823  return ERROR_INT("dew not defined", procName, 1);
824 
825  dew->dewa = dewa;
826  pageno = dew->pageno;
827  if (pageno > MaxPtrArraySize)
828  return ERROR_INT("too many pages", procName, 1);
829  if (pageno > dewa->maxpage)
830  dewa->maxpage = pageno;
831  dewa->modelsready = 0; /* force re-evaluation at application time */
832 
833  /* Extend ptr array if necessary */
834  n = dewa->nalloc;
835  newsize = n;
836  if (pageno >= 2 * n)
837  newsize = 2 * pageno;
838  else if (pageno >= n)
839  newsize = 2 * n;
840  if (newsize > n) {
841  if (dewarpaExtendArraysToSize(dewa, newsize))
842  return ERROR_INT("extension failed", procName, 1);
843  }
844 
845  if ((prevdew = dewarpaGetDewarp(dewa, pageno)) != NULL)
846  dewarpDestroy(&prevdew);
847  dewa->dewarp[pageno] = dew;
848 
849  dew->sampling = dewa->sampling;
850  dew->redfactor = dewa->redfactor;
851  dew->minlines = dewa->minlines;
852 
853  /* Get the dimensions of the sampled array. This will be
854  * stored in an fpix, and the input resolution version is
855  * guaranteed to be larger than pixs. However, if you
856  * want to apply the disparity to an image with a width
857  * w > nx * s - 2 * s + 2
858  * you will need to extend the input res fpix.
859  * And similarly for h. */
860  dew->nx = (dew->w + 2 * dew->sampling - 2) / dew->sampling;
861  dew->ny = (dew->h + 2 * dew->sampling - 2) / dew->sampling;
862  return 0;
863 }
864 
865 
878 static l_int32
880  l_int32 size)
881 {
882  PROCNAME("dewarpaExtendArraysToSize");
883 
884  if (!dewa)
885  return ERROR_INT("dewa not defined", procName, 1);
886 
887  if (size > dewa->nalloc) {
888  if ((dewa->dewarp = (L_DEWARP **)reallocNew((void **)&dewa->dewarp,
889  sizeof(L_DEWARP *) * dewa->nalloc,
890  size * sizeof(L_DEWARP *))) == NULL)
891  return ERROR_INT("new ptr array not returned", procName, 1);
892  if ((dewa->dewarpcache =
893  (L_DEWARP **)reallocNew((void **)&dewa->dewarpcache,
894  sizeof(L_DEWARP *) * dewa->nalloc,
895  size * sizeof(L_DEWARP *))) == NULL)
896  return ERROR_INT("new ptr cache array not returned", procName, 1);
897  dewa->nalloc = size;
898  }
899  return 0;
900 }
901 
902 
910 L_DEWARP *
912  l_int32 index)
913 {
914  PROCNAME("dewarpaGetDewarp");
915 
916  if (!dewa)
917  return (L_DEWARP *)ERROR_PTR("dewa not defined", procName, NULL);
918  if (index < 0 || index > dewa->maxpage) {
919  L_ERROR("index = %d is invalid; max index = %d\n",
920  procName, index, dewa->maxpage);
921  return NULL;
922  }
923 
924  return dewa->dewarp[index];
925 }
926 
927 
928 /*----------------------------------------------------------------------*
929  * Setting parameters to control rendering from the model *
930  *----------------------------------------------------------------------*/
979 l_ok
981  l_int32 max_linecurv,
982  l_int32 min_diff_linecurv,
983  l_int32 max_diff_linecurv,
984  l_int32 max_edgecurv,
985  l_int32 max_diff_edgecurv,
986  l_int32 max_edgeslope)
987 {
988  PROCNAME("dewarpaSetCurvatures");
989 
990  if (!dewa)
991  return ERROR_INT("dewa not defined", procName, 1);
992 
993  if (max_linecurv == -1)
994  dewa->max_linecurv = DefaultMaxLineCurv;
995  else
996  dewa->max_linecurv = L_ABS(max_linecurv);
997 
998  if (min_diff_linecurv == -1)
999  dewa->min_diff_linecurv = DefaultMinDiffLineCurv;
1000  else
1001  dewa->min_diff_linecurv = L_ABS(min_diff_linecurv);
1002 
1003  if (max_diff_linecurv == -1)
1004  dewa->max_diff_linecurv = DefaultMaxDiffLineCurv;
1005  else
1006  dewa->max_diff_linecurv = L_ABS(max_diff_linecurv);
1007 
1008  if (max_edgecurv == -1)
1009  dewa->max_edgecurv = DefaultMaxEdgeCurv;
1010  else
1011  dewa->max_edgecurv = L_ABS(max_edgecurv);
1012 
1013  if (max_diff_edgecurv == -1)
1014  dewa->max_diff_edgecurv = DefaultMaxDiffEdgeCurv;
1015  else
1016  dewa->max_diff_edgecurv = L_ABS(max_diff_edgecurv);
1017 
1018  if (max_edgeslope == -1)
1019  dewa->max_edgeslope = DefaultMaxEdgeSlope;
1020  else
1021  dewa->max_edgeslope = L_ABS(max_edgeslope);
1022 
1023  dewa->modelsready = 0; /* force validation */
1024  return 0;
1025 }
1026 
1027 
1043 l_ok
1045  l_int32 useboth)
1046 {
1047  PROCNAME("dewarpaUseBothArrays");
1048 
1049  if (!dewa)
1050  return ERROR_INT("dewa not defined", procName, 1);
1051 
1052  dewa->useboth = useboth;
1053  dewa->modelsready = 0; /* force validation */
1054  return 0;
1055 }
1056 
1057 
1082 l_ok
1084  l_int32 check_columns)
1085 {
1086  PROCNAME("dewarpaSetCheckColumns");
1087 
1088  if (!dewa)
1089  return ERROR_INT("dewa not defined", procName, 1);
1090 
1091  dewa->check_columns = check_columns;
1092  return 0;
1093 }
1094 
1095 
1108 l_ok
1110  l_int32 maxdist)
1111 {
1112  PROCNAME("dewarpaSetMaxDistance");
1113 
1114  if (!dewa)
1115  return ERROR_INT("dewa not defined", procName, 1);
1116 
1117  dewa->maxdist = maxdist;
1118  dewa->modelsready = 0; /* force validation */
1119  return 0;
1120 }
1121 
1122 
1123 /*----------------------------------------------------------------------*
1124  * Dewarp serialized I/O *
1125  *----------------------------------------------------------------------*/
1132 L_DEWARP *
1133 dewarpRead(const char *filename)
1134 {
1135 FILE *fp;
1136 L_DEWARP *dew;
1137 
1138  PROCNAME("dewarpRead");
1139 
1140  if (!filename)
1141  return (L_DEWARP *)ERROR_PTR("filename not defined", procName, NULL);
1142  if ((fp = fopenReadStream(filename)) == NULL)
1143  return (L_DEWARP *)ERROR_PTR("stream not opened", procName, NULL);
1144 
1145  if ((dew = dewarpReadStream(fp)) == NULL) {
1146  fclose(fp);
1147  return (L_DEWARP *)ERROR_PTR("dew not read", procName, NULL);
1148  }
1149 
1150  fclose(fp);
1151  return dew;
1152 }
1153 
1154 
1172 L_DEWARP *
1174 {
1175 l_int32 version, sampling, redfactor, minlines, pageno, hasref, refpage;
1176 l_int32 w, h, nx, ny, vdispar, hdispar, nlines;
1177 l_int32 mincurv, maxcurv, leftslope, rightslope, leftcurv, rightcurv;
1178 L_DEWARP *dew;
1179 FPIX *fpixv, *fpixh;
1180 
1181  PROCNAME("dewarpReadStream");
1182 
1183  if (!fp)
1184  return (L_DEWARP *)ERROR_PTR("stream not defined", procName, NULL);
1185 
1186  if (fscanf(fp, "\nDewarp Version %d\n", &version) != 1)
1187  return (L_DEWARP *)ERROR_PTR("not a dewarp file", procName, NULL);
1188  if (version != DEWARP_VERSION_NUMBER)
1189  return (L_DEWARP *)ERROR_PTR("invalid dewarp version", procName, NULL);
1190  if (fscanf(fp, "pageno = %d\n", &pageno) != 1)
1191  return (L_DEWARP *)ERROR_PTR("read fail for pageno", procName, NULL);
1192  if (fscanf(fp, "hasref = %d, refpage = %d\n", &hasref, &refpage) != 2)
1193  return (L_DEWARP *)ERROR_PTR("read fail for hasref, refpage",
1194  procName, NULL);
1195  if (fscanf(fp, "sampling = %d, redfactor = %d\n", &sampling, &redfactor)
1196  != 2)
1197  return (L_DEWARP *)ERROR_PTR("read fail for sampling/redfactor",
1198  procName, NULL);
1199  if (fscanf(fp, "nlines = %d, minlines = %d\n", &nlines, &minlines) != 2)
1200  return (L_DEWARP *)ERROR_PTR("read fail for nlines/minlines",
1201  procName, NULL);
1202  if (fscanf(fp, "w = %d, h = %d\n", &w, &h) != 2)
1203  return (L_DEWARP *)ERROR_PTR("read fail for w, h", procName, NULL);
1204  if (fscanf(fp, "nx = %d, ny = %d\n", &nx, &ny) != 2)
1205  return (L_DEWARP *)ERROR_PTR("read fail for nx, ny", procName, NULL);
1206  if (fscanf(fp, "vert_dispar = %d, horiz_dispar = %d\n", &vdispar, &hdispar)
1207  != 2)
1208  return (L_DEWARP *)ERROR_PTR("read fail for flags", procName, NULL);
1209  if (vdispar) {
1210  if (fscanf(fp, "min line curvature = %d, max line curvature = %d\n",
1211  &mincurv, &maxcurv) != 2)
1212  return (L_DEWARP *)ERROR_PTR("read fail for mincurv & maxcurv",
1213  procName, NULL);
1214  }
1215  if (hdispar) {
1216  if (fscanf(fp, "left edge slope = %d, right edge slope = %d\n",
1217  &leftslope, &rightslope) != 2)
1218  return (L_DEWARP *)ERROR_PTR("read fail for leftslope & rightslope",
1219  procName, NULL);
1220  if (fscanf(fp, "left edge curvature = %d, right edge curvature = %d\n",
1221  &leftcurv, &rightcurv) != 2)
1222  return (L_DEWARP *)ERROR_PTR("read fail for leftcurv & rightcurv",
1223  procName, NULL);
1224  }
1225  if (vdispar) {
1226  if ((fpixv = fpixReadStream(fp)) == NULL)
1227  return (L_DEWARP *)ERROR_PTR("read fail for vdispar",
1228  procName, NULL);
1229  }
1230  if (hdispar) {
1231  if ((fpixh = fpixReadStream(fp)) == NULL)
1232  return (L_DEWARP *)ERROR_PTR("read fail for hdispar",
1233  procName, NULL);
1234  }
1235  getc(fp);
1236 
1237  dew = (L_DEWARP *)LEPT_CALLOC(1, sizeof(L_DEWARP));
1238  dew->w = w;
1239  dew->h = h;
1240  dew->pageno = pageno;
1241  dew->sampling = sampling;
1242  dew->redfactor = redfactor;
1243  dew->minlines = minlines;
1244  dew->nlines = nlines;
1245  dew->hasref = hasref;
1246  dew->refpage = refpage;
1247  if (hasref == 0) /* any dew without a ref has an actual model */
1248  dew->vsuccess = 1;
1249  dew->nx = nx;
1250  dew->ny = ny;
1251  if (vdispar) {
1252  dew->mincurv = mincurv;
1253  dew->maxcurv = maxcurv;
1254  dew->vsuccess = 1;
1255  dew->sampvdispar = fpixv;
1256  }
1257  if (hdispar) {
1258  dew->leftslope = leftslope;
1259  dew->rightslope = rightslope;
1260  dew->leftcurv = leftcurv;
1261  dew->rightcurv = rightcurv;
1262  dew->hsuccess = 1;
1263  dew->samphdispar = fpixh;
1264  }
1265 
1266  return dew;
1267 }
1268 
1269 
1277 L_DEWARP *
1278 dewarpReadMem(const l_uint8 *data,
1279  size_t size)
1280 {
1281 FILE *fp;
1282 L_DEWARP *dew;
1283 
1284  PROCNAME("dewarpReadMem");
1285 
1286  if (!data)
1287  return (L_DEWARP *)ERROR_PTR("data not defined", procName, NULL);
1288  if ((fp = fopenReadFromMemory(data, size)) == NULL)
1289  return (L_DEWARP *)ERROR_PTR("stream not opened", procName, NULL);
1290 
1291  dew = dewarpReadStream(fp);
1292  fclose(fp);
1293  if (!dew) L_ERROR("dew not read\n", procName);
1294  return dew;
1295 }
1296 
1297 
1305 l_ok
1306 dewarpWrite(const char *filename,
1307  L_DEWARP *dew)
1308 {
1309 l_int32 ret;
1310 FILE *fp;
1311 
1312  PROCNAME("dewarpWrite");
1313 
1314  if (!filename)
1315  return ERROR_INT("filename not defined", procName, 1);
1316  if (!dew)
1317  return ERROR_INT("dew not defined", procName, 1);
1318 
1319  if ((fp = fopenWriteStream(filename, "wb")) == NULL)
1320  return ERROR_INT("stream not opened", procName, 1);
1321  ret = dewarpWriteStream(fp, dew);
1322  fclose(fp);
1323  if (ret)
1324  return ERROR_INT("dew not written to stream", procName, 1);
1325  return 0;
1326 }
1327 
1328 
1343 l_ok
1345  L_DEWARP *dew)
1346 {
1347 l_int32 vdispar, hdispar;
1348 
1349  PROCNAME("dewarpWriteStream");
1350 
1351  if (!fp)
1352  return ERROR_INT("stream not defined", procName, 1);
1353  if (!dew)
1354  return ERROR_INT("dew not defined", procName, 1);
1355 
1356  fprintf(fp, "\nDewarp Version %d\n", DEWARP_VERSION_NUMBER);
1357  fprintf(fp, "pageno = %d\n", dew->pageno);
1358  fprintf(fp, "hasref = %d, refpage = %d\n", dew->hasref, dew->refpage);
1359  fprintf(fp, "sampling = %d, redfactor = %d\n",
1360  dew->sampling, dew->redfactor);
1361  fprintf(fp, "nlines = %d, minlines = %d\n", dew->nlines, dew->minlines);
1362  fprintf(fp, "w = %d, h = %d\n", dew->w, dew->h);
1363  fprintf(fp, "nx = %d, ny = %d\n", dew->nx, dew->ny);
1364  vdispar = (dew->sampvdispar) ? 1 : 0;
1365  hdispar = (dew->samphdispar) ? 1 : 0;
1366  fprintf(fp, "vert_dispar = %d, horiz_dispar = %d\n", vdispar, hdispar);
1367  if (vdispar)
1368  fprintf(fp, "min line curvature = %d, max line curvature = %d\n",
1369  dew->mincurv, dew->maxcurv);
1370  if (hdispar) {
1371  fprintf(fp, "left edge slope = %d, right edge slope = %d\n",
1372  dew->leftslope, dew->rightslope);
1373  fprintf(fp, "left edge curvature = %d, right edge curvature = %d\n",
1374  dew->leftcurv, dew->rightcurv);
1375  }
1376  if (vdispar) fpixWriteStream(fp, dew->sampvdispar);
1377  if (hdispar) fpixWriteStream(fp, dew->samphdispar);
1378  fprintf(fp, "\n");
1379 
1380  if (!vdispar)
1381  L_WARNING("no disparity arrays!\n", procName);
1382  return 0;
1383 }
1384 
1385 
1399 l_ok
1400 dewarpWriteMem(l_uint8 **pdata,
1401  size_t *psize,
1402  L_DEWARP *dew)
1403 {
1404 l_int32 ret;
1405 FILE *fp;
1406 
1407  PROCNAME("dewarpWriteMem");
1408 
1409  if (pdata) *pdata = NULL;
1410  if (psize) *psize = 0;
1411  if (!pdata)
1412  return ERROR_INT("&data not defined", procName, 1);
1413  if (!psize)
1414  return ERROR_INT("&size not defined", procName, 1);
1415  if (!dew)
1416  return ERROR_INT("dew not defined", procName, 1);
1417 
1418 #if HAVE_FMEMOPEN
1419  if ((fp = open_memstream((char **)pdata, psize)) == NULL)
1420  return ERROR_INT("stream not opened", procName, 1);
1421  ret = dewarpWriteStream(fp, dew);
1422  fputc('\0', fp);
1423  fclose(fp);
1424  *psize = *psize - 1;
1425 #else
1426  L_INFO("work-around: writing to a temp file\n", procName);
1427  #ifdef _WIN32
1428  if ((fp = fopenWriteWinTempfile()) == NULL)
1429  return ERROR_INT("tmpfile stream not opened", procName, 1);
1430  #else
1431  if ((fp = tmpfile()) == NULL)
1432  return ERROR_INT("tmpfile stream not opened", procName, 1);
1433  #endif /* _WIN32 */
1434  ret = dewarpWriteStream(fp, dew);
1435  rewind(fp);
1436  *pdata = l_binaryReadStream(fp, psize);
1437  fclose(fp);
1438 #endif /* HAVE_FMEMOPEN */
1439  return ret;
1440 }
1441 
1442 
1443 /*----------------------------------------------------------------------*
1444  * Dewarpa serialized I/O *
1445  *----------------------------------------------------------------------*/
1452 L_DEWARPA *
1453 dewarpaRead(const char *filename)
1454 {
1455 FILE *fp;
1456 L_DEWARPA *dewa;
1457 
1458  PROCNAME("dewarpaRead");
1459 
1460  if (!filename)
1461  return (L_DEWARPA *)ERROR_PTR("filename not defined", procName, NULL);
1462  if ((fp = fopenReadStream(filename)) == NULL)
1463  return (L_DEWARPA *)ERROR_PTR("stream not opened", procName, NULL);
1464 
1465  if ((dewa = dewarpaReadStream(fp)) == NULL) {
1466  fclose(fp);
1467  return (L_DEWARPA *)ERROR_PTR("dewa not read", procName, NULL);
1468  }
1469 
1470  fclose(fp);
1471  return dewa;
1472 }
1473 
1474 
1489 L_DEWARPA *
1491 {
1492 l_int32 i, version, ndewarp, maxpage;
1493 l_int32 sampling, redfactor, minlines, maxdist, useboth;
1494 l_int32 max_linecurv, min_diff_linecurv, max_diff_linecurv;
1495 l_int32 max_edgeslope, max_edgecurv, max_diff_edgecurv;
1496 L_DEWARP *dew;
1497 L_DEWARPA *dewa;
1498 NUMA *namodels;
1499 
1500  PROCNAME("dewarpaReadStream");
1501 
1502  if (!fp)
1503  return (L_DEWARPA *)ERROR_PTR("stream not defined", procName, NULL);
1504 
1505  if (fscanf(fp, "\nDewarpa Version %d\n", &version) != 1)
1506  return (L_DEWARPA *)ERROR_PTR("not a dewarpa file", procName, NULL);
1507  if (version != DEWARP_VERSION_NUMBER)
1508  return (L_DEWARPA *)ERROR_PTR("invalid dewarp version", procName, NULL);
1509 
1510  if (fscanf(fp, "ndewarp = %d, maxpage = %d\n", &ndewarp, &maxpage) != 2)
1511  return (L_DEWARPA *)ERROR_PTR("read fail for maxpage+", procName, NULL);
1512  if (ndewarp < 1)
1513  return (L_DEWARPA *)ERROR_PTR("pages not >= 1", procName, NULL);
1514  if (ndewarp > MaxPtrArraySize)
1515  return (L_DEWARPA *)ERROR_PTR("too many pages", procName, NULL);
1516  if (fscanf(fp,
1517  "sampling = %d, redfactor = %d, minlines = %d, maxdist = %d\n",
1518  &sampling, &redfactor, &minlines, &maxdist) != 4)
1519  return (L_DEWARPA *)ERROR_PTR("read fail for 4 params", procName, NULL);
1520  if (fscanf(fp,
1521  "max_linecurv = %d, min_diff_linecurv = %d, max_diff_linecurv = %d\n",
1522  &max_linecurv, &min_diff_linecurv, &max_diff_linecurv) != 3)
1523  return (L_DEWARPA *)ERROR_PTR("read fail for linecurv", procName, NULL);
1524  if (fscanf(fp,
1525  "max_edgeslope = %d, max_edgecurv = %d, max_diff_edgecurv = %d\n",
1526  &max_edgeslope, &max_edgecurv, &max_diff_edgecurv) != 3)
1527  return (L_DEWARPA *)ERROR_PTR("read fail for edgecurv", procName, NULL);
1528  if (fscanf(fp, "fullmodel = %d\n", &useboth) != 1)
1529  return (L_DEWARPA *)ERROR_PTR("read fail for useboth", procName, NULL);
1530 
1531  dewa = dewarpaCreate(maxpage + 1, sampling, redfactor, minlines, maxdist);
1532  dewa->maxpage = maxpage;
1533  dewa->max_linecurv = max_linecurv;
1534  dewa->min_diff_linecurv = min_diff_linecurv;
1535  dewa->max_diff_linecurv = max_diff_linecurv;
1536  dewa->max_edgeslope = max_edgeslope;
1537  dewa->max_edgecurv = max_edgecurv;
1538  dewa->max_diff_edgecurv = max_diff_edgecurv;
1539  dewa->useboth = useboth;
1540  namodels = numaCreate(ndewarp);
1541  dewa->namodels = namodels;
1542  for (i = 0; i < ndewarp; i++) {
1543  if ((dew = dewarpReadStream(fp)) == NULL) {
1544  L_ERROR("read fail for dew[%d]\n", procName, i);
1545  dewarpaDestroy(&dewa);
1546  return NULL;
1547  }
1548  dewarpaInsertDewarp(dewa, dew);
1549  numaAddNumber(namodels, dew->pageno);
1550  }
1551 
1552  /* Validate the models and insert reference models */
1553  dewarpaInsertRefModels(dewa, 0, 0);
1554  return dewa;
1555 }
1556 
1557 
1565 L_DEWARPA *
1566 dewarpaReadMem(const l_uint8 *data,
1567  size_t size)
1568 {
1569 FILE *fp;
1570 L_DEWARPA *dewa;
1571 
1572  PROCNAME("dewarpaReadMem");
1573 
1574  if (!data)
1575  return (L_DEWARPA *)ERROR_PTR("data not defined", procName, NULL);
1576  if ((fp = fopenReadFromMemory(data, size)) == NULL)
1577  return (L_DEWARPA *)ERROR_PTR("stream not opened", procName, NULL);
1578 
1579  dewa = dewarpaReadStream(fp);
1580  fclose(fp);
1581  if (!dewa) L_ERROR("dewa not read\n", procName);
1582  return dewa;
1583 }
1584 
1585 
1593 l_ok
1594 dewarpaWrite(const char *filename,
1595  L_DEWARPA *dewa)
1596 {
1597 l_int32 ret;
1598 FILE *fp;
1599 
1600  PROCNAME("dewarpaWrite");
1601 
1602  if (!filename)
1603  return ERROR_INT("filename not defined", procName, 1);
1604  if (!dewa)
1605  return ERROR_INT("dewa not defined", procName, 1);
1606 
1607  if ((fp = fopenWriteStream(filename, "wb")) == NULL)
1608  return ERROR_INT("stream not opened", procName, 1);
1609  ret = dewarpaWriteStream(fp, dewa);
1610  fclose(fp);
1611  if (ret)
1612  return ERROR_INT("dewa not written to stream", procName, 1);
1613  return 0;
1614 }
1615 
1616 
1624 l_ok
1626  L_DEWARPA *dewa)
1627 {
1628 l_int32 ndewarp, i, pageno;
1629 
1630  PROCNAME("dewarpaWriteStream");
1631 
1632  if (!fp)
1633  return ERROR_INT("stream not defined", procName, 1);
1634  if (!dewa)
1635  return ERROR_INT("dewa not defined", procName, 1);
1636 
1637  /* Generate the list of page numbers for which a model exists.
1638  * Note that no attempt is made to determine if the model is
1639  * valid, because that determination is associated with
1640  * using the model to remove the warping, which typically
1641  * can happen later, after all the models have been built. */
1642  dewarpaListPages(dewa);
1643  if (!dewa->namodels)
1644  return ERROR_INT("dewa->namodels not made", procName, 1);
1645  ndewarp = numaGetCount(dewa->namodels); /* with actual page models */
1646 
1647  fprintf(fp, "\nDewarpa Version %d\n", DEWARP_VERSION_NUMBER);
1648  fprintf(fp, "ndewarp = %d, maxpage = %d\n", ndewarp, dewa->maxpage);
1649  fprintf(fp, "sampling = %d, redfactor = %d, minlines = %d, maxdist = %d\n",
1650  dewa->sampling, dewa->redfactor, dewa->minlines, dewa->maxdist);
1651  fprintf(fp,
1652  "max_linecurv = %d, min_diff_linecurv = %d, max_diff_linecurv = %d\n",
1653  dewa->max_linecurv, dewa->min_diff_linecurv, dewa->max_diff_linecurv);
1654  fprintf(fp,
1655  "max_edgeslope = %d, max_edgecurv = %d, max_diff_edgecurv = %d\n",
1656  dewa->max_edgeslope, dewa->max_edgecurv, dewa->max_diff_edgecurv);
1657  fprintf(fp, "fullmodel = %d\n", dewa->useboth);
1658  for (i = 0; i < ndewarp; i++) {
1659  numaGetIValue(dewa->namodels, i, &pageno);
1660  dewarpWriteStream(fp, dewarpaGetDewarp(dewa, pageno));
1661  }
1662 
1663  return 0;
1664 }
1665 
1666 
1680 l_ok
1681 dewarpaWriteMem(l_uint8 **pdata,
1682  size_t *psize,
1683  L_DEWARPA *dewa)
1684 {
1685 l_int32 ret;
1686 FILE *fp;
1687 
1688  PROCNAME("dewarpaWriteMem");
1689 
1690  if (pdata) *pdata = NULL;
1691  if (psize) *psize = 0;
1692  if (!pdata)
1693  return ERROR_INT("&data not defined", procName, 1);
1694  if (!psize)
1695  return ERROR_INT("&size not defined", procName, 1);
1696  if (!dewa)
1697  return ERROR_INT("dewa not defined", procName, 1);
1698 
1699 #if HAVE_FMEMOPEN
1700  if ((fp = open_memstream((char **)pdata, psize)) == NULL)
1701  return ERROR_INT("stream not opened", procName, 1);
1702  ret = dewarpaWriteStream(fp, dewa);
1703  fputc('\0', fp);
1704  fclose(fp);
1705  *psize = *psize - 1;
1706 #else
1707  L_INFO("work-around: writing to a temp file\n", procName);
1708  #ifdef _WIN32
1709  if ((fp = fopenWriteWinTempfile()) == NULL)
1710  return ERROR_INT("tmpfile stream not opened", procName, 1);
1711  #else
1712  if ((fp = tmpfile()) == NULL)
1713  return ERROR_INT("tmpfile stream not opened", procName, 1);
1714  #endif /* _WIN32 */
1715  ret = dewarpaWriteStream(fp, dewa);
1716  rewind(fp);
1717  *pdata = l_binaryReadStream(fp, psize);
1718  fclose(fp);
1719 #endif /* HAVE_FMEMOPEN */
1720  return ret;
1721 }
L_DEWARPA * dewarpaRead(const char *filename)
dewarpaRead()
Definition: dewarp1.c:1453
L_DEWARPA * dewarpaReadStream(FILE *fp)
dewarpaReadStream()
Definition: dewarp1.c:1490
l_ok dewarpaUseBothArrays(L_DEWARPA *dewa, l_int32 useboth)
dewarpaUseBothArrays()
Definition: dewarp1.c:1044
l_ok dewarpaSetMaxDistance(L_DEWARPA *dewa, l_int32 maxdist)
dewarpaSetMaxDistance()
Definition: dewarp1.c:1109
L_DEWARP * dewarpCreateRef(l_int32 pageno, l_int32 refpage)
dewarpCreateRef()
Definition: dewarp1.c:498
void dewarpaDestroy(L_DEWARPA **pdewa)
dewarpaDestroy()
Definition: dewarp1.c:730
static l_int32 dewarpaExtendArraysToSize(L_DEWARPA *dewa, l_int32 size)
dewarpaExtendArraysToSize()
Definition: dewarp1.c:879
l_ok dewarpWriteStream(FILE *fp, L_DEWARP *dew)
dewarpWriteStream()
Definition: dewarp1.c:1344
l_ok dewarpaDestroyDewarp(L_DEWARPA *dewa, l_int32 pageno)
dewarpaDestroyDewarp()
Definition: dewarp1.c:769
l_ok dewarpaInsertDewarp(L_DEWARPA *dewa, L_DEWARP *dew)
dewarpaInsertDewarp()
Definition: dewarp1.c:812
void dewarpDestroy(L_DEWARP **pdew)
dewarpDestroy()
Definition: dewarp1.c:518
l_ok dewarpWrite(const char *filename, L_DEWARP *dew)
dewarpWrite()
Definition: dewarp1.c:1306
L_DEWARP * dewarpReadStream(FILE *fp)
dewarpReadStream()
Definition: dewarp1.c:1173
L_DEWARPA * dewarpaCreateFromPixacomp(PIXAC *pixac, l_int32 useboth, l_int32 sampling, l_int32 minlines, l_int32 maxdist)
dewarpaCreateFromPixacomp()
Definition: dewarp1.c:669
l_ok dewarpaSetCheckColumns(L_DEWARPA *dewa, l_int32 check_columns)
dewarpaSetCheckColumns()
Definition: dewarp1.c:1083
L_DEWARPA * dewarpaReadMem(const l_uint8 *data, size_t size)
dewarpaReadMem()
Definition: dewarp1.c:1566
l_ok dewarpaWriteStream(FILE *fp, L_DEWARPA *dewa)
dewarpaWriteStream()
Definition: dewarp1.c:1625
l_ok dewarpWriteMem(l_uint8 **pdata, size_t *psize, L_DEWARP *dew)
dewarpWriteMem()
Definition: dewarp1.c:1400
L_DEWARP * dewarpaGetDewarp(L_DEWARPA *dewa, l_int32 index)
dewarpaGetDewarp()
Definition: dewarp1.c:911
L_DEWARPA * dewarpaCreate(l_int32 nptrs, l_int32 sampling, l_int32 redfactor, l_int32 minlines, l_int32 maxdist)
dewarpaCreate()
Definition: dewarp1.c:580
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:1594
L_DEWARP * dewarpReadMem(const l_uint8 *data, size_t size)
dewarpReadMem()
Definition: dewarp1.c:1278
l_ok dewarpaWriteMem(l_uint8 **pdata, size_t *psize, L_DEWARPA *dewa)
dewarpaWriteMem()
Definition: dewarp1.c:1681
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:980
L_DEWARP * dewarpRead(const char *filename)
dewarpRead()
Definition: dewarp1.c:1133
l_ok dewarpBuildPageModel(L_DEWARP *dew, const char *debugfile)
dewarpBuildPageModel()
Definition: dewarp2.c:156
l_ok dewarpMinimize(L_DEWARP *dew)
dewarpMinimize()
Definition: dewarp3.c:731
l_ok dewarpaListPages(L_DEWARPA *dewa)
dewarpaListPages()
Definition: dewarp4.c:296
l_ok dewarpaInsertRefModels(L_DEWARPA *dewa, l_int32 notests, l_int32 debug)
dewarpaInsertRefModels()
Definition: dewarp4.c:454
#define DEWARP_VERSION_NUMBER
Definition: dewarp.h:110
l_ok fpixWriteStream(FILE *fp, FPIX *fpix)
fpixWriteStream()
Definition: fpix1.c:1692
void fpixDestroy(FPIX **pfpix)
fpixDestroy()
Definition: fpix1.c:292
FPIX * fpixReadStream(FILE *fp)
fpixReadStream()
Definition: fpix1.c:1580
l_ok numaAddNumber(NUMA *na, l_float32 val)
numaAddNumber()
Definition: numabasic.c:478
NUMA * numaCreate(l_int32 n)
numaCreate()
Definition: numabasic.c:194
void numaDestroy(NUMA **pna)
numaDestroy()
Definition: numabasic.c:366
l_int32 numaGetCount(NUMA *na)
numaGetCount()
Definition: numabasic.c:658
l_ok numaGetIValue(NUMA *na, l_int32 index, l_int32 *pival)
numaGetIValue()
Definition: numabasic.c:754
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:621
PIX * pixClone(PIX *pixs)
pixClone()
Definition: pix1.c:593
l_int32 pixacompGetOffset(PIXAC *pixac)
pixacompGetOffset()
Definition: pixcomp.c:1440
l_int32 pixacompGetCount(PIXAC *pixac)
pixacompGetCount()
Definition: pixcomp.c:1162
PIX * pixacompGetPix(PIXAC *pixac, l_int32 index)
pixacompGetPix()
Definition: pixcomp.c:1227
Definition: pix.h:579
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
Definition: array.h:71
Definition: pix.h:139
Definition: pix.h:654
l_uint8 * l_binaryReadStream(FILE *fp, size_t *pnbytes)
l_binaryReadStream()
Definition: utils2.c:1402
FILE * fopenReadFromMemory(const l_uint8 *data, size_t size)
fopenReadFromMemory()
Definition: utils2.c:2009
FILE * fopenWriteStream(const char *filename, const char *modestring)
fopenWriteStream()
Definition: utils2.c:1975
void * reallocNew(void **pindata, size_t oldsize, size_t newsize)
reallocNew()
Definition: utils2.c:1302
FILE * fopenWriteWinTempfile(void)
fopenWriteWinTempfile()
Definition: utils2.c:2055
FILE * fopenReadStream(const char *filename)
fopenReadStream()
Definition: utils2.c:1932