Leptonica  1.82.0
Image processing and image analysis suite
utils1.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 
106 #ifdef HAVE_CONFIG_H
107 #include <config_auto.h>
108 #endif /* HAVE_CONFIG_H */
109 
110 #ifdef _WIN32
111 #include <windows.h>
112 #endif /* _WIN32 */
113 
114 #include <time.h>
115 #include "allheaders.h"
116 #include <math.h>
117 
118  /* Global for controlling message output at runtime */
119 LEPT_DLL l_int32 LeptMsgSeverity = DEFAULT_SEVERITY;
120 
121 #define DEBUG_SEV 0
122 
123 /*----------------------------------------------------------------------*
124  * Control of error, warning and info messages *
125  *----------------------------------------------------------------------*/
142 l_int32
143 setMsgSeverity(l_int32 newsev)
144 {
145 l_int32 oldsev;
146 char *envsev;
147 
148  oldsev = LeptMsgSeverity;
149  if (newsev == L_SEVERITY_EXTERNAL) {
150  envsev = getenv("LEPT_MSG_SEVERITY");
151  if (envsev) {
152  LeptMsgSeverity = atoi(envsev);
153 #if DEBUG_SEV
154  L_INFO("message severity set to external\n", "setMsgSeverity");
155 #endif /* DEBUG_SEV */
156  } else {
157 #if DEBUG_SEV
158  L_WARNING("environment var LEPT_MSG_SEVERITY not defined\n",
159  "setMsgSeverity");
160 #endif /* DEBUG_SEV */
161  }
162  } else {
163  LeptMsgSeverity = newsev;
164 #if DEBUG_SEV
165  L_INFO("message severity set to %d\n", "setMsgSeverity", newsev);
166 #endif /* DEBUG_SEV */
167  }
168 
169  return oldsev;
170 }
171 
172 
173 /*----------------------------------------------------------------------*
174  * Error return functions, invoked by macros *
175  *----------------------------------------------------------------------*
176  * *
177  * (1) These error functions print messages to stderr and allow *
178  * exit from the function that called them. *
179  * (2) They must be invoked only by the macros ERROR_INT, *
180  * ERROR_FLOAT and ERROR_PTR, which are in environ.h *
181  * (3) The print output can be disabled at compile time, either *
182  * by using -DNO_CONSOLE_IO or by setting LeptMsgSeverity. *
183  *----------------------------------------------------------------------*/
192 l_int32
193 returnErrorInt(const char *msg,
194  const char *procname,
195  l_int32 ival)
196 {
197  lept_stderr("Error in %s: %s\n", procname, msg);
198  return ival;
199 }
200 
201 
210 l_float32
211 returnErrorFloat(const char *msg,
212  const char *procname,
213  l_float32 fval)
214 {
215  lept_stderr("Error in %s: %s\n", procname, msg);
216  return fval;
217 }
218 
219 
228 void *
229 returnErrorPtr(const char *msg,
230  const char *procname,
231  void *pval)
232 {
233  lept_stderr("Error in %s: %s\n", procname, msg);
234  return pval;
235 }
236 
237 
238 /*------------------------------------------------------------------------*
239  * Runtime redirection of stderr *
240  *------------------------------------------------------------------------*
241  * *
242  * The user can provide a callback function to redirect messages *
243  * that would otherwise go to stderr. Here are two examples: *
244  * (1) to stop all messages: *
245  * void send_to_devnull(const char *msg) {} *
246  * (2) to write to the system logger: *
247  * void send_to_syslog(const char *msg) { *
248  * syslog(1, msg); *
249  * } *
250  * These would then be registered using *
251  * leptSetStderrHandler(send_to_devnull); *
252  * and *
253  * leptSetStderrHandler(send_to_syslog); *
254  *------------------------------------------------------------------------*/
255  /* By default, all messages go to stderr */
256 static void lept_default_stderr_handler(const char *formatted_msg)
257 {
258  if (formatted_msg)
259  fputs(formatted_msg, stderr);
260 }
261 
262  /* The stderr callback handler is private to leptonica.
263  * By default it writes to stderr. */
264 void (*stderr_handler)(const char *) = lept_default_stderr_handler;
265 
266 
280 void leptSetStderrHandler(void (*handler)(const char *))
281 {
282  if (handler)
283  stderr_handler = handler;
284  else
285  stderr_handler = lept_default_stderr_handler;
286 }
287 
288 
289 #define MAX_DEBUG_MESSAGE 2000
306 void lept_stderr(const char *fmt, ...)
307 {
308 va_list args;
309 char msg[MAX_DEBUG_MESSAGE];
310 l_int32 n;
311 
312  va_start(args, fmt);
313  n = vsnprintf(msg, sizeof(msg), fmt, args);
314  va_end(args);
315  if (n < 0)
316  return;
317  (*stderr_handler)(msg);
318 }
319 
320 
321 /*--------------------------------------------------------------------*
322  * Test files for equivalence *
323  *--------------------------------------------------------------------*/
332 l_ok
333 filesAreIdentical(const char *fname1,
334  const char *fname2,
335  l_int32 *psame)
336 {
337 l_int32 i, same;
338 size_t nbytes1, nbytes2;
339 l_uint8 *array1, *array2;
340 
341  PROCNAME("filesAreIdentical");
342 
343  if (!psame)
344  return ERROR_INT("&same not defined", procName, 1);
345  *psame = 0;
346  if (!fname1 || !fname2)
347  return ERROR_INT("both names not defined", procName, 1);
348 
349  nbytes1 = nbytesInFile(fname1);
350  nbytes2 = nbytesInFile(fname2);
351  if (nbytes1 != nbytes2)
352  return 0;
353 
354  if ((array1 = l_binaryRead(fname1, &nbytes1)) == NULL)
355  return ERROR_INT("array1 not read", procName, 1);
356  if ((array2 = l_binaryRead(fname2, &nbytes2)) == NULL) {
357  LEPT_FREE(array1);
358  return ERROR_INT("array2 not read", procName, 1);
359  }
360  same = 1;
361  for (i = 0; i < nbytes1; i++) {
362  if (array1[i] != array2[i]) {
363  same = 0;
364  break;
365  }
366  }
367  LEPT_FREE(array1);
368  LEPT_FREE(array2);
369  *psame = same;
370 
371  return 0;
372 }
373 
374 
375 /*--------------------------------------------------------------------------*
376  * 16 and 32 bit byte-swapping on big endian and little endian machines *
377  *--------------------------------------------------------------------------*
378  * *
379  * These are typically used for I/O conversions: *
380  * (1) endian conversion for data that was read from a file *
381  * (2) endian conversion on data before it is written to a file *
382  *--------------------------------------------------------------------------*/
383 
384 /*--------------------------------------------------------------------*
385  * 16-bit byte swapping *
386  *--------------------------------------------------------------------*/
387 #ifdef L_BIG_ENDIAN
388 
389 l_uint16
390 convertOnBigEnd16(l_uint16 shortin)
391 {
392  return ((shortin << 8) | (shortin >> 8));
393 }
394 
395 l_uint16
396 convertOnLittleEnd16(l_uint16 shortin)
397 {
398  return shortin;
399 }
400 
401 #else /* L_LITTLE_ENDIAN */
402 
403 l_uint16
404 convertOnLittleEnd16(l_uint16 shortin)
405 {
406  return ((shortin << 8) | (shortin >> 8));
407 }
408 
409 l_uint16
410 convertOnBigEnd16(l_uint16 shortin)
411 {
412  return shortin;
413 }
414 
415 #endif /* L_BIG_ENDIAN */
416 
417 
418 /*--------------------------------------------------------------------*
419  * 32-bit byte swapping *
420  *--------------------------------------------------------------------*/
421 #ifdef L_BIG_ENDIAN
422 
423 l_uint32
424 convertOnBigEnd32(l_uint32 wordin)
425 {
426  return ((wordin << 24) | ((wordin << 8) & 0x00ff0000) |
427  ((wordin >> 8) & 0x0000ff00) | (wordin >> 24));
428 }
429 
430 l_uint32
431 convertOnLittleEnd32(l_uint32 wordin)
432 {
433  return wordin;
434 }
435 
436 #else /* L_LITTLE_ENDIAN */
437 
438 l_uint32
439 convertOnLittleEnd32(l_uint32 wordin)
440 {
441  return ((wordin << 24) | ((wordin << 8) & 0x00ff0000) |
442  ((wordin >> 8) & 0x0000ff00) | (wordin >> 24));
443 }
444 
445 l_uint32
446 convertOnBigEnd32(l_uint32 wordin)
447 {
448  return wordin;
449 }
450 
451 #endif /* L_BIG_ENDIAN */
452 
453 
454 /*---------------------------------------------------------------------*
455  * File corruption and byte replacement operations *
456  *---------------------------------------------------------------------*/
477 l_ok
478 fileCorruptByDeletion(const char *filein,
479  l_float32 loc,
480  l_float32 size,
481  const char *fileout)
482 {
483 l_int32 i, locb, sizeb, rembytes;
484 size_t inbytes, outbytes;
485 l_uint8 *datain, *dataout;
486 
487  PROCNAME("fileCorruptByDeletion");
488 
489  if (!filein || !fileout)
490  return ERROR_INT("filein and fileout not both specified", procName, 1);
491  if (loc < 0.0 || loc >= 1.0)
492  return ERROR_INT("loc must be in [0.0 ... 1.0)", procName, 1);
493  if (size <= 0.0)
494  return ERROR_INT("size must be > 0.0", procName, 1);
495  if (loc + size > 1.0)
496  size = 1.0 - loc;
497 
498  datain = l_binaryRead(filein, &inbytes);
499  locb = (l_int32)(loc * inbytes + 0.5);
500  locb = L_MIN(locb, inbytes - 1);
501  sizeb = (l_int32)(size * inbytes + 0.5);
502  sizeb = L_MAX(1, sizeb);
503  sizeb = L_MIN(sizeb, inbytes - locb); /* >= 1 */
504  L_INFO("Removed %d bytes at location %d\n", procName, sizeb, locb);
505  rembytes = inbytes - locb - sizeb; /* >= 0; to be copied, after excision */
506 
507  outbytes = inbytes - sizeb;
508  dataout = (l_uint8 *)LEPT_CALLOC(outbytes, 1);
509  for (i = 0; i < locb; i++)
510  dataout[i] = datain[i];
511  for (i = 0; i < rembytes; i++)
512  dataout[locb + i] = datain[locb + sizeb + i];
513  l_binaryWrite(fileout, "w", dataout, outbytes);
514 
515  LEPT_FREE(datain);
516  LEPT_FREE(dataout);
517  return 0;
518 }
519 
520 
541 l_ok
542 fileCorruptByMutation(const char *filein,
543  l_float32 loc,
544  l_float32 size,
545  const char *fileout)
546 {
547 l_int32 i, locb, sizeb;
548 size_t bytes;
549 l_uint8 *data;
550 
551  PROCNAME("fileCorruptByMutation");
552 
553  if (!filein || !fileout)
554  return ERROR_INT("filein and fileout not both specified", procName, 1);
555  if (loc < 0.0 || loc >= 1.0)
556  return ERROR_INT("loc must be in [0.0 ... 1.0)", procName, 1);
557  if (size <= 0.0)
558  return ERROR_INT("size must be > 0.0", procName, 1);
559  if (loc + size > 1.0)
560  size = 1.0 - loc;
561 
562  data = l_binaryRead(filein, &bytes);
563  locb = (l_int32)(loc * bytes + 0.5);
564  locb = L_MIN(locb, bytes - 1);
565  sizeb = (l_int32)(size * bytes + 0.5);
566  sizeb = L_MAX(1, sizeb);
567  sizeb = L_MIN(sizeb, bytes - locb); /* >= 1 */
568  L_INFO("Randomizing %d bytes at location %d\n", procName, sizeb, locb);
569 
570  /* Make an array of random bytes and do the substitution */
571  for (i = 0; i < sizeb; i++) {
572  data[locb + i] =
573  (l_uint8)(255.9 * ((l_float64)rand() / (l_float64)RAND_MAX));
574  }
575 
576  l_binaryWrite(fileout, "w", data, bytes);
577  LEPT_FREE(data);
578  return 0;
579 }
580 
581 
602 l_ok
603 fileReplaceBytes(const char *filein,
604  l_int32 start,
605  l_int32 nbytes,
606  l_uint8 *newdata,
607  size_t newsize,
608  const char *fileout)
609 {
610 l_int32 i, index;
611 size_t inbytes, outbytes;
612 l_uint8 *datain, *dataout;
613 
614  PROCNAME("fileReplaceBytes");
615 
616  if (!filein || !fileout)
617  return ERROR_INT("filein and fileout not both specified", procName, 1);
618 
619  datain = l_binaryRead(filein, &inbytes);
620  if (start + nbytes > inbytes)
621  L_WARNING("start + nbytes > length(filein) = %zu\n", procName, inbytes);
622 
623  if (!newdata) newsize = 0;
624  outbytes = inbytes - nbytes + newsize;
625  if ((dataout = (l_uint8 *)LEPT_CALLOC(outbytes, 1)) == NULL) {
626  LEPT_FREE(datain);
627  return ERROR_INT("calloc fail for dataout", procName, 1);
628  }
629 
630  for (i = 0; i < start; i++)
631  dataout[i] = datain[i];
632  for (i = start; i < start + newsize; i++)
633  dataout[i] = newdata[i - start];
634  index = start + nbytes; /* for datain */
635  start += newsize; /* for dataout */
636  for (i = start; i < outbytes; i++, index++)
637  dataout[i] = datain[index];
638  l_binaryWrite(fileout, "w", dataout, outbytes);
639 
640  LEPT_FREE(datain);
641  LEPT_FREE(dataout);
642  return 0;
643 }
644 
645 
646 /*---------------------------------------------------------------------*
647  * Generate random integer in given interval *
648  *---------------------------------------------------------------------*/
658 l_ok
660  l_int32 end,
661  l_int32 seed,
662  l_int32 *pval)
663 {
664 l_float64 range;
665 
666  PROCNAME("genRandomIntOnInterval");
667 
668  if (!pval)
669  return ERROR_INT("&val not defined", procName, 1);
670  *pval = 0;
671  if (end < start)
672  return ERROR_INT("invalid range", procName, 1);
673 
674  if (seed > 0) srand(seed);
675  range = (l_float64)(end - start + 1);
676  *pval = start + (l_int32)((l_float64)range *
677  ((l_float64)rand() / (l_float64)RAND_MAX));
678  return 0;
679 }
680 
681 
682 /*---------------------------------------------------------------------*
683  * Simple math function *
684  *---------------------------------------------------------------------*/
699 l_int32
700 lept_roundftoi(l_float32 fval)
701 {
702  return (fval >= 0.0) ? (l_int32)(fval + 0.5) : (l_int32)(fval - 0.5);
703 }
704 
705 
706 /*---------------------------------------------------------------------*
707  * 64-bit hash functions *
708  *---------------------------------------------------------------------*/
731 l_ok
732 l_hashStringToUint64(const char *str,
733  l_uint64 *phash)
734 {
735 l_uint64 hash, mulp;
736 
737  PROCNAME("l_hashStringToUint64");
738 
739  if (phash) *phash = 0;
740  if (!str || (str[0] == '\0'))
741  return ERROR_INT("str not defined or empty", procName, 1);
742  if (!phash)
743  return ERROR_INT("&hash not defined", procName, 1);
744 
745  mulp = 26544357894361247; /* prime, about 1/700 of the max uint64 */
746  hash = 104395301;
747  while (*str) {
748  hash += (*str++ * mulp) ^ (hash >> 7); /* shift [1...23] are ok */
749  }
750  *phash = hash ^ (hash << 37);
751  return 0;
752 }
753 
754 
770 l_ok
771 l_hashStringToUint64Fast(const char *str,
772  l_uint64 *phash)
773 {
774 l_uint64 h;
775 l_uint8 *p;
776 
777  PROCNAME("l_hashStringToUint64Fast");
778 
779  if (phash) *phash = 0;
780  if (!str || (str[0] == '\0'))
781  return ERROR_INT("str not defined or empty", procName, 1);
782  if (!phash)
783  return ERROR_INT("&hash not defined", procName, 1);
784 
785  h = 0;
786  for (p = (l_uint8 *)str; *p != '\0'; p++)
787  h = 37 * h + *p; /* 37 is good prime number for this */
788  *phash = h;
789  return 0;
790 }
791 
792 
806 l_ok
808  l_int32 y,
809  l_uint64 *phash)
810 {
811  PROCNAME("l_hashPtToUint64");
812 
813  if (!phash)
814  return ERROR_INT("&hash not defined", procName, 1);
815 
816  *phash = (l_uint64)(2173249142.3849 * x + 3763193258.6227 * y);
817  return 0;
818 }
819 
820 
836 l_ok
837 l_hashFloat64ToUint64(l_float64 val,
838  l_uint64 *phash)
839 {
840  PROCNAME("l_hashFloatToUint64");
841 
842  if (!phash)
843  return ERROR_INT("&hash not defined", procName, 1);
844  val = (val >= 0.0) ? 847019.66701 * val : -217324.91613 * val;
845  *phash = (l_uint64)val;
846  return 0;
847 }
848 
849 
850 /*---------------------------------------------------------------------*
851  * Prime finders *
852  *---------------------------------------------------------------------*/
860 l_ok
861 findNextLargerPrime(l_int32 start,
862  l_uint32 *pprime)
863 {
864 l_int32 i, is_prime;
865 
866  PROCNAME("findNextLargerPrime");
867 
868  if (!pprime)
869  return ERROR_INT("&prime not defined", procName, 1);
870  *pprime = 0;
871  if (start <= 0)
872  return ERROR_INT("start must be > 0", procName, 1);
873 
874  for (i = start + 1; ; i++) {
875  lept_isPrime(i, &is_prime, NULL);
876  if (is_prime) {
877  *pprime = i;
878  return 0;
879  }
880  }
881 
882  return ERROR_INT("prime not found!", procName, 1);
883 }
884 
885 
895 l_ok
896 lept_isPrime(l_uint64 n,
897  l_int32 *pis_prime,
898  l_uint32 *pfactor)
899 {
900 l_uint32 div;
901 l_uint64 limit, ratio;
902 
903  PROCNAME("lept_isPrime");
904 
905  if (pis_prime) *pis_prime = 0;
906  if (pfactor) *pfactor = 0;
907  if (!pis_prime)
908  return ERROR_INT("&is_prime not defined", procName, 1);
909  if (n <= 0)
910  return ERROR_INT("n must be > 0", procName, 1);
911 
912  if (n % 2 == 0) {
913  if (pfactor) *pfactor = 2;
914  return 0;
915  }
916 
917  limit = (l_uint64)sqrt((l_float64)n);
918  for (div = 3; div < limit; div += 2) {
919  ratio = n / div;
920  if (ratio * div == n) {
921  if (pfactor) *pfactor = div;
922  return 0;
923  }
924  }
925 
926  *pis_prime = 1;
927  return 0;
928 }
929 
930 
931 /*---------------------------------------------------------------------*
932  * Gray code conversion *
933  *---------------------------------------------------------------------*/
946 l_uint32
947 convertIntToGrayCode(l_uint32 val)
948 {
949  return (val >> 1) ^ val;
950 }
951 
952 
959 l_uint32
960 convertGrayCodeToInt(l_uint32 val)
961 {
962 l_uint32 shift;
963 
964  for (shift = 1; shift < 32; shift <<= 1)
965  val ^= val >> shift;
966  return val;
967 }
968 
969 
970 /*---------------------------------------------------------------------*
971  * Leptonica version number *
972  *---------------------------------------------------------------------*/
981 char *
983 {
984 size_t bufsize = 100;
985 
986  char *version = (char *)LEPT_CALLOC(bufsize, sizeof(char));
987 
988 #ifdef _MSC_VER
989  #ifdef _USRDLL
990  char dllStr[] = "DLL";
991  #else
992  char dllStr[] = "LIB";
993  #endif
994  #ifdef _DEBUG
995  char debugStr[] = "Debug";
996  #else
997  char debugStr[] = "Release";
998  #endif
999  #ifdef _M_IX86
1000  char bitStr[] = " x86";
1001  #elif _M_X64
1002  char bitStr[] = " x64";
1003  #else
1004  char bitStr[] = "";
1005  #endif
1006  snprintf(version, bufsize, "leptonica-%d.%d.%d (%s, %s) [MSC v.%d %s %s%s]",
1007  LIBLEPT_MAJOR_VERSION, LIBLEPT_MINOR_VERSION, LIBLEPT_PATCH_VERSION,
1008  __DATE__, __TIME__, _MSC_VER, dllStr, debugStr, bitStr);
1009 
1010 #else
1011 
1012  snprintf(version, bufsize, "leptonica-%d.%d.%d", LIBLEPT_MAJOR_VERSION,
1013  LIBLEPT_MINOR_VERSION, LIBLEPT_PATCH_VERSION);
1014 
1015 #endif /* _MSC_VER */
1016  return version;
1017 }
1018 
1019 
1020 /*---------------------------------------------------------------------*
1021  * Timing procs *
1022  *---------------------------------------------------------------------*/
1023 #if !defined(_WIN32) && !defined(__Fuchsia__)
1024 
1025 #include <sys/time.h>
1026 #include <sys/resource.h>
1027 
1028 static struct rusage rusage_before;
1029 static struct rusage rusage_after;
1030 
1040 void
1042 {
1043  getrusage(RUSAGE_SELF, &rusage_before);
1044 }
1045 
1046 l_float32
1047 stopTimer(void)
1048 {
1049 l_int32 tsec, tusec;
1050 
1051  getrusage(RUSAGE_SELF, &rusage_after);
1052 
1053  tsec = rusage_after.ru_utime.tv_sec - rusage_before.ru_utime.tv_sec;
1054  tusec = rusage_after.ru_utime.tv_usec - rusage_before.ru_utime.tv_usec;
1055  return (tsec + ((l_float32)tusec) / 1000000.0);
1056 }
1057 
1058 
1072 L_TIMER
1074 {
1075 struct rusage *rusage_start;
1076 
1077  rusage_start = (struct rusage *)LEPT_CALLOC(1, sizeof(struct rusage));
1078  getrusage(RUSAGE_SELF, rusage_start);
1079  return rusage_start;
1080 }
1081 
1082 l_float32
1083 stopTimerNested(L_TIMER rusage_start)
1084 {
1085 l_int32 tsec, tusec;
1086 struct rusage rusage_stop;
1087 
1088  getrusage(RUSAGE_SELF, &rusage_stop);
1089 
1090  tsec = rusage_stop.ru_utime.tv_sec -
1091  ((struct rusage *)rusage_start)->ru_utime.tv_sec;
1092  tusec = rusage_stop.ru_utime.tv_usec -
1093  ((struct rusage *)rusage_start)->ru_utime.tv_usec;
1094  LEPT_FREE(rusage_start);
1095  return (tsec + ((l_float32)tusec) / 1000000.0);
1096 }
1097 
1098 
1106 void
1107 l_getCurrentTime(l_int32 *sec,
1108  l_int32 *usec)
1109 {
1110 struct timeval tv;
1111 
1112  gettimeofday(&tv, NULL);
1113  if (sec) *sec = (l_int32)tv.tv_sec;
1114  if (usec) *usec = (l_int32)tv.tv_usec;
1115 }
1116 
1117 #elif defined(__Fuchsia__) /* resource.h not implemented on Fuchsia. */
1118 
1119  /* Timer functions are used for testing and debugging, and
1120  * are stubbed out. If they are needed in the future, they
1121  * can be implemented in Fuchsia using the zircon syscall
1122  * zx_object_get_info() in ZX_INFOR_THREAD_STATS mode. */
1123 void
1124 startTimer(void)
1125 {
1126 }
1127 
1128 l_float32
1129 stopTimer(void)
1130 {
1131  return 0.0;
1132 }
1133 
1134 L_TIMER
1135 startTimerNested(void)
1136 {
1137  return NULL;
1138 }
1139 
1140 l_float32
1141 stopTimerNested(L_TIMER rusage_start)
1142 {
1143  return 0.0;
1144 }
1145 
1146 void
1147 l_getCurrentTime(l_int32 *sec,
1148  l_int32 *usec)
1149 {
1150 }
1151 
1152 #else /* _WIN32 : resource.h not implemented under Windows */
1153 
1154  /* Note: if division by 10^7 seems strange, the time is expressed
1155  * as the number of 100-nanosecond intervals that have elapsed
1156  * since 12:00 A.M. January 1, 1601. */
1157 
1158 static ULARGE_INTEGER utime_before;
1159 static ULARGE_INTEGER utime_after;
1160 
1161 void
1162 startTimer(void)
1163 {
1164 HANDLE this_process;
1165 FILETIME start, stop, kernel, user;
1166 
1167  this_process = GetCurrentProcess();
1168 
1169  GetProcessTimes(this_process, &start, &stop, &kernel, &user);
1170 
1171  utime_before.LowPart = user.dwLowDateTime;
1172  utime_before.HighPart = user.dwHighDateTime;
1173 }
1174 
1175 l_float32
1176 stopTimer(void)
1177 {
1178 HANDLE this_process;
1179 FILETIME start, stop, kernel, user;
1180 ULONGLONG hnsec; /* in units of hecto-nanosecond (100 ns) intervals */
1181 
1182  this_process = GetCurrentProcess();
1183 
1184  GetProcessTimes(this_process, &start, &stop, &kernel, &user);
1185 
1186  utime_after.LowPart = user.dwLowDateTime;
1187  utime_after.HighPart = user.dwHighDateTime;
1188  hnsec = utime_after.QuadPart - utime_before.QuadPart;
1189  return (l_float32)(signed)hnsec / 10000000.0;
1190 }
1191 
1192 L_TIMER
1193 startTimerNested(void)
1194 {
1195 HANDLE this_process;
1196 FILETIME start, stop, kernel, user;
1197 ULARGE_INTEGER *utime_start;
1198 
1199  this_process = GetCurrentProcess();
1200 
1201  GetProcessTimes (this_process, &start, &stop, &kernel, &user);
1202 
1203  utime_start = (ULARGE_INTEGER *)LEPT_CALLOC(1, sizeof(ULARGE_INTEGER));
1204  utime_start->LowPart = user.dwLowDateTime;
1205  utime_start->HighPart = user.dwHighDateTime;
1206  return utime_start;
1207 }
1208 
1209 l_float32
1210 stopTimerNested(L_TIMER utime_start)
1211 {
1212 HANDLE this_process;
1213 FILETIME start, stop, kernel, user;
1214 ULARGE_INTEGER utime_stop;
1215 ULONGLONG hnsec; /* in units of 100 ns intervals */
1216 
1217  this_process = GetCurrentProcess ();
1218 
1219  GetProcessTimes (this_process, &start, &stop, &kernel, &user);
1220 
1221  utime_stop.LowPart = user.dwLowDateTime;
1222  utime_stop.HighPart = user.dwHighDateTime;
1223  hnsec = utime_stop.QuadPart - ((ULARGE_INTEGER *)utime_start)->QuadPart;
1224  LEPT_FREE(utime_start);
1225  return (l_float32)(signed)hnsec / 10000000.0;
1226 }
1227 
1228 void
1229 l_getCurrentTime(l_int32 *sec,
1230  l_int32 *usec)
1231 {
1232 ULARGE_INTEGER utime, birthunix;
1233 FILETIME systemtime;
1234 LONGLONG birthunixhnsec = 116444736000000000; /*in units of 100 ns */
1235 LONGLONG usecs;
1236 
1237  GetSystemTimeAsFileTime(&systemtime);
1238  utime.LowPart = systemtime.dwLowDateTime;
1239  utime.HighPart = systemtime.dwHighDateTime;
1240 
1241  birthunix.LowPart = (DWORD) birthunixhnsec;
1242  birthunix.HighPart = birthunixhnsec >> 32;
1243 
1244  usecs = (LONGLONG) ((utime.QuadPart - birthunix.QuadPart) / 10);
1245 
1246  if (sec) *sec = (l_int32) (usecs / 1000000);
1247  if (usec) *usec = (l_int32) (usecs % 1000000);
1248 }
1249 
1250 #endif
1251 
1252 
1267 L_WALLTIMER *
1269 {
1270 L_WALLTIMER *timer;
1271 
1272  timer = (L_WALLTIMER *)LEPT_CALLOC(1, sizeof(L_WALLTIMER));
1273  l_getCurrentTime(&timer->start_sec, &timer->start_usec);
1274  return timer;
1275 }
1276 
1283 l_float32
1285 {
1286 l_int32 tsec, tusec;
1287 L_WALLTIMER *timer;
1288 
1289  PROCNAME("stopWallTimer");
1290 
1291  if (!ptimer)
1292  return (l_float32)ERROR_FLOAT("&timer not defined", procName, 0.0);
1293  timer = *ptimer;
1294  if (!timer)
1295  return (l_float32)ERROR_FLOAT("timer not defined", procName, 0.0);
1296 
1297  l_getCurrentTime(&timer->stop_sec, &timer->stop_usec);
1298  tsec = timer->stop_sec - timer->start_sec;
1299  tusec = timer->stop_usec - timer->start_usec;
1300  LEPT_FREE(timer);
1301  *ptimer = NULL;
1302  return (tsec + ((l_float32)tusec) / 1000000.0);
1303 }
1304 
1305 
1318 char *
1320 {
1321 char buf[128] = "", sep = 'Z';
1322 l_int32 gmt_offset, relh, relm;
1323 time_t ut, lt;
1324 struct tm Tm;
1325 struct tm *tptr = &Tm;
1326 
1327  ut = time(NULL);
1328 
1329  /* This generates a second "time_t" value by calling "gmtime" to
1330  fill in a "tm" structure expressed as UTC and then calling
1331  "mktime", which expects a "tm" structure expressed as the
1332  local time. The result is a value that is offset from the
1333  value returned by the "time" function by the local UTC offset.
1334  "tm_isdst" is set to -1 to tell "mktime" to determine for
1335  itself whether DST is in effect. This is necessary because
1336  "gmtime" always sets "tm_isdst" to 0, which would tell
1337  "mktime" to presume that DST is not in effect. */
1338 #ifdef _WIN32
1339  #ifdef _MSC_VER
1340  gmtime_s(tptr, &ut);
1341  #else /* mingw */
1342  tptr = gmtime(&ut);
1343  #endif
1344 #else
1345  gmtime_r(&ut, tptr);
1346 #endif
1347  tptr->tm_isdst = -1;
1348  lt = mktime(tptr);
1349 
1350  /* Calls "difftime" to obtain the resulting difference in seconds,
1351  * because "time_t" is an opaque type, per the C standard. */
1352  gmt_offset = (l_int32) difftime(ut, lt);
1353  if (gmt_offset > 0)
1354  sep = '+';
1355  else if (gmt_offset < 0)
1356  sep = '-';
1357  relh = L_ABS(gmt_offset) / 3600;
1358  relm = (L_ABS(gmt_offset) % 3600) / 60;
1359 
1360 #ifdef _WIN32
1361  #ifdef _MSC_VER
1362  localtime_s(tptr, &ut);
1363  #else /* mingw */
1364  tptr = localtime(&ut);
1365  #endif
1366 #else
1367  localtime_r(&ut, tptr);
1368 #endif
1369  strftime(buf, sizeof(buf), "%Y%m%d%H%M%S", tptr);
1370  sprintf(buf + 14, "%c%02d'%02d'", sep, relh, relm);
1371  return stringNew(buf);
1372 }
l_ok fileCorruptByMutation(const char *filein, l_float32 loc, l_float32 size, const char *fileout)
fileCorruptByMutation()
Definition: utils1.c:542
l_ok filesAreIdentical(const char *fname1, const char *fname2, l_int32 *psame)
filesAreIdentical()
Definition: utils1.c:333
l_ok fileReplaceBytes(const char *filein, l_int32 start, l_int32 nbytes, l_uint8 *newdata, size_t newsize, const char *fileout)
fileReplaceBytes()
Definition: utils1.c:603
l_float32 stopWallTimer(L_WALLTIMER **ptimer)
stopWallTimer()
Definition: utils1.c:1284
void startTimer(void)
startTimer(), stopTimer()
Definition: utils1.c:1041
void * returnErrorPtr(const char *msg, const char *procname, void *pval)
returnErrorPtr()
Definition: utils1.c:229
l_ok l_hashStringToUint64Fast(const char *str, l_uint64 *phash)
l_hashStringToUint64Fast()
Definition: utils1.c:771
l_ok genRandomIntOnInterval(l_int32 start, l_int32 end, l_int32 seed, l_int32 *pval)
genRandomIntOnInterval()
Definition: utils1.c:659
L_WALLTIMER * startWallTimer(void)
startWallTimer()
Definition: utils1.c:1268
void lept_stderr(const char *fmt,...)
lept_stderr()
Definition: utils1.c:306
l_ok lept_isPrime(l_uint64 n, l_int32 *pis_prime, l_uint32 *pfactor)
lept_isPrime()
Definition: utils1.c:896
void leptSetStderrHandler(void(*handler)(const char *))
leptSetStderrHandler()
Definition: utils1.c:280
char * l_getFormattedDate(void)
l_getFormattedDate()
Definition: utils1.c:1319
l_float32 returnErrorFloat(const char *msg, const char *procname, l_float32 fval)
returnErrorFloat()
Definition: utils1.c:211
l_ok findNextLargerPrime(l_int32 start, l_uint32 *pprime)
findNextLargerPrime()
Definition: utils1.c:861
l_ok fileCorruptByDeletion(const char *filein, l_float32 loc, l_float32 size, const char *fileout)
fileCorruptByDeletion()
Definition: utils1.c:478
LEPT_DLL l_int32 LeptMsgSeverity
Definition: utils1.c:119
l_ok l_hashStringToUint64(const char *str, l_uint64 *phash)
l_hashStringToUint64()
Definition: utils1.c:732
void l_getCurrentTime(l_int32 *sec, l_int32 *usec)
l_getCurrentTime()
Definition: utils1.c:1107
L_TIMER startTimerNested(void)
startTimerNested(), stopTimerNested()
Definition: utils1.c:1073
l_int32 setMsgSeverity(l_int32 newsev)
setMsgSeverity()
Definition: utils1.c:143
l_int32 lept_roundftoi(l_float32 fval)
lept_roundftoi()
Definition: utils1.c:700
l_uint32 convertGrayCodeToInt(l_uint32 val)
convertGrayCodeToInt()
Definition: utils1.c:960
char * getLeptonicaVersion(void)
getLeptonicaVersion()
Definition: utils1.c:982
l_int32 returnErrorInt(const char *msg, const char *procname, l_int32 ival)
returnErrorInt()
Definition: utils1.c:193
l_uint32 convertIntToGrayCode(l_uint32 val)
convertIntToGrayCode()
Definition: utils1.c:947
l_ok l_hashFloat64ToUint64(l_float64 val, l_uint64 *phash)
l_hashFloat64ToUint64()
Definition: utils1.c:837
l_ok l_hashPtToUint64(l_int32 x, l_int32 y, l_uint64 *phash)
l_hashPtToUint64()
Definition: utils1.c:807
size_t nbytesInFile(const char *filename)
nbytesInFile()
Definition: utils2.c:1611
char * stringNew(const char *src)
stringNew()
Definition: utils2.c:223
l_ok l_binaryWrite(const char *filename, const char *operation, const void *data, size_t nbytes)
l_binaryWrite()
Definition: utils2.c:1569
l_uint8 * l_binaryRead(const char *filename, size_t *pnbytes)
l_binaryRead()
Definition: utils2.c:1352