Leptonica  1.83.1
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  if (!psame)
342  return ERROR_INT("&same not defined", __func__, 1);
343  *psame = 0;
344  if (!fname1 || !fname2)
345  return ERROR_INT("both names not defined", __func__, 1);
346 
347  nbytes1 = nbytesInFile(fname1);
348  nbytes2 = nbytesInFile(fname2);
349  if (nbytes1 != nbytes2)
350  return 0;
351 
352  if ((array1 = l_binaryRead(fname1, &nbytes1)) == NULL)
353  return ERROR_INT("array1 not read", __func__, 1);
354  if ((array2 = l_binaryRead(fname2, &nbytes2)) == NULL) {
355  LEPT_FREE(array1);
356  return ERROR_INT("array2 not read", __func__, 1);
357  }
358  same = 1;
359  for (i = 0; i < nbytes1; i++) {
360  if (array1[i] != array2[i]) {
361  same = 0;
362  break;
363  }
364  }
365  LEPT_FREE(array1);
366  LEPT_FREE(array2);
367  *psame = same;
368 
369  return 0;
370 }
371 
372 
373 /*--------------------------------------------------------------------------*
374  * 16 and 32 bit byte-swapping on big endian and little endian machines *
375  *--------------------------------------------------------------------------*
376  * *
377  * These are typically used for I/O conversions: *
378  * (1) endian conversion for data that was read from a file *
379  * (2) endian conversion on data before it is written to a file *
380  *--------------------------------------------------------------------------*/
381 
382 /*--------------------------------------------------------------------*
383  * 16-bit byte swapping *
384  *--------------------------------------------------------------------*/
385 #ifdef L_BIG_ENDIAN
386 
387 l_uint16
388 convertOnBigEnd16(l_uint16 shortin)
389 {
390  return ((shortin << 8) | (shortin >> 8));
391 }
392 
393 l_uint16
394 convertOnLittleEnd16(l_uint16 shortin)
395 {
396  return shortin;
397 }
398 
399 #else /* L_LITTLE_ENDIAN */
400 
401 l_uint16
402 convertOnLittleEnd16(l_uint16 shortin)
403 {
404  return ((shortin << 8) | (shortin >> 8));
405 }
406 
407 l_uint16
408 convertOnBigEnd16(l_uint16 shortin)
409 {
410  return shortin;
411 }
412 
413 #endif /* L_BIG_ENDIAN */
414 
415 
416 /*--------------------------------------------------------------------*
417  * 32-bit byte swapping *
418  *--------------------------------------------------------------------*/
419 #ifdef L_BIG_ENDIAN
420 
421 l_uint32
422 convertOnBigEnd32(l_uint32 wordin)
423 {
424  return ((wordin << 24) | ((wordin << 8) & 0x00ff0000) |
425  ((wordin >> 8) & 0x0000ff00) | (wordin >> 24));
426 }
427 
428 l_uint32
429 convertOnLittleEnd32(l_uint32 wordin)
430 {
431  return wordin;
432 }
433 
434 #else /* L_LITTLE_ENDIAN */
435 
436 l_uint32
437 convertOnLittleEnd32(l_uint32 wordin)
438 {
439  return ((wordin << 24) | ((wordin << 8) & 0x00ff0000) |
440  ((wordin >> 8) & 0x0000ff00) | (wordin >> 24));
441 }
442 
443 l_uint32
444 convertOnBigEnd32(l_uint32 wordin)
445 {
446  return wordin;
447 }
448 
449 #endif /* L_BIG_ENDIAN */
450 
451 
452 /*---------------------------------------------------------------------*
453  * File corruption and byte replacement operations *
454  *---------------------------------------------------------------------*/
475 l_ok
476 fileCorruptByDeletion(const char *filein,
477  l_float32 loc,
478  l_float32 size,
479  const char *fileout)
480 {
481 l_int32 i, locb, sizeb, rembytes;
482 size_t inbytes, outbytes;
483 l_uint8 *datain, *dataout;
484 
485  if (!filein || !fileout)
486  return ERROR_INT("filein and fileout not both specified", __func__, 1);
487  if (loc < 0.0 || loc >= 1.0)
488  return ERROR_INT("loc must be in [0.0 ... 1.0)", __func__, 1);
489  if (size <= 0.0)
490  return ERROR_INT("size must be > 0.0", __func__, 1);
491  if (loc + size > 1.0)
492  size = 1.0 - loc;
493 
494  datain = l_binaryRead(filein, &inbytes);
495  locb = (l_int32)(loc * inbytes + 0.5);
496  locb = L_MIN(locb, inbytes - 1);
497  sizeb = (l_int32)(size * inbytes + 0.5);
498  sizeb = L_MAX(1, sizeb);
499  sizeb = L_MIN(sizeb, inbytes - locb); /* >= 1 */
500  L_INFO("Removed %d bytes at location %d\n", __func__, sizeb, locb);
501  rembytes = inbytes - locb - sizeb; /* >= 0; to be copied, after excision */
502 
503  outbytes = inbytes - sizeb;
504  dataout = (l_uint8 *)LEPT_CALLOC(outbytes, 1);
505  for (i = 0; i < locb; i++)
506  dataout[i] = datain[i];
507  for (i = 0; i < rembytes; i++)
508  dataout[locb + i] = datain[locb + sizeb + i];
509  l_binaryWrite(fileout, "w", dataout, outbytes);
510 
511  LEPT_FREE(datain);
512  LEPT_FREE(dataout);
513  return 0;
514 }
515 
516 
537 l_ok
538 fileCorruptByMutation(const char *filein,
539  l_float32 loc,
540  l_float32 size,
541  const char *fileout)
542 {
543 l_int32 i, locb, sizeb;
544 size_t bytes;
545 l_uint8 *data;
546 
547  if (!filein || !fileout)
548  return ERROR_INT("filein and fileout not both specified", __func__, 1);
549  if (loc < 0.0 || loc >= 1.0)
550  return ERROR_INT("loc must be in [0.0 ... 1.0)", __func__, 1);
551  if (size <= 0.0)
552  return ERROR_INT("size must be > 0.0", __func__, 1);
553  if (loc + size > 1.0)
554  size = 1.0 - loc;
555 
556  data = l_binaryRead(filein, &bytes);
557  locb = (l_int32)(loc * bytes + 0.5);
558  locb = L_MIN(locb, bytes - 1);
559  sizeb = (l_int32)(size * bytes + 0.5);
560  sizeb = L_MAX(1, sizeb);
561  sizeb = L_MIN(sizeb, bytes - locb); /* >= 1 */
562  L_INFO("Randomizing %d bytes at location %d\n", __func__, sizeb, locb);
563 
564  /* Make an array of random bytes and do the substitution */
565  for (i = 0; i < sizeb; i++) {
566  data[locb + i] =
567  (l_uint8)(255.9 * ((l_float64)rand() / (l_float64)RAND_MAX));
568  }
569 
570  l_binaryWrite(fileout, "w", data, bytes);
571  LEPT_FREE(data);
572  return 0;
573 }
574 
575 
596 l_ok
597 fileReplaceBytes(const char *filein,
598  l_int32 start,
599  l_int32 nbytes,
600  l_uint8 *newdata,
601  size_t newsize,
602  const char *fileout)
603 {
604 l_int32 i, index;
605 size_t inbytes, outbytes;
606 l_uint8 *datain, *dataout;
607 
608  if (!filein || !fileout)
609  return ERROR_INT("filein and fileout not both specified", __func__, 1);
610 
611  datain = l_binaryRead(filein, &inbytes);
612  if (start + nbytes > inbytes)
613  L_WARNING("start + nbytes > length(filein) = %zu\n", __func__, inbytes);
614 
615  if (!newdata) newsize = 0;
616  outbytes = inbytes - nbytes + newsize;
617  if ((dataout = (l_uint8 *)LEPT_CALLOC(outbytes, 1)) == NULL) {
618  LEPT_FREE(datain);
619  return ERROR_INT("calloc fail for dataout", __func__, 1);
620  }
621 
622  for (i = 0; i < start; i++)
623  dataout[i] = datain[i];
624  for (i = start; i < start + newsize; i++)
625  dataout[i] = newdata[i - start];
626  index = start + nbytes; /* for datain */
627  start += newsize; /* for dataout */
628  for (i = start; i < outbytes; i++, index++)
629  dataout[i] = datain[index];
630  l_binaryWrite(fileout, "w", dataout, outbytes);
631 
632  LEPT_FREE(datain);
633  LEPT_FREE(dataout);
634  return 0;
635 }
636 
637 
638 /*---------------------------------------------------------------------*
639  * Generate random integer in given interval *
640  *---------------------------------------------------------------------*/
650 l_ok
652  l_int32 end,
653  l_int32 seed,
654  l_int32 *pval)
655 {
656 l_float64 range;
657 
658  if (!pval)
659  return ERROR_INT("&val not defined", __func__, 1);
660  *pval = 0;
661  if (end < start)
662  return ERROR_INT("invalid range", __func__, 1);
663 
664  if (seed > 0) srand(seed);
665  range = (l_float64)(end - start + 1);
666  *pval = start + (l_int32)((l_float64)range *
667  ((l_float64)rand() / (l_float64)RAND_MAX));
668  return 0;
669 }
670 
671 
672 /*---------------------------------------------------------------------*
673  * Simple math function *
674  *---------------------------------------------------------------------*/
689 l_int32
690 lept_roundftoi(l_float32 fval)
691 {
692  return (fval >= 0.0) ? (l_int32)(fval + 0.5) : (l_int32)(fval - 0.5);
693 }
694 
695 
696 /*---------------------------------------------------------------------*
697  * 64-bit hash functions *
698  *---------------------------------------------------------------------*/
721 l_ok
722 l_hashStringToUint64(const char *str,
723  l_uint64 *phash)
724 {
725 l_uint64 hash, mulp;
726 
727  if (phash) *phash = 0;
728  if (!str || (str[0] == '\0'))
729  return ERROR_INT("str not defined or empty", __func__, 1);
730  if (!phash)
731  return ERROR_INT("&hash not defined", __func__, 1);
732 
733  mulp = 26544357894361247; /* prime, about 1/700 of the max uint64 */
734  hash = 104395301;
735  while (*str) {
736  hash += (*str++ * mulp) ^ (hash >> 7); /* shift [1...23] are ok */
737  }
738  *phash = hash ^ (hash << 37);
739  return 0;
740 }
741 
742 
758 l_ok
759 l_hashStringToUint64Fast(const char *str,
760  l_uint64 *phash)
761 {
762 l_uint64 h;
763 l_uint8 *p;
764 
765  if (phash) *phash = 0;
766  if (!str || (str[0] == '\0'))
767  return ERROR_INT("str not defined or empty", __func__, 1);
768  if (!phash)
769  return ERROR_INT("&hash not defined", __func__, 1);
770 
771  h = 0;
772  for (p = (l_uint8 *)str; *p != '\0'; p++)
773  h = 37 * h + *p; /* 37 is good prime number for this */
774  *phash = h;
775  return 0;
776 }
777 
778 
792 l_ok
794  l_int32 y,
795  l_uint64 *phash)
796 {
797  if (!phash)
798  return ERROR_INT("&hash not defined", __func__, 1);
799 
800  *phash = (l_uint64)(2173249142.3849 * x + 3763193258.6227 * y);
801  return 0;
802 }
803 
804 
820 l_ok
821 l_hashFloat64ToUint64(l_float64 val,
822  l_uint64 *phash)
823 {
824  if (!phash)
825  return ERROR_INT("&hash not defined", __func__, 1);
826  val = (val >= 0.0) ? 847019.66701 * val : -217324.91613 * val;
827  *phash = (l_uint64)val;
828  return 0;
829 }
830 
831 
832 /*---------------------------------------------------------------------*
833  * Prime finders *
834  *---------------------------------------------------------------------*/
842 l_ok
843 findNextLargerPrime(l_int32 start,
844  l_uint32 *pprime)
845 {
846 l_int32 i, is_prime;
847 
848  if (!pprime)
849  return ERROR_INT("&prime not defined", __func__, 1);
850  *pprime = 0;
851  if (start <= 0)
852  return ERROR_INT("start must be > 0", __func__, 1);
853 
854  for (i = start + 1; ; i++) {
855  lept_isPrime(i, &is_prime, NULL);
856  if (is_prime) {
857  *pprime = i;
858  return 0;
859  }
860  }
861 
862  return ERROR_INT("prime not found!", __func__, 1);
863 }
864 
865 
875 l_ok
876 lept_isPrime(l_uint64 n,
877  l_int32 *pis_prime,
878  l_uint32 *pfactor)
879 {
880 l_uint32 div;
881 l_uint64 limit, ratio;
882 
883  if (pis_prime) *pis_prime = 0;
884  if (pfactor) *pfactor = 0;
885  if (!pis_prime)
886  return ERROR_INT("&is_prime not defined", __func__, 1);
887  if (n <= 0)
888  return ERROR_INT("n must be > 0", __func__, 1);
889 
890  if (n % 2 == 0) {
891  if (pfactor) *pfactor = 2;
892  return 0;
893  }
894 
895  limit = (l_uint64)sqrt((l_float64)n);
896  for (div = 3; div < limit; div += 2) {
897  ratio = n / div;
898  if (ratio * div == n) {
899  if (pfactor) *pfactor = div;
900  return 0;
901  }
902  }
903 
904  *pis_prime = 1;
905  return 0;
906 }
907 
908 
909 /*---------------------------------------------------------------------*
910  * Gray code conversion *
911  *---------------------------------------------------------------------*/
924 l_uint32
925 convertIntToGrayCode(l_uint32 val)
926 {
927  return (val >> 1) ^ val;
928 }
929 
930 
937 l_uint32
938 convertGrayCodeToInt(l_uint32 val)
939 {
940 l_uint32 shift;
941 
942  for (shift = 1; shift < 32; shift <<= 1)
943  val ^= val >> shift;
944  return val;
945 }
946 
947 
948 /*---------------------------------------------------------------------*
949  * Leptonica version number *
950  *---------------------------------------------------------------------*/
959 char *
961 {
962 size_t bufsize = 100;
963 
964  char *version = (char *)LEPT_CALLOC(bufsize, sizeof(char));
965 
966 #ifdef _MSC_VER
967  #ifdef _USRDLL
968  char dllStr[] = "DLL";
969  #else
970  char dllStr[] = "LIB";
971  #endif
972  #ifdef _DEBUG
973  char debugStr[] = "Debug";
974  #else
975  char debugStr[] = "Release";
976  #endif
977  #ifdef _M_IX86
978  char bitStr[] = " x86";
979  #elif _M_X64
980  char bitStr[] = " x64";
981  #else
982  char bitStr[] = "";
983  #endif
984  snprintf(version, bufsize, "leptonica-%d.%d.%d (%s, %s) [MSC v.%d %s %s%s]",
985  LIBLEPT_MAJOR_VERSION, LIBLEPT_MINOR_VERSION, LIBLEPT_PATCH_VERSION,
986  __DATE__, __TIME__, _MSC_VER, dllStr, debugStr, bitStr);
987 
988 #else
989 
990  snprintf(version, bufsize, "leptonica-%d.%d.%d", LIBLEPT_MAJOR_VERSION,
991  LIBLEPT_MINOR_VERSION, LIBLEPT_PATCH_VERSION);
992 
993 #endif /* _MSC_VER */
994  return version;
995 }
996 
997 
998 /*---------------------------------------------------------------------*
999  * Timing procs *
1000  *---------------------------------------------------------------------*/
1001 #if !defined(_WIN32) && !defined(__Fuchsia__)
1002 
1003 #include <sys/time.h>
1004 #include <sys/resource.h>
1005 
1006 static struct rusage rusage_before;
1007 static struct rusage rusage_after;
1008 
1018 void
1020 {
1021  getrusage(RUSAGE_SELF, &rusage_before);
1022 }
1023 
1024 l_float32
1025 stopTimer(void)
1026 {
1027 l_int32 tsec, tusec;
1028 
1029  getrusage(RUSAGE_SELF, &rusage_after);
1030 
1031  tsec = rusage_after.ru_utime.tv_sec - rusage_before.ru_utime.tv_sec;
1032  tusec = rusage_after.ru_utime.tv_usec - rusage_before.ru_utime.tv_usec;
1033  return (tsec + ((l_float32)tusec) / 1000000.0);
1034 }
1035 
1036 
1050 L_TIMER
1052 {
1053 struct rusage *rusage_start;
1054 
1055  rusage_start = (struct rusage *)LEPT_CALLOC(1, sizeof(struct rusage));
1056  getrusage(RUSAGE_SELF, rusage_start);
1057  return rusage_start;
1058 }
1059 
1060 l_float32
1061 stopTimerNested(L_TIMER rusage_start)
1062 {
1063 l_int32 tsec, tusec;
1064 struct rusage rusage_stop;
1065 
1066  getrusage(RUSAGE_SELF, &rusage_stop);
1067 
1068  tsec = rusage_stop.ru_utime.tv_sec -
1069  ((struct rusage *)rusage_start)->ru_utime.tv_sec;
1070  tusec = rusage_stop.ru_utime.tv_usec -
1071  ((struct rusage *)rusage_start)->ru_utime.tv_usec;
1072  LEPT_FREE(rusage_start);
1073  return (tsec + ((l_float32)tusec) / 1000000.0);
1074 }
1075 
1076 
1084 void
1085 l_getCurrentTime(l_int32 *sec,
1086  l_int32 *usec)
1087 {
1088 struct timeval tv;
1089 
1090  gettimeofday(&tv, NULL);
1091  if (sec) *sec = (l_int32)tv.tv_sec;
1092  if (usec) *usec = (l_int32)tv.tv_usec;
1093 }
1094 
1095 #elif defined(__Fuchsia__) /* resource.h not implemented on Fuchsia. */
1096 
1097  /* Timer functions are used for testing and debugging, and
1098  * are stubbed out. If they are needed in the future, they
1099  * can be implemented in Fuchsia using the zircon syscall
1100  * zx_object_get_info() in ZX_INFOR_THREAD_STATS mode. */
1101 void
1102 startTimer(void)
1103 {
1104 }
1105 
1106 l_float32
1107 stopTimer(void)
1108 {
1109  return 0.0;
1110 }
1111 
1112 L_TIMER
1113 startTimerNested(void)
1114 {
1115  return NULL;
1116 }
1117 
1118 l_float32
1119 stopTimerNested(L_TIMER rusage_start)
1120 {
1121  return 0.0;
1122 }
1123 
1124 void
1125 l_getCurrentTime(l_int32 *sec,
1126  l_int32 *usec)
1127 {
1128 }
1129 
1130 #else /* _WIN32 : resource.h not implemented under Windows */
1131 
1132  /* Note: if division by 10^7 seems strange, the time is expressed
1133  * as the number of 100-nanosecond intervals that have elapsed
1134  * since 12:00 A.M. January 1, 1601. */
1135 
1136 static ULARGE_INTEGER utime_before;
1137 static ULARGE_INTEGER utime_after;
1138 
1139 void
1140 startTimer(void)
1141 {
1142 HANDLE this_process;
1143 FILETIME start, stop, kernel, user;
1144 
1145  this_process = GetCurrentProcess();
1146 
1147  GetProcessTimes(this_process, &start, &stop, &kernel, &user);
1148 
1149  utime_before.LowPart = user.dwLowDateTime;
1150  utime_before.HighPart = user.dwHighDateTime;
1151 }
1152 
1153 l_float32
1154 stopTimer(void)
1155 {
1156 HANDLE this_process;
1157 FILETIME start, stop, kernel, user;
1158 ULONGLONG hnsec; /* in units of hecto-nanosecond (100 ns) intervals */
1159 
1160  this_process = GetCurrentProcess();
1161 
1162  GetProcessTimes(this_process, &start, &stop, &kernel, &user);
1163 
1164  utime_after.LowPart = user.dwLowDateTime;
1165  utime_after.HighPart = user.dwHighDateTime;
1166  hnsec = utime_after.QuadPart - utime_before.QuadPart;
1167  return (l_float32)(signed)hnsec / 10000000.0;
1168 }
1169 
1170 L_TIMER
1171 startTimerNested(void)
1172 {
1173 HANDLE this_process;
1174 FILETIME start, stop, kernel, user;
1175 ULARGE_INTEGER *utime_start;
1176 
1177  this_process = GetCurrentProcess();
1178 
1179  GetProcessTimes (this_process, &start, &stop, &kernel, &user);
1180 
1181  utime_start = (ULARGE_INTEGER *)LEPT_CALLOC(1, sizeof(ULARGE_INTEGER));
1182  utime_start->LowPart = user.dwLowDateTime;
1183  utime_start->HighPart = user.dwHighDateTime;
1184  return utime_start;
1185 }
1186 
1187 l_float32
1188 stopTimerNested(L_TIMER utime_start)
1189 {
1190 HANDLE this_process;
1191 FILETIME start, stop, kernel, user;
1192 ULARGE_INTEGER utime_stop;
1193 ULONGLONG hnsec; /* in units of 100 ns intervals */
1194 
1195  this_process = GetCurrentProcess ();
1196 
1197  GetProcessTimes (this_process, &start, &stop, &kernel, &user);
1198 
1199  utime_stop.LowPart = user.dwLowDateTime;
1200  utime_stop.HighPart = user.dwHighDateTime;
1201  hnsec = utime_stop.QuadPart - ((ULARGE_INTEGER *)utime_start)->QuadPart;
1202  LEPT_FREE(utime_start);
1203  return (l_float32)(signed)hnsec / 10000000.0;
1204 }
1205 
1206 void
1207 l_getCurrentTime(l_int32 *sec,
1208  l_int32 *usec)
1209 {
1210 ULARGE_INTEGER utime, birthunix;
1211 FILETIME systemtime;
1212 LONGLONG birthunixhnsec = 116444736000000000; /*in units of 100 ns */
1213 LONGLONG usecs;
1214 
1215  GetSystemTimeAsFileTime(&systemtime);
1216  utime.LowPart = systemtime.dwLowDateTime;
1217  utime.HighPart = systemtime.dwHighDateTime;
1218 
1219  birthunix.LowPart = (DWORD) birthunixhnsec;
1220  birthunix.HighPart = birthunixhnsec >> 32;
1221 
1222  usecs = (LONGLONG) ((utime.QuadPart - birthunix.QuadPart) / 10);
1223 
1224  if (sec) *sec = (l_int32) (usecs / 1000000);
1225  if (usec) *usec = (l_int32) (usecs % 1000000);
1226 }
1227 
1228 #endif
1229 
1230 
1245 L_WALLTIMER *
1247 {
1248 L_WALLTIMER *timer;
1249 
1250  timer = (L_WALLTIMER *)LEPT_CALLOC(1, sizeof(L_WALLTIMER));
1251  l_getCurrentTime(&timer->start_sec, &timer->start_usec);
1252  return timer;
1253 }
1254 
1261 l_float32
1263 {
1264 l_int32 tsec, tusec;
1265 L_WALLTIMER *timer;
1266 
1267  if (!ptimer)
1268  return (l_float32)ERROR_FLOAT("&timer not defined", __func__, 0.0);
1269  timer = *ptimer;
1270  if (!timer)
1271  return (l_float32)ERROR_FLOAT("timer not defined", __func__, 0.0);
1272 
1273  l_getCurrentTime(&timer->stop_sec, &timer->stop_usec);
1274  tsec = timer->stop_sec - timer->start_sec;
1275  tusec = timer->stop_usec - timer->start_usec;
1276  LEPT_FREE(timer);
1277  *ptimer = NULL;
1278  return (tsec + ((l_float32)tusec) / 1000000.0);
1279 }
1280 
1281 
1294 char *
1296 {
1297 char buf[128] = "", sep = 'Z';
1298 l_int32 gmt_offset, relh, relm;
1299 time_t ut, lt;
1300 struct tm Tm;
1301 struct tm *tptr = &Tm;
1302 
1303  ut = time(NULL);
1304 
1305  /* This generates a second "time_t" value by calling "gmtime" to
1306  fill in a "tm" structure expressed as UTC and then calling
1307  "mktime", which expects a "tm" structure expressed as the
1308  local time. The result is a value that is offset from the
1309  value returned by the "time" function by the local UTC offset.
1310  "tm_isdst" is set to -1 to tell "mktime" to determine for
1311  itself whether DST is in effect. This is necessary because
1312  "gmtime" always sets "tm_isdst" to 0, which would tell
1313  "mktime" to presume that DST is not in effect. */
1314 #ifdef _WIN32
1315  #ifdef _MSC_VER
1316  gmtime_s(tptr, &ut);
1317  #else /* mingw */
1318  tptr = gmtime(&ut);
1319  #endif
1320 #else
1321  gmtime_r(&ut, tptr);
1322 #endif
1323  tptr->tm_isdst = -1;
1324  lt = mktime(tptr);
1325 
1326  /* Calls "difftime" to obtain the resulting difference in seconds,
1327  * because "time_t" is an opaque type, per the C standard. */
1328  gmt_offset = (l_int32) difftime(ut, lt);
1329  if (gmt_offset > 0)
1330  sep = '+';
1331  else if (gmt_offset < 0)
1332  sep = '-';
1333  relh = L_ABS(gmt_offset) / 3600;
1334  relm = (L_ABS(gmt_offset) % 3600) / 60;
1335 
1336 #ifdef _WIN32
1337  #ifdef _MSC_VER
1338  localtime_s(tptr, &ut);
1339  #else /* mingw */
1340  tptr = localtime(&ut);
1341  #endif
1342 #else
1343  localtime_r(&ut, tptr);
1344 #endif
1345  strftime(buf, sizeof(buf), "%Y%m%d%H%M%S", tptr);
1346  sprintf(buf + 14, "%c%02d'%02d'", sep, relh, relm);
1347  return stringNew(buf);
1348 }
l_ok fileCorruptByMutation(const char *filein, l_float32 loc, l_float32 size, const char *fileout)
fileCorruptByMutation()
Definition: utils1.c:538
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:597
l_float32 stopWallTimer(L_WALLTIMER **ptimer)
stopWallTimer()
Definition: utils1.c:1262
void startTimer(void)
startTimer(), stopTimer()
Definition: utils1.c:1019
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:759
l_ok genRandomIntOnInterval(l_int32 start, l_int32 end, l_int32 seed, l_int32 *pval)
genRandomIntOnInterval()
Definition: utils1.c:651
L_WALLTIMER * startWallTimer(void)
startWallTimer()
Definition: utils1.c:1246
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:876
void leptSetStderrHandler(void(*handler)(const char *))
leptSetStderrHandler()
Definition: utils1.c:280
char * l_getFormattedDate(void)
l_getFormattedDate()
Definition: utils1.c:1295
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:843
l_ok fileCorruptByDeletion(const char *filein, l_float32 loc, l_float32 size, const char *fileout)
fileCorruptByDeletion()
Definition: utils1.c:476
LEPT_DLL l_int32 LeptMsgSeverity
Definition: utils1.c:119
l_ok l_hashStringToUint64(const char *str, l_uint64 *phash)
l_hashStringToUint64()
Definition: utils1.c:722
void l_getCurrentTime(l_int32 *sec, l_int32 *usec)
l_getCurrentTime()
Definition: utils1.c:1085
L_TIMER startTimerNested(void)
startTimerNested(), stopTimerNested()
Definition: utils1.c:1051
l_int32 setMsgSeverity(l_int32 newsev)
setMsgSeverity()
Definition: utils1.c:143
l_int32 lept_roundftoi(l_float32 fval)
lept_roundftoi()
Definition: utils1.c:690
l_uint32 convertGrayCodeToInt(l_uint32 val)
convertGrayCodeToInt()
Definition: utils1.c:938
char * getLeptonicaVersion(void)
getLeptonicaVersion()
Definition: utils1.c:960
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:925
l_ok l_hashFloat64ToUint64(l_float64 val, l_uint64 *phash)
l_hashFloat64ToUint64()
Definition: utils1.c:821
l_ok l_hashPtToUint64(l_int32 x, l_int32 y, l_uint64 *phash)
l_hashPtToUint64()
Definition: utils1.c:793
size_t nbytesInFile(const char *filename)
nbytesInFile()
Definition: utils2.c:1559
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:1519
l_uint8 * l_binaryRead(const char *filename, size_t *pnbytes)
l_binaryRead()
Definition: utils2.c:1310