Leptonica  1.83.1
Image processing and image analysis suite
regutils.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 
27 
68 #ifdef HAVE_CONFIG_H
69 #include <config_auto.h>
70 #endif /* HAVE_CONFIG_H */
71 
72 #include <string.h>
73 #include "allheaders.h"
74 
75 extern l_int32 NumImageFileFormatExtensions;
76 extern const char *ImageFileFormatExtensions[];
77 
78 static char *getRootNameFromArgv0(const char *argv0);
79 
80 
81 /*--------------------------------------------------------------------*
82  * Regression test utilities *
83  *--------------------------------------------------------------------*/
122 l_ok
123 regTestSetup(l_int32 argc,
124  char **argv,
125  L_REGPARAMS **prp)
126 {
127 char *testname, *vers;
128 char errormsg[64];
129 L_REGPARAMS *rp;
130 
131  if (argc != 1 && argc != 2) {
132  snprintf(errormsg, sizeof(errormsg),
133  "Syntax: %s [ [compare] | generate | display ]", argv[0]);
134  return ERROR_INT(errormsg, __func__, 1);
135  }
136 
137  if ((testname = getRootNameFromArgv0(argv[0])) == NULL)
138  return ERROR_INT("invalid root", __func__, 1);
139 
140  setLeptDebugOK(1); /* required for testing */
141 
142  rp = (L_REGPARAMS *)LEPT_CALLOC(1, sizeof(L_REGPARAMS));
143  *prp = rp;
144  rp->testname = testname;
145  rp->index = -1; /* increment before each test */
146 
147  /* Initialize to true. A failure in any test is registered
148  * as a failure of the regression test. */
149  rp->success = TRUE;
150 
151  /* Make sure the lept/regout subdirectory exists */
152  lept_mkdir("lept/regout");
153 
154  /* Only open a stream to a temp file for the 'compare' case */
155  if (argc == 1 || !strcmp(argv[1], "compare")) {
156  rp->mode = L_REG_COMPARE;
157  rp->tempfile = stringNew("/tmp/lept/regout/regtest_output.txt");
158  rp->fp = fopenWriteStream(rp->tempfile, "wb");
159  if (rp->fp == NULL) {
160  rp->success = FALSE;
161  return ERROR_INT("stream not opened for tempfile", __func__, 1);
162  }
163  } else if (!strcmp(argv[1], "generate")) {
164  rp->mode = L_REG_GENERATE;
165  lept_mkdir("lept/golden");
166  } else if (!strcmp(argv[1], "display")) {
167  rp->mode = L_REG_DISPLAY;
168  rp->display = TRUE;
169  } else {
170  LEPT_FREE(rp);
171  snprintf(errormsg, sizeof(errormsg),
172  "Syntax: %s [ [generate] | compare | display ]", argv[0]);
173  return ERROR_INT(errormsg, __func__, 1);
174  }
175 
176  /* Print out test name and both the leptonica and
177  * image library versions */
178  lept_stderr("\n////////////////////////////////////////////////\n"
179  "//////////////// %s_reg ///////////////\n"
180  "////////////////////////////////////////////////\n",
181  rp->testname);
182  vers = getLeptonicaVersion();
183  lept_stderr("%s : ", vers);
184  LEPT_FREE(vers);
185  vers = getImagelibVersions();
186  lept_stderr("%s\n", vers);
187  LEPT_FREE(vers);
188 
189  rp->tstart = startTimerNested();
190  return 0;
191 }
192 
193 
206 l_ok
208 {
209 char result[512];
210 char *results_file; /* success/failure output in 'compare' mode */
211 char *text, *message;
212 l_int32 retval;
213 size_t nbytes;
214 
215  if (!rp)
216  return ERROR_INT("rp not defined", __func__, 1);
217 
218  lept_stderr("Time: %7.3f sec\n", stopTimerNested(rp->tstart));
219 
220  /* If generating golden files or running in display mode, release rp */
221  if (!rp->fp) {
222  LEPT_FREE(rp->testname);
223  LEPT_FREE(rp->tempfile);
224  LEPT_FREE(rp);
225  return 0;
226  }
227 
228  /* Compare mode: read back data from temp file */
229  fclose(rp->fp);
230  text = (char *)l_binaryRead(rp->tempfile, &nbytes);
231  LEPT_FREE(rp->tempfile);
232  if (!text) {
233  rp->success = FALSE;
234  LEPT_FREE(rp->testname);
235  LEPT_FREE(rp);
236  return ERROR_INT("text not returned", __func__, 1);
237  }
238 
239  /* Prepare result message */
240  if (rp->success)
241  snprintf(result, sizeof(result), "SUCCESS: %s_reg\n", rp->testname);
242  else
243  snprintf(result, sizeof(result), "FAILURE: %s_reg\n", rp->testname);
244  message = stringJoin(text, result);
245  LEPT_FREE(text);
246  results_file = stringNew("/tmp/lept/reg_results.txt");
247  fileAppendString(results_file, message);
248  retval = (rp->success) ? 0 : 1;
249  LEPT_FREE(results_file);
250  LEPT_FREE(message);
251 
252  LEPT_FREE(rp->testname);
253  LEPT_FREE(rp);
254  return retval;
255 }
256 
257 
268 l_ok
270  l_float32 val1,
271  l_float32 val2,
272  l_float32 delta)
273 {
274 l_float32 diff;
275 
276  if (!rp)
277  return ERROR_INT("rp not defined", __func__, 1);
278 
279  rp->index++;
280  diff = L_ABS(val2 - val1);
281 
282  /* Record on failure */
283  if (diff > delta) {
284  if (rp->fp) {
285  fprintf(rp->fp,
286  "Failure in %s_reg: value comparison for index %d\n"
287  "difference = %f but allowed delta = %f\n",
288  rp->testname, rp->index, diff, delta);
289  }
290  lept_stderr("Failure in %s_reg: value comparison for index %d\n"
291  "difference = %f but allowed delta = %f\n",
292  rp->testname, rp->index, diff, delta);
293  rp->success = FALSE;
294  }
295  return 0;
296 }
297 
298 
310 l_ok
312  l_uint8 *string1,
313  size_t bytes1,
314  l_uint8 *string2,
315  size_t bytes2)
316 {
317 l_int32 same;
318 char buf[256];
319 
320  if (!rp)
321  return ERROR_INT("rp not defined", __func__, 1);
322 
323  rp->index++;
324  l_binaryCompare(string1, bytes1, string2, bytes2, &same);
325 
326  /* Output on failure */
327  if (!same) {
328  /* Write the two strings to file */
329  snprintf(buf, sizeof(buf), "/tmp/lept/regout/string1_%d_%zu",
330  rp->index, bytes1);
331  l_binaryWrite(buf, "w", string1, bytes1);
332  snprintf(buf, sizeof(buf), "/tmp/lept/regout/string2_%d_%zu",
333  rp->index, bytes2);
334  l_binaryWrite(buf, "w", string2, bytes2);
335 
336  /* Report comparison failure */
337  snprintf(buf, sizeof(buf), "/tmp/lept/regout/string*_%d_*", rp->index);
338  if (rp->fp) {
339  fprintf(rp->fp,
340  "Failure in %s_reg: string comp for index %d; "
341  "written to %s\n", rp->testname, rp->index, buf);
342  }
343  lept_stderr("Failure in %s_reg: string comp for index %d; "
344  "written to %s\n", rp->testname, rp->index, buf);
345  rp->success = FALSE;
346  }
347  return 0;
348 }
349 
350 
365 l_ok
367  PIX *pix1,
368  PIX *pix2)
369 {
370 l_int32 same;
371 
372  if (!rp)
373  return ERROR_INT("rp not defined", __func__, 1);
374  if (!pix1 || !pix2) {
375  rp->success = FALSE;
376  return ERROR_INT("pix1 and pix2 not both defined", __func__, 1);
377  }
378 
379  rp->index++;
380  pixEqual(pix1, pix2, &same);
381 
382  /* Record on failure */
383  if (!same) {
384  if (rp->fp) {
385  fprintf(rp->fp, "Failure in %s_reg: pix comparison for index %d\n",
386  rp->testname, rp->index);
387  }
388  lept_stderr("Failure in %s_reg: pix comparison for index %d\n",
389  rp->testname, rp->index);
390  rp->success = FALSE;
391  }
392  return 0;
393 }
394 
395 
423 l_ok
425  PIX *pix1,
426  PIX *pix2,
427  l_int32 mindiff,
428  l_float32 maxfract,
429  l_int32 printstats)
430 {
431 l_int32 w, h, factor, similar;
432 
433  if (!rp)
434  return ERROR_INT("rp not defined", __func__, 1);
435  if (!pix1 || !pix2) {
436  rp->success = FALSE;
437  return ERROR_INT("pix1 and pix2 not both defined", __func__, 1);
438  }
439 
440  rp->index++;
441  pixGetDimensions(pix1, &w, &h, NULL);
442  factor = L_MAX(w, h) / 400;
443  factor = L_MAX(1, L_MIN(factor, 4)); /* between 1 and 4 */
444  pixTestForSimilarity(pix1, pix2, factor, mindiff, maxfract, 0.0,
445  &similar, printstats);
446 
447  /* Record on failure */
448  if (!similar) {
449  if (rp->fp) {
450  fprintf(rp->fp,
451  "Failure in %s_reg: pix similarity comp for index %d\n",
452  rp->testname, rp->index);
453  }
454  lept_stderr("Failure in %s_reg: pix similarity comp for index %d\n",
455  rp->testname, rp->index);
456  rp->success = FALSE;
457  }
458  return 0;
459 }
460 
461 
488 l_ok
490  const char *localname)
491 {
492 char *ext;
493 char namebuf[256];
494 l_int32 ret, same, format;
495 PIX *pix1, *pix2;
496 
497  if (!rp)
498  return ERROR_INT("rp not defined", __func__, 1);
499  if (!localname) {
500  rp->success = FALSE;
501  return ERROR_INT("local name not defined", __func__, 1);
502  }
503  if (rp->mode != L_REG_GENERATE && rp->mode != L_REG_COMPARE &&
504  rp->mode != L_REG_DISPLAY) {
505  rp->success = FALSE;
506  return ERROR_INT("invalid mode", __func__, 1);
507  }
508  rp->index++;
509 
510  /* If display mode, no generation and no testing */
511  if (rp->mode == L_REG_DISPLAY) return 0;
512 
513  /* Generate the golden file name; used in 'generate' and 'compare' */
514  splitPathAtExtension(localname, NULL, &ext);
515  snprintf(namebuf, sizeof(namebuf), "/tmp/lept/golden/%s_golden.%02d%s",
516  rp->testname, rp->index, ext);
517  LEPT_FREE(ext);
518 
519  /* Generate mode. No testing. */
520  if (rp->mode == L_REG_GENERATE) {
521  /* Save the file as a golden file */
522  ret = fileCopy(localname, namebuf);
523 #if 0 /* Enable for details on writing of golden files */
524  if (!ret) {
525  char *local = genPathname(localname, NULL);
526  char *golden = genPathname(namebuf, NULL);
527  L_INFO("Copy: %s to %s\n", __func__, local, golden);
528  LEPT_FREE(local);
529  LEPT_FREE(golden);
530  }
531 #endif
532  return ret;
533  }
534 
535  /* Compare mode: test and record on failure. This can be used
536  * for all image formats, as well as for all files of serialized
537  * data, such as boxa, pta, etc. In all cases except for
538  * GIF compressed images, we compare the files to see if they
539  * are identical. GIF doesn't support RGB images; to write
540  * a 32 bpp RGB image in GIF, we do a lossy quantization to
541  * 256 colors, so the cycle read-RGB/write-GIF is not idempotent.
542  * And although the read/write cycle for GIF images with bpp <= 8
543  * is idempotent in the image pixels, it is not idempotent in the
544  * actual file bytes; tests comparing file bytes before and after
545  * a GIF read/write cycle will fail. So for GIF we uncompress
546  * the two images and compare the actual pixels. PNG is both
547  * lossless and idempotent in file bytes on read/write, so it is
548  * not necessary to compare pixels. (Comparing pixels requires
549  * decompression, and thus would increase the regression test
550  * time. JPEG is lossy and not idempotent in the image pixels,
551  * so no tests are constructed that would require it. */
552  findFileFormat(localname, &format);
553  if (format == IFF_GIF) {
554  same = 0;
555  pix1 = pixRead(localname);
556  pix2 = pixRead(namebuf);
557  pixEqual(pix1, pix2, &same);
558  pixDestroy(&pix1);
559  pixDestroy(&pix2);
560  } else {
561  filesAreIdentical(localname, namebuf, &same);
562  }
563  if (!same) {
564  fprintf(rp->fp, "Failure in %s_reg, index %d: comparing %s with %s\n",
565  rp->testname, rp->index, localname, namebuf);
566  lept_stderr("Failure in %s_reg, index %d: comparing %s with %s\n",
567  rp->testname, rp->index, localname, namebuf);
568  rp->success = FALSE;
569  }
570 
571  return 0;
572 }
573 
574 
594 l_ok
596  l_int32 index1,
597  l_int32 index2)
598 {
599 char *name1, *name2;
600 char namebuf[256];
601 l_int32 same;
602 SARRAY *sa;
603 
604  if (!rp)
605  return ERROR_INT("rp not defined", __func__, 1);
606  if (index1 < 0 || index2 < 0) {
607  rp->success = FALSE;
608  return ERROR_INT("index1 and/or index2 is negative", __func__, 1);
609  }
610  if (index1 == index2) {
611  rp->success = FALSE;
612  return ERROR_INT("index1 must differ from index2", __func__, 1);
613  }
614 
615  rp->index++;
616  if (rp->mode != L_REG_COMPARE) return 0;
617 
618  /* Generate the golden file names */
619  snprintf(namebuf, sizeof(namebuf), "%s_golden.%02d", rp->testname, index1);
620  sa = getSortedPathnamesInDirectory("/tmp/lept/golden", namebuf, 0, 0);
621  if (sarrayGetCount(sa) != 1) {
622  sarrayDestroy(&sa);
623  rp->success = FALSE;
624  L_ERROR("golden file %s not found\n", __func__, namebuf);
625  return 1;
626  }
627  name1 = sarrayGetString(sa, 0, L_COPY);
628  sarrayDestroy(&sa);
629 
630  snprintf(namebuf, sizeof(namebuf), "%s_golden.%02d", rp->testname, index2);
631  sa = getSortedPathnamesInDirectory("/tmp/lept/golden", namebuf, 0, 0);
632  if (sarrayGetCount(sa) != 1) {
633  sarrayDestroy(&sa);
634  rp->success = FALSE;
635  LEPT_FREE(name1);
636  L_ERROR("golden file %s not found\n", __func__, namebuf);
637  return 1;
638  }
639  name2 = sarrayGetString(sa, 0, L_COPY);
640  sarrayDestroy(&sa);
641 
642  /* Test and record on failure */
643  filesAreIdentical(name1, name2, &same);
644  if (!same) {
645  fprintf(rp->fp,
646  "Failure in %s_reg, index %d: comparing %s with %s\n",
647  rp->testname, rp->index, name1, name2);
648  lept_stderr("Failure in %s_reg, index %d: comparing %s with %s\n",
649  rp->testname, rp->index, name1, name2);
650  rp->success = FALSE;
651  }
652 
653  LEPT_FREE(name1);
654  LEPT_FREE(name2);
655  return 0;
656 }
657 
658 
685 l_ok
687  PIX *pix,
688  l_int32 format)
689 {
690 char namebuf[256];
691 
692  if (!rp)
693  return ERROR_INT("rp not defined", __func__, 1);
694  if (!pix) {
695  rp->success = FALSE;
696  return ERROR_INT("pix not defined", __func__, 1);
697  }
698  if (format < 0 || format >= NumImageFileFormatExtensions) {
699  rp->success = FALSE;
700  return ERROR_INT("invalid format", __func__, 1);
701  }
702 
703  /* Use bmp format for testing if library for requested
704  * format for jpeg, png or tiff is not available */
705  changeFormatForMissingLib(&format);
706 
707  /* Generate the local file name */
708  snprintf(namebuf, sizeof(namebuf), "/tmp/lept/regout/%s.%02d.%s",
709  rp->testname, rp->index + 1, ImageFileFormatExtensions[format]);
710 
711  /* Write the local file */
712  if (pixGetDepth(pix) < 8)
713  pixSetPadBits(pix, 0);
714  pixWrite(namebuf, pix, format);
715 
716  /* Either write the golden file ("generate") or check the
717  local file against an existing golden file ("compare") */
718  regTestCheckFile(rp, namebuf);
719 
720  return 0;
721 }
722 
723 
754 l_ok
756  void *data,
757  size_t nbytes,
758  const char *ext)
759 {
760 char namebuf[256];
761 
762  if (!rp)
763  return ERROR_INT("rp not defined", __func__, 1);
764  if (!data || nbytes == 0) {
765  rp->success = FALSE;
766  return ERROR_INT("data not defined or size == 0", __func__, 1);
767  }
768 
769  /* Generate the local file name */
770  snprintf(namebuf, sizeof(namebuf), "/tmp/lept/regout/%s.%02d.%s",
771  rp->testname, rp->index + 1, ext);
772 
773  /* Write the local file */
774  l_binaryWrite(namebuf, "w", data, nbytes);
775 
776  /* Either write the golden file ("generate") or check the
777  local file against an existing golden file ("compare") */
778  regTestCheckFile(rp, namebuf);
779  return 0;
780 }
781 
782 
803 char *
805  l_int32 index,
806  l_int32 format)
807 {
808 char buf[64];
809 l_int32 ind;
810 
811  if (!rp)
812  return (char *)ERROR_PTR("rp not defined", __func__, NULL);
813 
814  ind = (index >= 0) ? index : rp->index;
815  snprintf(buf, sizeof(buf), "/tmp/lept/regout/%s.%02d.%s",
816  rp->testname, ind, ImageFileFormatExtensions[format]);
817  return stringNew(buf);
818 }
819 
820 
837 static char *
838 getRootNameFromArgv0(const char *argv0)
839 {
840 l_int32 len;
841 char *root;
842 
843  splitPathAtDirectory(argv0, NULL, &root);
844  if ((len = strlen(root)) <= 4) {
845  LEPT_FREE(root);
846  return (char *)ERROR_PTR("invalid argv0; too small", __func__, NULL);
847  }
848 
849 #ifndef _WIN32
850  {
851  char *newroot;
852  l_int32 loc;
853  if (stringFindSubstr(root, "-", &loc)) {
854  newroot = stringNew(root + loc + 1); /* strip out "lt-" */
855  LEPT_FREE(root);
856  root = newroot;
857  len = strlen(root);
858  }
859  len -= 4; /* remove the "_reg" suffix */
860  }
861 #else
862  if (strstr(root, ".exe") != NULL)
863  len -= 4;
864  if (strstr(root, "_reg") == root + len - 4)
865  len -= 4;
866 #endif /* ! _WIN32 */
867 
868  root[len] = '\0'; /* terminate */
869  return root;
870 }
l_ok pixEqual(PIX *pix1, PIX *pix2, l_int32 *psame)
pixEqual()
Definition: compare.c:156
l_ok pixTestForSimilarity(PIX *pix1, PIX *pix2, l_int32 factor, l_int32 mindiff, l_float32 maxfract, l_float32 maxave, l_int32 *psimilar, l_int32 details)
pixTestForSimilarity()
Definition: compare.c:1302
char * getImagelibVersions(void)
getImagelibVersions()
Definition: libversions.c:102
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:608
l_ok pixGetDimensions(const PIX *pix, l_int32 *pw, l_int32 *ph, l_int32 *pd)
pixGetDimensions()
Definition: pix1.c:1074
l_ok pixSetPadBits(PIX *pix, l_int32 val)
pixSetPadBits()
Definition: pix2.c:1346
@ L_COPY
Definition: pix.h:505
l_ok findFileFormat(const char *filename, l_int32 *pformat)
findFileFormat()
Definition: readfile.c:570
PIX * pixRead(const char *filename)
pixRead()
Definition: readfile.c:189
l_ok regTestSetup(l_int32 argc, char **argv, L_REGPARAMS **prp)
regTestSetup()
Definition: regutils.c:123
l_ok regTestCompareSimilarPix(L_REGPARAMS *rp, PIX *pix1, PIX *pix2, l_int32 mindiff, l_float32 maxfract, l_int32 printstats)
regTestCompareSimilarPix()
Definition: regutils.c:424
l_ok regTestCompareFiles(L_REGPARAMS *rp, l_int32 index1, l_int32 index2)
regTestCompareFiles()
Definition: regutils.c:595
l_ok regTestCompareStrings(L_REGPARAMS *rp, l_uint8 *string1, size_t bytes1, l_uint8 *string2, size_t bytes2)
regTestCompareStrings()
Definition: regutils.c:311
l_ok regTestWritePixAndCheck(L_REGPARAMS *rp, PIX *pix, l_int32 format)
regTestWritePixAndCheck()
Definition: regutils.c:686
static char * getRootNameFromArgv0(const char *argv0)
getRootNameFromArgv0()
Definition: regutils.c:838
l_ok regTestCheckFile(L_REGPARAMS *rp, const char *localname)
regTestCheckFile()
Definition: regutils.c:489
l_ok regTestComparePix(L_REGPARAMS *rp, PIX *pix1, PIX *pix2)
regTestComparePix()
Definition: regutils.c:366
char * regTestGenLocalFilename(L_REGPARAMS *rp, l_int32 index, l_int32 format)
regTestGenLocalFilename()
Definition: regutils.c:804
l_ok regTestCompareValues(L_REGPARAMS *rp, l_float32 val1, l_float32 val2, l_float32 delta)
regTestCompareValues()
Definition: regutils.c:269
l_ok regTestCleanup(L_REGPARAMS *rp)
regTestCleanup()
Definition: regutils.c:207
l_ok regTestWriteDataAndCheck(L_REGPARAMS *rp, void *data, size_t nbytes, const char *ext)
regTestWriteDataAndCheck()
Definition: regutils.c:755
char * sarrayGetString(SARRAY *sa, l_int32 index, l_int32 copyflag)
sarrayGetString()
Definition: sarray1.c:673
l_int32 sarrayGetCount(SARRAY *sa)
sarrayGetCount()
Definition: sarray1.c:617
void sarrayDestroy(SARRAY **psa)
sarrayDestroy()
Definition: sarray1.c:353
SARRAY * getSortedPathnamesInDirectory(const char *dirname, const char *substr, l_int32 first, l_int32 nfiles)
getSortedPathnamesInDirectory()
Definition: sarray1.c:1739
char * testname
Definition: regutils.h:120
l_int32 success
Definition: regutils.h:124
char * tempfile
Definition: regutils.h:121
l_int32 display
Definition: regutils.h:125
l_int32 index
Definition: regutils.h:123
l_int32 mode
Definition: regutils.h:122
L_TIMER tstart
Definition: regutils.h:126
FILE * fp
Definition: regutils.h:119
l_ok filesAreIdentical(const char *fname1, const char *fname2, l_int32 *psame)
filesAreIdentical()
Definition: utils1.c:333
void lept_stderr(const char *fmt,...)
lept_stderr()
Definition: utils1.c:306
L_TIMER startTimerNested(void)
startTimerNested(), stopTimerNested()
Definition: utils1.c:1051
char * getLeptonicaVersion(void)
getLeptonicaVersion()
Definition: utils1.c:960
char * stringNew(const char *src)
stringNew()
Definition: utils2.c:223
l_ok fileAppendString(const char *filename, const char *str)
fileAppendString()
Definition: utils2.c:1741
l_ok splitPathAtExtension(const char *pathname, char **pbasename, char **pextension)
splitPathAtExtension()
Definition: utils2.c:2796
l_ok l_binaryCompare(const l_uint8 *data1, size_t size1, const l_uint8 *data2, size_t size2, l_int32 *psame)
l_binaryCompare()
Definition: utils2.c:1653
l_ok splitPathAtDirectory(const char *pathname, char **pdir, char **ptail)
splitPathAtDirectory()
Definition: utils2.c:2728
FILE * fopenWriteStream(const char *filename, const char *modestring)
fopenWriteStream()
Definition: utils2.c:1905
l_int32 stringFindSubstr(const char *src, const char *sub, l_int32 *ploc)
stringFindSubstr()
Definition: utils2.c:995
char * genPathname(const char *dir, const char *fname)
genPathname()
Definition: utils2.c:3068
l_int32 lept_mkdir(const char *subdir)
lept_mkdir()
Definition: utils2.c:2138
char * stringJoin(const char *src1, const char *src2)
stringJoin()
Definition: utils2.c:506
l_ok l_binaryWrite(const char *filename, const char *operation, const void *data, size_t nbytes)
l_binaryWrite()
Definition: utils2.c:1519
l_uint8 * l_binaryRead(const char *filename, size_t *pnbytes)
l_binaryRead()
Definition: utils2.c:1310
l_ok fileCopy(const char *srcfile, const char *newfile)
fileCopy()
Definition: utils2.c:1687